I noticed that clock(3) currently violates a requirement of POSIX 2001 (that CLOCKS_PER_SEC is 1000000) and that the various archs are inconsistent and somtimes different from what is in clocks(7). However clock() isn't mentioned on the C99 project page. This patch changes clock_t to a size that is consistent on all platforms and big enough to allow CLOCKS_PER_SEC to be increased to 1e6 without loss of range. This implies a binary compatibility breakage for programs that call clock() or times(), and therefore a __FreeBSD_version bump which I haven't included in this patch. I also haven't tested it yet :-) Is there anything else to worry about that I might not be aware of? This patch is rather repetitive. IWBNI the MI stuff in machine/ansi.h could be moved into an MI header, e.g. sys/ansi.h which might be included by machine/ansi.h or vice versa. Tony.
On Tue, 28 May 2002, Tony Finch wrote: > I noticed that clock(3) currently violates a requirement of POSIX > 2001 (that CLOCKS_PER_SEC is 1000000) and that the various archs > are inconsistent and somtimes different from what is in clocks(7).That is only in a (broken) XSI extension. "Fixing" this would mainly break binary compatibility since it would change from one historical wrong value to another (128 -> 1000000). The first C standard got this right by permitting it to be a runtime parameter. This value should be <frequency of kernel timecounter> which may be a few billion on current machines. This requires clock_t to be much larger than uint32_t so that it can represent 24 hours in ticks. clock_t should probably be double. POSIX's clock_getres() is broken as designed too. It specifies returning the precision in a timeval, by FreeBSD's potential resolution of (1 <frequency of kernel timecounter>) started overflowing a year or two ago when TSC frequencies started exceeding 1 billion).> This patch changes clock_t to a size that is consistent on all platforms > and big enough to allow CLOCKS_PER_SEC to be increased to 1e6 without > loss of range. This implies a binary compatibility breakage for programs > that call clock() or times(), and therefore a __FreeBSD_version bump > which I haven't included in this patch. I also haven't tested it yet :-)I would prefer to break things only once in the transition to the correct non-XSI-supporting implementation, something like this: - clock_t of type double, long double or uint64_t or larger - CLOCKS_PER_SECOND = ((clock_t)sysconf(_SC_CLK_TCK)) (this limits it to LONG_MAX, but longs will soon always be >= 64 bits) - sysconf(_SC_CLK_TCK) returns <frequency of kernel timecounter> (scaled down a little if necessary) I actually prefer to let this rot and tell everyone to use clock_gettime().> This patch is rather repetitive. IWBNI the MI stuff in machine/ansi.h > could be moved into an MI header, e.g. sys/ansi.h which might be included > by machine/ansi.h or vice versa.This is potentially very MD. E.g., uint64_t is a good type for clock_t on 64-bit machines, but double is probably more efficient on 32-bit ones. Machines with a clock frequency of 18.4 Hz need a double to even represent the frequency. _BSD_CLOCKS_PER_SECOND_ was gratuitously MD because most copies of it were cloned from a rotted value for CLK_TCK in NetBSD starting with the alpha, despite the alpha not having any binary compatibility baggage so it could have started with a reasonably large value like 1e6 :-). Clocks.7 mentions too many clocks but doesn't manage to mention any except old i386 ones. Bruce To Unsubscribe: send mail to with "unsubscribe freebsd-standards" in the body of the message
On Wed, May 29, 2002 at 05:56:17AM +1000, Bruce Evans wrote:
> On Tue, 28 May 2002, Tony Finch wrote:
>
> > I noticed that clock(3) currently violates a requirement of POSIX
> > 2001 (that CLOCKS_PER_SEC is 1000000) and that the various archs
> > are inconsistent and somtimes different from what is in clocks(7).
>
> That is only in a (broken) XSI extension. "Fixing" this would mainly
> break binary compatibility since it would change from one historical
> wrong value to another (128 -> 1000000). The first C standard got this
> right by permitting it to be a runtime parameter. This value should
> be <frequency of kernel timecounter> which may be a few billion on
> current machines. This requires clock_t to be much larger than uint32_t
> so that it can represent 24 hours in ticks. clock_t should probably be
> double.But to do this would require changing the implementation to use something
other than getrusage() to implement clock() and times(). Wouldn't it be
better to add a non-standard interface for getting the higher resolution
value, instead of being non-compliant?
There's currently a discussion on comp.std.c about relaxing the C99
definition of CLOCKS_PER_SEC back to the C89 definition.
> I actually prefer to let this rot and tell everyone to use clock_gettime().
We currently tell everyone to use getrusage().
Tony.
On Tue, 28 May 2002, Tony Finch wrote: > On Wed, May 29, 2002 at 05:56:17AM +1000, Bruce Evans wrote: > > On Tue, 28 May 2002, Tony Finch wrote: > > > > > I noticed that clock(3) currently violates a requirement of POSIX > > > 2001 (that CLOCKS_PER_SEC is 1000000) and that the various archs > > > are inconsistent and somtimes different from what is in clocks(7). > > > > That is only in a (broken) XSI extension. "Fixing" this would mainly > > break binary compatibility since it would change from one historical > > wrong value to another (128 -> 1000000). The first C standard got this > > right by permitting it to be a runtime parameter. This value should > > be <frequency of kernel timecounter> which may be a few billion on > > current machines. This requires clock_t to be much larger than uint32_t > > so that it can represent 24 hours in ticks. clock_t should probably be > > double. > > But to do this would require changing the implementation to use something > other than getrusage() to implement clock() and times(). Wouldn't it be > better to add a non-standard interface for getting the higher resolution > value, instead of being non-compliant?clock() and times() can keep using getrusage() for a while. The important points are to enlarge clock_t and make CLOCKS_PER_SECOND a non-constant so that it can be changed without breaking binary compatibility. BTW, the Linux emulator has several Linux constants for CLK_TCK compiled in. times(3) is is times(2) in Linux, so if Linux changed it then the emulator would need to have even more Linux constants and ifdefs to decide which one to use...> There's currently a discussion on comp.std.c about relaxing the C99 > definition of CLOCKS_PER_SEC back to the C89 definition.I didn't know that C99 changed it. I read com.std.c every week or so. Time to catch up. It all seems to be there... Almost content-free except for the first post :-). Yes, the old definition was better. CLOCKS_PER_SEC is 18.2 in all the versions of Turbo/Burland C that I've looked at (1987-1999), but clock_t is long. Requiring CLOCKS_PER_SEC to have type clock_t breaks this. Requiring CLOCKS_PER_SEC to be a compile-time constant breaks my preferred definition of it as sysconf(...) :-), and is bad for portabilty as discussed in the thread. I suspect that there is a lot of practical code that does stupid things like revaluating CLOCKS_PER_SEC in inner loops, but I think this isn't much of a problem under BSDish system because serious code uses gettimeofday() or getrusage().> > I actually prefer to let this rot and tell everyone to use clock_gettime(). > > We currently tell everyone to use getrusage().I used to use gettimeofday() in my clock syscall overhead benchmark, but switched to clock_gettime() a few months ago when I finally got a system with a >= 1GHz clock :-). Bruce To Unsubscribe: send mail to with "unsubscribe freebsd-standards" in the body of the message
On Wed, May 29, 2002 at 05:56:17AM +1000, Bruce Evans wrote:
> On Tue, 28 May 2002, Tony Finch wrote:
>
> > I noticed that clock(3) currently violates a requirement of POSIX
> > 2001 (that CLOCKS_PER_SEC is 1000000) and that the various archs
> > are inconsistent and somtimes different from what is in clocks(7).
>
> That is only in a (broken) XSI extension. "Fixing" this would mainly
> break binary compatibility since it would change from one historical
> wrong value to another (128 -> 1000000). The first C standard got this
> right by permitting it to be a runtime parameter. This value should
> be <frequency of kernel timecounter> which may be a few billion on
> current machines. This requires clock_t to be much larger than uint32_t
> so that it can represent 24 hours in ticks. clock_t should probably be
> double.Hmm, I've been thinking about this a bit more. Does FreeBSD actually
keep the necessary statistics at that resolution? As far as I can
tell it is done internally at microsecond resolution.
Tony.
On Thu, 30 May 2002, Tony Finch wrote:
> On Wed, May 29, 2002 at 05:56:17AM +1000, Bruce Evans wrote:
> > On Tue, 28 May 2002, Tony Finch wrote:
> >
> > > I noticed that clock(3) currently violates a requirement of POSIX
> > > 2001 (that CLOCKS_PER_SEC is 1000000) and that the various archs
> > > are inconsistent and somtimes different from what is in clocks(7).
> >
> > That is only in a (broken) XSI extension. "Fixing" this would mainly
> > break binary compatibility since it would change from one historical
> > wrong value to another (128 -> 1000000). The first C standard got this
> ...
> Hmm, I've been thinking about this a bit more. Does FreeBSD actually
> keep the necessary statistics at that resolution? As far as I can
> tell it is done internally at microsecond resolution.It does now, more or less. Process times are stored in struct bintime
in -current. struct bintime has a resolution of 2^-64 seconds. User,
sys and interrupt times are the process time split up statistically
(so their accuracy is much lower than the resolution). This only
affects getrusage() and similar interfaces. clock() could use
timecounters directly and get the 2^-64 resolution, but there is
currently no syscall for this. clock_gettime() is closest.
Bruce
To Unsubscribe: send mail to
with "unsubscribe freebsd-standards" in the body of the message