Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 12 Jun 2012 10:47:24 +1000 (EST)
From:      Bruce Evans <brde@optusnet.com.au>
To:        Hans Petter Selasky <hselasky@c2i.net>
Cc:        "svn-src-head@freebsd.org" <svn-src-head@freebsd.org>, "svn-src-all@freebsd.org" <svn-src-all@freebsd.org>, "src-committers@freebsd.org" <src-committers@freebsd.org>, Pawel Jakub Dawidek <pjd@freebsd.org>
Subject:   Re: svn commit: r236909 - head/sbin/hastd
Message-ID:  <20120612100540.M1359@besplex.bde.org>
In-Reply-To: <201206112221.51793.hselasky@c2i.net>
References:  <201206111921.q5BJL0jP005127@svn.freebsd.org> <20120611200507.GG1399@garage.freebsd.pl> <201206112221.51793.hselasky@c2i.net>

next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, 11 Jun 2012, Hans Petter Selasky wrote:

> On Monday 11 June 2012 22:05:07 Pawel Jakub Dawidek wrote:
>> On Mon, Jun 11, 2012 at 07:21:00PM +0000, Hans Petter Selasky wrote:
>>> Log:
>>>   Use the correct clock source when computing timeouts.
>>
>> Could you please explain why? As you can see some lines above in
>> cv_init(), we initialize condition variable with CLOCK_MONOTONIC too:
>
> Sorry, this was a mistake clearly. I will revert ASAP. Pointyhat to me.

It does seem wrong.  Perhaps CLOCK_REALTIME is correct, but the kernel
mostly uses CLOCK_MONOTONIC for timeouts.  The kernel is mostly wrong
here too.

> My test program didn't take the setattr into account.
>
> However, while at it, what is the default clock used by
> pthread_cond_timedwait(). In libusb we don't set any clock, and can we depend
> on that CLOCK_REALTIME is the default clock used? Else I should probably make
> a patch there.

Mostly you can depend on CLOCK_MONONTONIC beiing used, even when POSIX 
explicitly says otherwise.  E.g., for nanosleep().

> man pthread_cond_timedwait() is silent!

POSIX (draft 2001 version at least) is not silent, but is fuzzy.  It has
hints that CLOCK_REALTIME is used, and notes the problem with someone
stepping the clock:

% 32854              Timed Wait Semantics
% 32855              An absolute time measure was chosen for specifying the timeout parameter for two reasons.

This is about pthread_cond_timedwait()'s parameter.  It is an _absolute_
time.

% 32856              First, a relative time measure can be easily implemented on top of a function that specifies

s/easily/with great difficulty/ if stepping the clock is allowed.

s/easily/with difficulty/ if the time interval might contain leap seconds.

% 32857              absolute time, but there is a race condition associated with specifying an absolute timeout on top
% 32858              of a function that specifies relative timeouts. For example, assume that clock_gettime( ) returns
% 32859              the current time and cond_relative_timed_wait( ) uses relative timeouts:
% 32860              clock_gettime(CLOCK_REALTIME, &now)
% 32861              reltime = sleep_til_this_absolute_time -now;
% 32862              cond_relative_timed_wait(c, m, &reltime);
% 32863              If the thread is preempted between the first statement and the last statement, the thread blocks
% 32864              for too long. Blocking, however, is irrelevant if an absolute timeout is used. An absolute timeout
% 32865              also need not be recomputed if it is used multiple times in a loop, such as that enclosing a
% 32866              condition wait.

Elsewhere, POSIX specifies clock_nanosleep() to have a clock id arg
and a TIMER_ABSTIME flag, so that you can control and know which clock
you are getting and whether the timer is absolute.  This fixes related
API problems with nanosleep().  But FreeBSD doesn't implement
clock_nanosleep(), and for pthread_cond_timedwait(), there seems to
be no choice, and CLOCK_REALTIME makes most sense if only 1 clock id
is supported.

% 32867              For cases when the system clock is advanced discontinuously by an operator, it is expected that
% 32868              implementations process any timed wait expiring at an intervening time as if that time had
% 32869              actually occurred.

Since an operator is not permitted to advance CLOCK_MONOTONIC, at least via
any POSIX API, this is apparently talking about CLOCK_REALTIME.

It doesn't say what happens if the operator retarded the system clock
discontinuously.  I think the following should happen: the timer expires
as soon as possible after `abstime' is first reached.  (This will just
be later than if the system clock was not retarded.)  If the system
clock was stepped forth and back, then the same rule applies (if any
advance went past `abstime', then the timer expires, even if the clock
is immediately stepped back.  The worst cases of this shouldn't happen).

Also, if the system or its clock was stopped when `abstime' would have
been reached if they were not stopped, then the system is not required
to start so as to deliver the timeout sooner than would be possible if
it didn't restart, unless this is a magic timer for reastating systems.

Absolute times make most sense with CLOCK_REALTIME, but they would mostly
work OK or better with CLOCK_MONOTONIC, if that worked correctly.  It
doesn't, since it is relative to a variable time in the past although
POSIX requires it to be relative to a fixed time in the past.

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120612100540.M1359>