How to use sem_timedwait?
Konstantin Belousov
kostikbel at gmail.com
Thu Dec 15 11:20:58 UTC 2016
On Wed, Dec 14, 2016 at 09:35:32PM -0700, Ian Lepore wrote:
> On Wed, 2016-12-14 at 21:18 -0700, Ian Lepore wrote:
> > On Thu, 2016-12-15 at 01:29 +0100, Goran Meki? wrote:
> > >
> > > On Wed, Dec 14, 2016 at 01:56:00PM -0700, Ian Lepore wrote:
> > > > [...]
> >
> > Making a guess here: Is your actual goal to wake up periodically
> > with the period between wakeups as accurate as possible? If so, a
> > better mechanism might be to use kqueue(2)/kevent(2)
> > with EVFILT_TIMER events. With EVFILT_TIMER events, the wakeups are
> > scheduled as if aligned to a grid -- even if one wakeup is a bit late
> > due to system workload, the next wakeup after it will still be
> > properly aligned to the original grid. For example, if you ask for a
> > wakeup once per millisecond and some wake happens after 1.2mS, the
> > next wakeup will be .8mS after that; the phase of the wakeups doesn't
> > shift over time.
Well, this can be alternatively explained as the statement that the
timeouts are scheduled to execute at the absolute times, instead of
specifying offsets from the current moment. With such formulation, it is
obvious that userspace may do the same, calculating the next absolute
time based on previous desired moment + offset, instead of current time
+ offset. sem_timedwait(2) requests timeouts in CLOCK_REALTIME base.
Of course, kqueue(2) timers resets are less expensive since all this happens
in the callout callback in kernel.
>
> I just dug up some old source code for testing kevent timers, included
> below. Good news and bad news... The good news is that it works
> perfectly on an arm system running -current:
>
> root at imx6 :~ # ./kevent_evfilt_timer
> nsec = 10000058742 for 10000 loops of 1000000 nsec
>
> The extra 58uS is fixed overhead for getting the ending time; if the
> loop runs for 100 seconds instead of 10 the extra time is still 55-
> 60uS.
>
> The bad news is that it doesn't work right on amd64 running 10-stable:
>
> revolution > ./kevent_evfilt_timer
> nsec = 9313236220 for 10000 loops of 1000000 nsec
>
> I don't have any other x86 systems handy to test it on right now, but
> it's disturbing that 10 seconds worth of 1mS sleeps takes less than 10
> seconds. A strange thing here is that the *ratio* of the undersleeping
> is fixed, running the loop for 100 seconds instead of 10 gives:
>
> revolution > ./kevent_evfilt_timer
> nsec = 93132267106 for 100000 loops of 1000000 nsec
What are timecounter and eventcounter used on this machine ?
Also please show first 20 lines of the dmesg, where CPU identification
is performed.
I checked on two machines, one running 11 and using HPET for events:
nsec = 10000091075 for 10000 loops of 1000000 nsec
another running HEAD and using LAPIC deadline:
nsec = 10000129629 for 10000 loops of 1000000 nsec
More information about the freebsd-hackers
mailing list