Page MenuHomeFreeBSD

D4076.id9915.diff
No OneTemporary

D4076.id9915.diff

Index: kern/kern_timeout.c
===================================================================
--- kern/kern_timeout.c
+++ kern/kern_timeout.c
@@ -136,6 +136,7 @@
*/
struct cc_exec {
struct callout *cc_curr;
+ void (*cc_drain)(void *);
#ifdef SMP
void (*ce_migration_func)(void *);
void *ce_migration_arg;
@@ -170,6 +171,7 @@
#define callout_migrating(c) ((c)->c_iflags & CALLOUT_DFRMIGRATION)
#define cc_exec_curr(cc, dir) cc->cc_exec_entity[dir].cc_curr
+#define cc_exec_drain(cc, dir) cc->cc_exec_entity[dir].cc_drain
#define cc_exec_next(cc) cc->cc_next
#define cc_exec_cancel(cc, dir) cc->cc_exec_entity[dir].cc_cancel
#define cc_exec_waiting(cc, dir) cc->cc_exec_entity[dir].cc_waiting
@@ -679,6 +681,7 @@
cc_exec_curr(cc, direct) = c;
cc_exec_cancel(cc, direct) = false;
+ cc_exec_drain(cc, direct) = NULL;
CC_UNLOCK(cc);
if (c_lock != NULL) {
class->lc_lock(c_lock, lock_status);
@@ -744,6 +747,15 @@
CC_LOCK(cc);
KASSERT(cc_exec_curr(cc, direct) == c, ("mishandled cc_curr"));
cc_exec_curr(cc, direct) = NULL;
+ if (cc_exec_drain(cc, direct)) {
+ void (*drain)(void *);
+
+ drain = cc_exec_drain(cc, direct);
+ cc_exec_drain(cc, direct) = NULL;
+ CC_UNLOCK(cc);
+ drain(c_arg);
+ CC_LOCK(cc);
+ }
if (cc_exec_waiting(cc, direct)) {
/*
* There is someone waiting for the
@@ -1145,7 +1157,7 @@
}
int
-_callout_stop_safe(struct callout *c, int safe)
+_callout_stop_safe(struct callout *c, int safe, void (*drain)(void *))
{
struct callout_cpu *cc, *old_cc;
struct lock_class *class;
@@ -1225,20 +1237,35 @@
* stop it by other means however.
*/
if (!(c->c_iflags & CALLOUT_PENDING)) {
- c->c_flags &= ~CALLOUT_ACTIVE;
-
/*
* If it wasn't on the queue and it isn't the current
* callout, then we can't stop it, so just bail.
+ * It probably has already been run (if locking
+ * is properly done). You could get here if the caller
+ * calls stop twice in a row for example. The second
+ * call would fall here without CALLOUT_ACTIVE set.
*/
if (cc_exec_curr(cc, direct) != c) {
+ int act;
CTR3(KTR_CALLOUT, "failed to stop %p func %p arg %p",
c, c->c_func, c->c_arg);
+ c->c_flags &= ~CALLOUT_ACTIVE;
+ act = c->c_flags & CALLOUT_ACTIVE;
CC_UNLOCK(cc);
+ if (drain && act) {
+ /*
+ * Call the drain function, it finished.
+ * Though the only way I can think of we
+ * get in here is if the caller did not
+ * use proper locking and clearing ACTIVE.
+ */
+ drain(c->c_arg);
+ }
if (sq_locked)
sleepq_release(&cc_exec_waiting(cc, direct));
return (0);
}
+ c->c_flags &= ~CALLOUT_ACTIVE;
if (safe) {
/*
@@ -1352,10 +1379,16 @@
CTR3(KTR_CALLOUT, "postponing stop %p func %p arg %p",
c, c->c_func, c->c_arg);
CC_UNLOCK(cc);
+ if (drain) {
+ cc_exec_drain(cc, direct) = drain;
+ }
return (0);
}
CTR3(KTR_CALLOUT, "failed to stop %p func %p arg %p",
c, c->c_func, c->c_arg);
+ if (drain) {
+ cc_exec_drain(cc, direct) = drain;
+ }
CC_UNLOCK(cc);
KASSERT(!sq_locked, ("sleepqueue chain still locked"));
return (0);
Index: sys/callout.h
===================================================================
--- sys/callout.h
+++ sys/callout.h
@@ -81,7 +81,7 @@
*/
#define callout_active(c) ((c)->c_flags & CALLOUT_ACTIVE)
#define callout_deactivate(c) ((c)->c_flags &= ~CALLOUT_ACTIVE)
-#define callout_drain(c) _callout_stop_safe(c, 1)
+#define callout_drain(c) _callout_stop_safe(c, 1, NULL)
void callout_init(struct callout *, int);
void _callout_init_lock(struct callout *, struct lock_object *, int);
#define callout_init_mtx(c, mtx, flags) \
@@ -119,10 +119,11 @@
int callout_schedule_on(struct callout *, int, int);
#define callout_schedule_curcpu(c, on_tick) \
callout_schedule_on((c), (on_tick), PCPU_GET(cpuid))
-#define callout_stop(c) _callout_stop_safe(c, 0)
-int _callout_stop_safe(struct callout *, int);
+#define callout_stop(c) _callout_stop_safe(c, 0, NULL)
+int _callout_stop_safe(struct callout *, int, void (*)(void *));
void callout_process(sbintime_t now);
-
+#define callout_async_drain(c, d) \
+ _callout_stop_safe(c, 0, d)
#endif
#endif /* _SYS_CALLOUT_H_ */

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 22, 9:26 PM (9 h, 18 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
25906084
Default Alt Text
D4076.id9915.diff (4 KB)

Event Timeline