Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/kern Change the contract for timer_settime() (the intern...



details:   https://anonhg.NetBSD.org/src/rev/d3e7b75c41eb
branches:  trunk
changeset: 544082:d3e7b75c41eb
user:      nathanw <nathanw%NetBSD.org@localhost>
date:      Mon Mar 10 21:49:56 2003 +0000

description:
Change the contract for timer_settime() (the internal routine, not the
syscall sys_timer_settime()) to take an absolute value for realtime
timers. This avoids a pair of gratiuitous conversions with the
possibility that the timer's intermediate value would be 0.0, which
would signal timer_settime() to cancel the timer.

Adjust callers of timer_settime() to compensate; catch the case where
sys_timer_settime() with an absolute time value of now and a virtual
timer would also be subtracted down to a timer-cancelling 0.0.

This should fix the bug seen in libpthread's nanosleep() where certain
applications, such as xmms, would wedge with unexpired userlevel
alarms.

diffstat:

 sys/kern/kern_time.c |  45 ++++++++++++++++++++++++++++++++++-----------
 1 files changed, 34 insertions(+), 11 deletions(-)

diffs (87 lines):

diff -r 726a8f7765d5 -r d3e7b75c41eb sys/kern/kern_time.c
--- a/sys/kern/kern_time.c      Mon Mar 10 21:21:10 2003 +0000
+++ b/sys/kern/kern_time.c      Mon Mar 10 21:49:56 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_time.c,v 1.66 2003/02/04 15:50:06 jdolecek Exp $  */
+/*     $NetBSD: kern_time.c,v 1.67 2003/03/10 21:49:56 nathanw Exp $   */
 
 /*-
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -72,7 +72,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_time.c,v 1.66 2003/02/04 15:50:06 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_time.c,v 1.67 2003/03/10 21:49:56 nathanw Exp $");
 
 #include "fs_nfs.h"
 #include "opt_nfs.h"
@@ -630,8 +630,9 @@
 }
 
 /*
- * Set up the given timer. The value in pt->pt_time.it_value is taken to be
- * relative to now.
+ * Set up the given timer. The value in pt->pt_time.it_value is taken
+ * to be an absolute time for CLOCK_REALTIME timers and a relative
+ * time for virtual timers.
  * Must be called at splclock().
  */
 void
@@ -643,8 +644,6 @@
        if (pt->pt_type == CLOCK_REALTIME) {
                callout_stop(&pt->pt_ch);
                if (timerisset(&pt->pt_time.it_value)) {
-                       timeradd(&pt->pt_time.it_value, &time,
-                           &pt->pt_time.it_value);
                        /*
                         * Don't need to check hzto() return value, here.
                         * callout_reset() does it for us.
@@ -763,11 +762,31 @@
        pt->pt_time = val;
 
        s = splclock();
-       /* If we've been passed an absolute time, convert it to relative. */
-       if (timerisset(&pt->pt_time.it_value) &&
-           (SCARG(uap, flags) & TIMER_ABSTIME))
-               timersub(&pt->pt_time.it_value, &time,
-                   &pt->pt_time.it_value);
+       /*
+        * If we've been passed a relative time for a realtime timer,
+        * convert it to absolute; if an absolute time for a virtual
+        * timer, convert it to relative and make sure we don't set it
+        * to zero, which would cancel the timer, or let it go
+        * negative, which would confuse the comparison tests.
+        */
+       if (timerisset(&pt->pt_time.it_value)) {
+               if (pt->pt_type == CLOCK_REALTIME) {
+                       if ((SCARG(uap, flags) & TIMER_ABSTIME) == 0)
+                               timeradd(&pt->pt_time.it_value, &time,
+                                   &pt->pt_time.it_value);
+               } else {
+                       if ((SCARG(uap, flags) & TIMER_ABSTIME) != 0) {
+                               timersub(&pt->pt_time.it_value, &time,
+                                   &pt->pt_time.it_value);
+                               if (!timerisset(&pt->pt_time.it_value) ||
+                                   pt->pt_time.it_value.tv_sec < 0) {
+                                       pt->pt_time.it_value.tv_sec = 0;
+                                       pt->pt_time.it_value.tv_usec = 1;
+                               }
+                       }
+               }
+       }
+
        timer_settime(pt);
        splx(s);
 
@@ -1009,6 +1028,10 @@
        p->p_timers->pts_timers[which] = pt;
 
        s = splclock();
+       if ((which == ITIMER_REAL) && timerisset(&pt->pt_time.it_value)) {
+               /* Convert to absolute time */
+               timeradd(&pt->pt_time.it_value, &time, &pt->pt_time.it_value);
+       }
        timer_settime(pt);
        splx(s);
 



Home | Main Index | Thread Index | Old Index