NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
kern/57512: clock_gettime(CLOCK_THREAD_CPUTIME_ID) sometimes goes backwards
>Number: 57512
>Category: kern
>Synopsis: clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) sometimes reports a timespec less than one obtained on a previous invocation (i.e, it goes backwards)
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Fri Jul 07 21:45:00 +0000 2023
>Originator: Conor Hughes
>Release: NetBSD 9.3
>Organization:
conorh%sdf.org@localhost
SDF Public Access UNIX System - http://sdf.org
>Environment:
System: NetBSD otaku 9.3 NetBSD 9.3 (GENERIC) #0: Thu Aug 4 15:30:37 UTC 2022 mkrepro%mkrepro.NetBSD.org@localhost:/usr/src/sys/arch/amd64/compile/GENERIC amd64
Architecture: x86_64
Machine: amd64
>Description:
When calling clock_gettime(2) and using CLOCK_THREAD_CPUTIME_ID as the clockid_t, the value filled into the timespec is sometimes less than a previous value obtained via the same call on the same thread. Since consuming negative CPU time doesn't make sense, this seems like a bug.
CLOCK_PROCESS_CPUTIME_ID does not seem to be affected and is a workaround in some cases. I've reproduced this on NetBSD 9.3 on x86_64 and evbarm/armv6.
>How-To-Repeat:
Compile and run the following test program.
#include <stdio.h>
#include <time.h>
#include <err.h>
#include <sysexits.h>
#include <stdlib.h>
#include <string.h>
/* The specifics of this function are immaterial but we have to do some work in order to separate
* start and end.
*/
static void waste_some_time()
{
for ( int i = 0; i< 1000; i++ ) {
char buf[4 * 4096];
arc4random_buf(buf, sizeof(buf));
char buf2[4 * 4096];
arc4random_buf(buf2, sizeof(buf2));
if ( memcmp(buf, buf2, sizeof(buf)) == 0 ) {
fprintf(stderr, "wow!\n");
}
}
}
int main(void)
{
static const int niter = 100;
static const clockid_t query_clock = CLOCK_THREAD_CPUTIME_ID;
for ( int iter = 0; iter < niter; iter++ ) {
struct timespec start;
if ( clock_gettime(query_clock, &start) != 0 ) {
err(EX_OSERR, "clock_gettime");
}
waste_some_time();
struct timespec end;
if ( clock_gettime(query_clock, &end) != 0 ) {
err(EX_OSERR, "clock_gettime");
}
if ( end.tv_sec < start.tv_sec ||
(end.tv_sec == start.tv_sec && end.tv_nsec < start.tv_nsec) ) {
errx(EX_OSERR, "clock_gettime went backwards!? after %d iterations, start (%lld %lld) end (%lld %lld)",
iter,
(long long)start.tv_sec, (long long)start.tv_nsec,
(long long)end.tv_sec, (long long)end.tv_nsec);
}
}
fprintf(stderr, "did %d iterations.\n", niter);
return EXIT_SUCCESS;
}
>Fix:
Unknown
Home |
Main Index |
Thread Index |
Old Index