Subject: kern/21405: clock_gettime() acts funny in -current 20030427
To: None <gnats-bugs@gnats.netbsd.org>
From: Frank Kardel <kardel@acm.org>
List: netbsd-bugs
Date: 04/30/2003 15:57:45
>Number:         21405
>Category:       kern
>Synopsis:       clock_gettime(CLOCK_REALTIME, ...) goes backwords in time by a second (-current 20030427)
>Confidential:   yes
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Apr 30 13:58:00 UTC 2003
>Closed-Date:
>Last-Modified:
>Originator:     Frank Kardel
>Release:        NetBSD 1.6R
>Organization:
	
>Environment:
	
	
System: NetBSD pip 1.6R NetBSD 1.6R (PIP) #1: Sun Apr 27 08:09:36 MEST 2003 kardel@pip:/fs/IC35L060-0-a/src/NetBSD/netbsd/sys/arch/i386/compile/obj.i386/PIP i386
Architecture: i386
Machine: i386
>Description:
	When reading successive time stamps via clock_gettime(CLOCK_REALTIME, ...) the difference between the later and
	the earlier time stamp can become -1 second.

>How-To-Repeat:

#include <stdio.h>
#include <time.h>

main()
{
  int a;
  struct timespec tsa;
  struct timespec tsb;

  if (clock_gettime(CLOCK_REALTIME, &tsa) == -1)
    perror("clock_gettime(CLOCK_REALTIME, &tsa)");
  while (1) {
    long long diff;

    if (clock_gettime(CLOCK_REALTIME, &tsb) == -1)
      perror("clock_gettime(CLOCK_REALTIME, &tsb)");
    diff = 1000000000LL * (tsb.tv_sec - tsa.tv_sec) + tsb.tv_nsec - tsa.tv_nsec;
    if (diff < 0 || diff > 100000000) {
      printf("bad time TSA: 0x%x.%08x, TSB: 0x%x.%08x, diff = %lld\n", tsa.tv_sec, tsa.tv_nsec, tsb.tv_sec, tsb.tv_nsec, diff);
    }
    tsa.tv_sec = tsb.tv_sec;
    tsa.tv_nsec = tsb.tv_nsec;
  }
  return 0;
}

Output:
bad time TSA: 0x3eafd20c.366e8e18, TSB: 0x3eafd20b.366e8e18, diff = -1000000000
bad time TSA: 0x3eafd21a.24bd7cb0, TSB: 0x3eafd219.24bd7cb0, diff = -1000000000
bad time TSA: 0x3eafd227.37108ad8, TSB: 0x3eafd226.37108ad8, diff = -1000000000
bad time TSA: 0x3eafd236.0296e720, TSB: 0x3eafd235.0296e720, diff = -1000000000
...

It is strange, that the tv_sec field goes backwords in time... seems tv_sec and tv_nsec are not atomically updated wrt/ clock_gettime.

Anything i overlooked ?

>Fix:
	? 
>Release-Note:
>Audit-Trail:
>Unformatted: