Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2014-07

Epiktimer elapsed = negative value

8 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Anthony Tekatch

Occasionally I get a negative "Elapsed" value using EpikTimer. Here is my code:

    RunWhile:=True;
    DelayInSeconds := 1.00; //Store every x seconds
    while RunWhile do begin
      ET.Clear;
      ET.Start;
      while (ET.Elapsed  < DelayInSeconds) and RunWhile do begin
        ET.SystemSleep(10);
        writeln('ET.Elapsed=',ET.Elapsed);
        if (ET.Elapsed < 0 ) then RunWhile:=False;
      end;
      LogOneReading(); //Store successive readings (my code)
    end;

This is the output after about 5 to 20 minutes where you can see the last line showing the negative value:
...
ET.Elapsed= 4.4526500000000000E-0001
ET.Elapsed= 4.5535900000000000E-0001
ET.Elapsed= 4.6544100000000000E-0001
ET.Elapsed=-4.2944917280000000E+0003

I did install EpikTimer from the latest github.

I am using Linux, and had to add "linux" to the uses clause to prevent the clock_gettime() error.

Thanks for looking,
Anthony

Reply by email

Michael Schnell
to Anthony Tekatch
Anthony Tekatch wrote
Occasionally I get a negative "Elapsed" value using EpikTimer.

Depending on the platform, the fpc release and the EpikTimer release, the timer might use the "time of day" value instead the "hardware clocks elapsed" value.

The time of day might be updated in the background by a process reading an Internet clock or something like this.

So the value might be hopping around.

-Michael

Reply by email

Michael Schnell
to Michael Schnell

Moreover:

Even if the CPU's hardware tick counter is used, in a multi-CPU system, each CPU might have it's own counter and those are not guaranteed to be in sync. as the OS might move the program from one CPU to the other, this method does not seem to be safe, either.

-Michael

Reply by email

Giuliano Colla
to Michael Schnell

Il 07/07/2014 11:28, Michael Schnell ha scritto:

Show quoted text 7 lines
Moreover: Even if the CPU's hardware tick counter is used, in a multi-CPU system, each CPU might have it's own counter and those are not guaranteed to be in sync. as the OS might move the program from one CPU to the other, this method does not seem to be safe, either.

I don't know Epiktimer implementation, but I have some experience about Linux timers, because I've implemented several "real time" schedulers on top of Linux kernel.
The POSIX clock_gettime() function provides a parameter to specify which timer should be used. From clock_gettime man page:

Show quoted text 24 lines
clock_gettime returns the current timespec value of tp for the specific clock, which_clock. The values that clockid_t currently supports for POSIX.1b timers, as defined in include/linux/time.h, are: CLOCK_REALTIME Systemwide realtime clock. CLOCK_MONOTONIC Represents monotonic time. Cannot be set. CLOCK_PROCESS_CPUTIME_ID High resolution per-process timer. CLOCK_THREAD_CPUTIME_ID Thread-specific timer. CLOCK_REALTIME_HR High resolution version of CLOCK_REALTIME. CLOCK_MONOTONIC_HR High resolution version of CLOCK_MONOTONIC.

In my C code a simple function like this:

Show quoted text 6 lines
struct timespec curr_time () { struct timespec ts; if (clock_gettime(CLOCK_REALTIME, &ts) == -1) handle_error("clock_gettime"); return (ts); }

always return correct time. Pascal code should bind to the proper libc function. Maybe CLOCK_MONOTONIC or CLOCK_MONOTONIC_HR is even safer.

Giuliano

Reply by email

Michael Schnell
to Giuliano Colla
Giuliano Colla wrote
The POSIX clock_gettime() function provides a parameter to specify which timer should be used. From clock_gettime man page:

With some Linux archs and revisions, this function is available via (low latency/low overhead) vDSO calls.

Unfortunately there seem to be arch where an "independent" (e.g. monotonic) timing clock can't be provided and in fact vDSO seem not to be "ubiquitous enough" (nor really decently on the enhancement agenda of the Linux Kernel Team) for trying to use it with a would-be multi-arch library (i.e. any commonly usable library for fpc/Lazarus).

I did some successful experiments with vDSO in fpc, hoping to be able to improve EpikTimer, but gave up due to the said facts.

-Michael

Reply by email

Anthony Tekatch
to Michael Schnell: Moreover: Even if the CPU's hardware tick counter is used, in a multi-CPU system, each…
Michael Schnell wrote 6 lines
Moreover: Even if the CPU's hardware tick counter is used, in a multi-CPU system, each CPU might have it's own counter and those are not guaranteed to be in sync. as the OS might move the program from one CPU to the other, this method does not seem to be safe, either.

OK, thanks for the details.
From my initial measurements, the elapsed time jumped on its own from 465ms to -4294 seconds:
ET.Elapsed= 4.6544100000000000E-0001
ET.Elapsed=-4.2944917280000000E+0003
That is very close to 12 hours. My test showed that this could happen within about 30 minutes of starting at any time of day.

I only really needed something to trigger once per second (on the second would be nice), but it needs to be reliable and multiplatform. For now I will just watch the datetime clock for changes as follows:

     oldsec:=secondof(now);
     while RunWhile do begin
       while oldsec=secondof(now) do begin
             sleep(10);
       end;
       oldsec:=secondof(now);
       LogOneReading(); //Store successive readings (my code)
    end;

Thanks,
Anthony

Reply by email

Anthony Tekatch
to Michael Schnell
Michael Schnell wrote
This might be correct in a worker thread. In the main thread it usually is a bad idea to do "sleep" or any sort of polling..

Agreed, polling is bad, so I did this instead:

     while RunWhile do begin
           sleep(1000 - MilliSecondOf(Now));
           LogOneReading(); //Store successive readings (my code)
     end;

Reply by email