[Lazarus] Better implementation of GetTickcount using clock_gettime

Luca Olivetti luca at wetron.es
Wed Apr 2 09:47:45 CEST 2014


El 02/04/14 09:08, Michael Van Canneyt ha escrit:
> 
> 
> On Tue, 1 Apr 2014, Mattias Gaertner wrote:
> 
>> On Tue, 01 Apr 2014 12:20:53 +0200
>> Luca Olivetti <luca at wetron.es> wrote:
>>
>>> [...]
>>> function GetTickCount64: QWord;
>>> var
>>>   tp: timespec;
>>> begin
>>>   clock_gettime(CLOCK_MONOTONIC, @tp);
>>>   Result := (Int64(tp.tv_sec) * 1000) + (tp.tv_nsec div 1000000);
>>> end;
>>> [...]
>>
>> Thanks. GetTickCount64 now uses it on Linux.
> 
> The implementation in Sysutils now does so too, and uses a fallback
> using gettimeofday.

I checked the revision and it looks wrong: fpgettimeofday uses a
TTimeVal (resolution microseconds), while clock_gettime uses TTimeSpec
(resolution nanoseconds). A suitable (I think) fallback could be
CLOCK_REALTIME, e.g.


var
  ts:TTimeSpec;
begin
{$IFDEF HAVECLOCKGETTIME}
  if clock_gettime(CLOCK_MONOTONIC, @ts)<0 then
{$ENDIF}
  clock_gettime(CLOCK_REALTIME, at ts);
  Result := (Int64(ts.tv_sec) * 1000) + (ts.tv_nsec div 1000000);
end;

The problem is that the clock_gettime function is only defined for linux
(isn't it supposed to be available in any posix system?) so maybe:

var
  tv:TTimeVal;
{$IFDEF HAVECLOCKGETTIME}
  ts:TTimeSpec;
{$ENDIF}
begin
{$IFDEF HAVECLOCKGETTIME}
  if clock_gettime(CLOCK_MONOTONIC, @ts)=0 then
  begin
    Result := (Int64(ts.tv_sec) * 1000) + (ts.tv_nsec div 1000000);
    exit;
  end;
{$ENDIF}
  clock_gettime(CLOCK_REALTIME, at tv);
  Result := (Int64(tv.tv_sec) * 1000) + (tv.tv_usec div 1000);
end;


Btw, in theory CLOCK_MONOTONIC_RAW should be even better, though it's
only available from linux 2.6.28

var
  tv:TTimeVal;
{$IFDEF HAVECLOCKGETTIME}
  r:cint;
  ts:TTimeSpec;
{$ENDIF}
begin
{$IFDEF HAVECLOCKGETTIME}
  r:=clock_gettime(CLOCK_MONOTONIC_RAW, @ts);
  if r<0 then
    r:=clock_gettime(CLOCK_MONOTONIC, @ts)=0;
  if r=0 then
  begin
    Result := (Int64(ts.tv_sec) * 1000) + (ts.tv_nsec div 1000000);
    exit;
  end;
{$ENDIF}
  clock_gettime(CLOCK_REALTIME, at tv);
  Result := (Int64(tv.tv_sec) * 1000) + (tv.tv_usec div 1000);
end;


and then there's CLOCK_MONOTONIC_COARSE......


Bye
-- 
Luca Olivetti
Wetron Automation Technology http://www.wetron.es
Tel. +34 935883004  Fax +34 935883007




More information about the Lazarus mailing list