nanosleep.c remarks

Pavel Pisa pisa at cmp.felk.cvut.cz
Mon Aug 1 19:51:02 UTC 2016


Hello Gedare

On Monday 01 of August 2016 17:21:14 Gedare Bloom wrote:
> On Mon, Aug 1, 2016 at 1:18 AM, Sebastian Huber
> It would be good to add some test cases calling clock_settime() and
> delivering signals while a thread nanosleep()s. I don't know that we
> have those cases tested yet.
>
> The rmtp is calculated only in consideration of elapsed score ticks.
> Maybe it would be better to call the clock functions using the
> clock_id.

I would like that approach much more.

The concept

int clock_nanosleep(
  clockid_t               clock_id,
  int                     flags,
  const struct timespec  *rqtp,
  struct timespec        *rmtp
)
{
  struct timespec  rqt = *rqtp;
  struct timespec startt;

  checks ...

  if ( ( rmtp != NULL ) || !( flags & TIMER_ABSTIME ) ) {
     clock_gettime(clk_id, &startt)
     if ( !( flags & TIMER_ABSTIME ) ) {
        timespecadd(&rqt, &startt);
     }
  }

  sleep until ABS rqt on clock_id,  WATCHDOG_REALTIME or WATCHDOG_MONOTONIC

  if ( rmtp != NULL ) {
    if ( timeout ) {
      struct timespec stopt;
      clock_gettime(clk_id, &rtm);
      timespecsub(&rtm, &startt);
      *rtmp = rtm;
    } else {
      rmtp->tv_sec = 0;
      rmtp->tv_nsec = 0;
    }
  }
}

I think that this has no bigger overhead than actual implementation,
no conversion in this part of the code. It is prepared for high resolution
timers and even without these it provides precise remaining time information
so prevents rounding errors etc.

As for 

  sleep until ABS rqt on clock_id,  WATCHDOG_REALTIME or WATCHDOG_MONOTONIC

I think that both timer queues used for POSIX related time operations
should work on same time resolution and same mechanism.

If we can afford to lose tick based queue then I would not regret its
killing, simply one queue for REALTIME one for MONOTONIC. The same
code same resolution same operations and ready for high resolution
timer support. This requires only to reprogram timer (compare value
for free running counter, initial count for single shot when time
source is separate) each time when the first timer on any queue changes
(use earlier from both/all).

If the queues are kept in compact timespec or bintime (I like that 64-bit
int + 64-bit fract but it is quite huge) then processing at HW timer
interrupt (today the tick) only needs to retrieve MONOTONIC time
process MONOTONIC queue add actual MONOTONIC to REALTIME offset
and process REALTIME queue expires. Then setup new tick or reprogram
for high resolution.

Only problem (I see for now) is that queue based on ticks is probably
required to stay. One option is to simulate it by MONOTONIC but with
scale adjustment, it can result in unexpected behavior (two tick coalesced
or one skipped). So if the tick based timing should be preserved
then third queue is required unfortuantelly. In the long term,
rough precision queue mechanisms with lower premature timer removal
cost can worth its existence. See the LWN article how Linux optimizes
timeouts performance (code actually merged to 4.8) by sacrificing 
timeouts precision

  http://lwn.net/Articles/646950/

On the other hand, Linux provides high resolution timers at nanosecond
"precision"/resolution (in the fact, precision is artificially lowered
and API allows even ranges specification to ensure that system is not
block by too many interrupts with minimal time distance).

As for the formats, I have read BSD timecounters papers and I like
the concept. May it be 10 timehands take too much memory for small systems.
Does this RTEMS limit to two or three for UP?

As for the format, linear/binary 64+64 is really nice and seem to be quite
effective for conversion to and from timespec. But arithmetic
for fractions and addition is quite huge. I think that 64-bits has
to be enough for timers/events for centuries (time measurement is
another case). If I think about quite often MONOTONIC + offset
to REALTIME conversion then compacted 34+30 is usable but has some
overhead. May it be 34+30 binary can work quite well. Resolution is not
integer multiple/fraction of 1 ns, but for timers it is not
problem. Conversion from tiemspec requires 32 * 32 -> 64 multiply + shr,
conversion back (if required - not so probable) should suffice with the same.

Compacted is worse for computation at tick or high resolution timer
fire time, but insertion of watchdogs is cheaper.

