Page MenuHomeFreeBSD

D3521.id.diff
No OneTemporary

D3521.id.diff

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

Mime Type
text/plain
Expires
Fri, May 15, 10:19 AM (11 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33075684
Default Alt Text
D3521.id.diff (4 KB)

Event Timeline