Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F156510066
D3521.id9941.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
D3521.id9941.diff
View Options
Index: share/man/man9/Makefile
===================================================================
--- share/man/man9/Makefile
+++ share/man/man9/Makefile
@@ -1694,6 +1694,7 @@
timeout.9 callout_active.9 \
timeout.9 callout_deactivate.9 \
timeout.9 callout_drain.9 \
+ timeout.9 callout_drain_async.9 \
timeout.9 callout_handle_init.9 \
timeout.9 callout_init.9 \
timeout.9 callout_init_mtx.9 \
Index: share/man/man9/timeout.9
===================================================================
--- share/man/man9/timeout.9
+++ share/man/man9/timeout.9
@@ -36,6 +36,7 @@
.Nm callout_active ,
.Nm callout_deactivate ,
.Nm callout_drain ,
+.Nm callout_drain_async ,
.Nm callout_handle_init ,
.Nm callout_init ,
.Nm callout_init_mtx ,
@@ -70,6 +71,8 @@
.Fn callout_deactivate "struct callout *c"
.Ft int
.Fn callout_drain "struct callout *c"
+.Ft int
+.Fn callout_drain_async "struct callout *c" "callout_func_t *fn" "void *arg"
.Ft void
.Fn callout_handle_init "struct callout_handle *handle"
.Bd -literal
@@ -264,6 +267,24 @@
.Fn callout_drain
returns.
.Pp
+The function
+.Fn callout_drain_async
+is non-blocking and works the same as the
+.Fn callout_stop
+function.
+When this function returns zero, do not call it again until the callback function given by
+.Fa fn
+has been called with argument
+.Fa arg .
+Only one of
+.Fn callout_drain
+or
+.Fn callout_drain_async
+should be called at a time to drain a callout.
+If this function returns non-zero, it is safe to free the callout structure pointed to by the
+.Fa c
+argument immediately.
+.Pp
The
.Fn callout_reset
and
Index: sys/kern/kern_timeout.c
===================================================================
--- sys/kern/kern_timeout.c
+++ sys/kern/kern_timeout.c
@@ -136,6 +136,8 @@
*/
struct cc_exec {
struct callout *cc_curr;
+ callout_func_t *cc_drain_fn;
+ void *cc_drain_arg;
#ifdef SMP
void (*ce_migration_func)(void *);
void *ce_migration_arg;
@@ -170,6 +172,8 @@
#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_fn(cc, dir) cc->cc_exec_entity[dir].cc_drain_fn
+#define cc_exec_drain_arg(cc, dir) cc->cc_exec_entity[dir].cc_drain_arg
#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 +683,7 @@
cc_exec_curr(cc, direct) = c;
cc_exec_cancel(cc, direct) = false;
+ cc_exec_drain_fn(cc, direct) = NULL;
CC_UNLOCK(cc);
if (c_lock != NULL) {
class->lc_lock(c_lock, lock_status);
@@ -744,6 +749,11 @@
CC_LOCK(cc);
KASSERT(cc_exec_curr(cc, direct) == c, ("mishandled cc_curr"));
cc_exec_curr(cc, direct) = NULL;
+ if (cc_exec_drain_fn(cc, direct) != NULL) {
+ CC_UNLOCK(cc);
+ cc_exec_drain_fn(cc, direct)(cc_exec_drain_arg(cc, direct));
+ CC_LOCK(cc);
+ }
if (cc_exec_waiting(cc, direct)) {
/*
* There is someone waiting for the
@@ -1145,6 +1155,41 @@
}
int
+callout_drain_async(struct callout *c, callout_func_t *func, void *arg)
+{
+ struct callout_cpu *cc;
+ int retval;
+ int direct;
+
+ /*
+ * NOTE: The return value of "callout_stop()" cannot be used
+ * in this context, because it does not reliably tell if the
+ * callout is currently executing or not.
+ */
+
+ /* stop callout */
+ (void) callout_stop(c);
+
+ /* check if callback is being called */
+ cc = callout_lock(c);
+ if (c->c_iflags & CALLOUT_DIRECT) {
+ direct = 1;
+ } else {
+ direct = 0;
+ }
+ retval = (cc_exec_curr(cc, direct) == c);
+
+ if (retval) {
+ /* install drain callback function and argument */
+ cc_exec_drain_fn(cc, direct) = func;
+ cc_exec_drain_arg(cc, direct) = arg;
+ }
+ CC_UNLOCK(cc);
+
+ return (!retval);
+}
+
+int
_callout_stop_safe(struct callout *c, int safe)
{
struct callout_cpu *cc, *old_cc;
Index: sys/sys/_callout.h
===================================================================
--- sys/sys/_callout.h
+++ sys/sys/_callout.h
@@ -46,6 +46,8 @@
SLIST_HEAD(callout_slist, callout);
TAILQ_HEAD(callout_tailq, callout);
+typedef void callout_func_t(void *);
+
struct callout {
union {
LIST_ENTRY(callout) le;
Index: sys/sys/callout.h
===================================================================
--- sys/sys/callout.h
+++ sys/sys/callout.h
@@ -82,6 +82,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)
+int callout_drain_async(struct callout *, callout_func_t *, void *);
void callout_init(struct callout *, int);
void _callout_init_lock(struct callout *, struct lock_object *, int);
#define callout_init_mtx(c, mtx, flags) \
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, May 15, 6:42 AM (8 h, 18 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33075684
Default Alt Text
D3521.id9941.diff (4 KB)
Attached To
Mode
D3521: Implement callout_drain_async()
Attached
Detach File
Event Timeline
Log In to Comment