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); } /*