there is an expectation that if you timeout_del the timeout will
not run. however, it doesnt prevent it from being about to run, or
from running on another cpu at the same time as you're doing the
timeout_del. you can check if the timeout ran with timeout_triggered,
but that can race unless you are at splsoftclock or higher.
unfortunately spls dont protect you if you don't hold the big lock.

this adds a return to timeout_del so you can know if the timeout
was pending or not. if you know you went timeout_add and timeout_del
returns 0, then you know you have to wait for your timeout to finish
working (which is your responsibility, not the timeout codes).

discussed with drinking art and art.

a manpage change will follow if this is ok.

ok?

Index: sys/timeout.h
===================================================================
RCS file: /cvs/src/sys/sys/timeout.h,v
retrieving revision 1.20
diff -u -p -r1.20 timeout.h
--- sys/timeout.h       26 May 2010 17:50:00 -0000      1.20
+++ sys/timeout.h       3 Apr 2011 15:59:32 -0000
@@ -91,7 +91,7 @@ void timeout_add_sec(struct timeout *, i
 void timeout_add_msec(struct timeout *, int);
 void timeout_add_usec(struct timeout *, int);
 void timeout_add_nsec(struct timeout *, int);
-void timeout_del(struct timeout *);
+int timeout_del(struct timeout *);
 
 void timeout_startup(void);
 
Index: kern/kern_timeout.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_timeout.c,v
retrieving revision 1.32
diff -u -p -r1.32 kern_timeout.c
--- kern/kern_timeout.c 4 Nov 2009 19:14:10 -0000       1.32
+++ kern/kern_timeout.c 3 Apr 2011 15:59:32 -0000
@@ -263,16 +263,21 @@ timeout_add_nsec(struct timeout *to, int
        timeout_add(to, to_ticks);
 }
 
-void
+int
 timeout_del(struct timeout *to)
 {
+       int ret = 0;
+
        mtx_enter(&timeout_mutex);
        if (to->to_flags & TIMEOUT_ONQUEUE) {
                CIRCQ_REMOVE(&to->to_list);
                to->to_flags &= ~TIMEOUT_ONQUEUE;
+               ret = 1;
        }
        to->to_flags &= ~TIMEOUT_TRIGGERED;
        mtx_leave(&timeout_mutex);
+
+       return (ret);
 }
 
 /*

Reply via email to