Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F137260857
D4076.id9915.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D4076.id9915.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D4076: Add async drain from within the callout system.
Attached
Detach File
Event Timeline
Log In to Comment