Anyway, I understand that all this timers discussion is in the theoretic level
now. But I hope that Gedare's and my clock_nanosleep with clock_gettime
proposal is future proof and conversion to non-optimal ticks for MONOTONIC
is the last step which can be easily changed to adjust for possible
future changes in underlaying code.

> > This function is probably superfluous now due to the timekeeping via the
> > FreeBSD timecounters. We tried to keep the existing behaviour during the
> > introduction of the FreeBSD timecounters. However, some parts of the
> > POSIX implementation in RTEMS are not according to POSIX. This must be
> > fixed step by step (its not on my current TODO list).
>
> I have a small budget remaining for POSIX work. However, I am focusing
> on putting together some mman interfaces. If there is a
> straightforward coding task for switching away from this
> _Timespec_From_ticks I might be able to get it done, but right now I
> don't know what it takes.

I fully understand. I am totally over my lifetime
budget these holidays to make some progress of RTEMS projects
which I hope that worth to move forward.

> >> I have mostly lost track in the call chain there.
> >> bintime2timespec is provided by NewLib as part of BSD time
> >> framework introduction
> >>
> >> https://devel.rtems.org/ticket/2271
> >> https://www.daemon-systems.org/man/timecounter.9.html
>
> You may also like http://phk.freebsd.dk/pubs/timecounter.pdf

I have found it and read on Saturday already.

> >> where seconds decrement seems suspicious to me.
> >
> > For FreeBSD compatibility the uptime starts with one second. For RTEMS
> > compatibility the uptime starts at zero.
>
> Yeah, we had this discussion before. Possibly it makes sense to add a
> brief comment there for clarity in the code.

OK. Comment in the place would be great.

> >> General rule for POSIX systems is that CLOCK_MONOTONIC and
> >> CLOCK_REALTIME scaling is done in sync only the base and
> >> step corrections are applied to CLOCK_REALTIME only.
> >> But there seem to be two relatively independed paths
> >> in the actual sources.
>
> The CLOCK_MONOTONIC uses the uptime, and the CLOCK_REALTIME uses
> uptime + boottime corrections are made by adjusting the estimated
> boottime. Every calculation using uptime is identical between the two
> clocks. I don't know if that helps address your questions about the
> relationship between those two clocks.

OK.

I am getting through all layers to rtems_timecounter_simple_install now.

> >> Other strict requirement for nanosleep is that it has
> >> to suspend task in minimum for specified time. But I am
> >> not sure if there is such round up in the actual code.
> >
> > Yes, the some test cases of the libstdc++ testsuite rely on this.
>
> I don't know if there is a rounding problem. I don't think I ran those
> tests.

I would expect that when conversion to ticks (and back) is used then
there is required extra care. Basicall you need to add (allmost) one
tick during conversion. I am not sure if it is there.

> >> This is critical if user build his/her own timers
> >> queue and premature wakeup leads to repeated abundant nanosleep
> >> calls and (in the case of round down) it can even result in busy
> >> loop for last tick cycle for example.
> >>
> >> Generally there seems to be many multiplications, divisions
> >> etc at leas in clock_nanosleep path.
>
> There are some redundant calculations since the relative_interval is
> always constructed but only used to detect a yield for CLOCK_REALTIME.
> If the WATCHDOG_RELATIVE uses a different format than score ticks, the
> calculations could be simpler.

But the watchdog queues are in absolute time and sane RT critical tasks
should use CLOCK_MONOTONIC and TIMER_ABSTIME.

By the way. I have retest my experiment with build of our LinTarget
project for RTEMS today and thanks to clock_nanosleep, I have it
run with minimal modification on RTEMS (one header and mlockall
commented out and rtems-cgf.c added for config table and init task).

   http://lintarget.sourceforge.net/

On the other hand, our RT domain applications are in range 1, 4
and 20 kHz so there has been huge overruns reports on QEMU
and I have not dared to go with tick frequency to that range.
But if sampling frequency is in range of 100 Hz or there is possibility
to use some special HW timer for fundamental sample tim
 we are getting to the usable area with RTEMS for precise motion control.

We can prepare something like this pun/toy

  http://lintarget.sourceforge.net/rpi-motor-control/index.html

or something more serious on Zynq, AM335x or AM43xx for some
of future exhibitions if there is interrest.

Best wishes,

              Pavel




More information about the devel mailing list