Subject: POSIX timer_settime() dosn't set timer in some cases (lost accuracy)
To: None <tech-kern@netbsd.org>
From: Ian Zagorskih <ianzag@megasignal.com>
List: tech-kern
Date: 08/31/2004 23:44:45
NetBSD IANZAG 2.0G NetBSD 2.0G (IANZAG) #1: Thu Aug 26 02:11:03 NOVST 2004  
ianzag@IANZAG:/usr/src/sys/arch/i386/compile/IANZAG i386

According to POSIX docs at 
http://www.opengroup.org/onlinepubs/009695399/functions/timer_getoverrun.html

---cut---
The timer_gettime() function shall store the amount of time until the 
specified timer, timerid, expires and the reload value of the timer into the 
space pointed to by the value argument. The it_value member of this structure 
shall contain the amount of time before the timer expires, or zero if the 
timer is disarmed.
---cut---

Same as NetBSD man pages says:

---cut---
The timer_settime() sets the next expiration time of the timer with id timerid 
to the it_value specified in the tim argument.  If the value is 0, the timer 
is disarmed.
---cut---

So, the code below

struct itimerspec its;
its.it_value.tv_sec = 0;
its.it_value.tv_nsec = 1;
its.it_interval.tv_sec = 1;
its.it_interval.tv_nsec = 0;
timer_settime(timerid, 0, &its, 0);

..must work course it_value field isn't zero. Even more, in the past according 
to the POSIX specs i'v got used to "start interval timer as far as possibly 
without initial delay" just setting it_value as shown above (sec = 0, nsec = 
1).

On the other hand, sys_timer_settime() in kern/kern_time.c converts itimerspec 
structure into internal itimerval struture with macro TIMESPEC_TO_TIMEVAL as:

#define TIMESPEC_TO_TIMEVAL(tv, ts) {  \
        (tv)->tv_sec = (ts)->tv_sec;   \
        (tv)->tv_usec = (ts)->tv_nsec / 1000;  \
}

Obviously, doing this way we'r lossing nanosecond part and 1 ns becomes 0 us 
-> timer isn't armed. From my point of view this violates POSIX way :)

Any ideas/comments ?

ps: Just porting some own old code and found that timer isn't armed while it's 
expected to..

// wbr