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