Index: share/man/man9/task_add.9 =================================================================== RCS file: /cvs/src/share/man/man9/task_add.9,v retrieving revision 1.16 diff -u -p -r1.16 task_add.9 --- share/man/man9/task_add.9 14 Sep 2015 15:14:55 -0000 1.16 +++ share/man/man9/task_add.9 30 Nov 2015 06:24:29 -0000 @@ -20,6 +20,7 @@ .Sh NAME .Nm taskq_create , .Nm taskq_destroy , +.Nm taskq_barrier , .Nm task_set , .Nm task_add , .Nm task_del , @@ -37,6 +38,8 @@ .Ft void .Fn taskq_destroy "struct taskq *tq" .Ft void +.Fn taskq_barrier "struct taskq *tq" +.Ft void .Fn task_set "struct task *t" "void (*fn)(void *)" "void *arg" .Ft int .Fn task_add "struct taskq *tq" "struct task *t" @@ -88,6 +91,15 @@ Calling against the system taskq is an error and will lead to undefined behaviour or a system fault. .Pp +.Fn taskq_barrier +guarantees that any task that was running on the +.Fa tq +taskq when the barrier was called has finished by the time the barrier +returns. +.Fn taskq_barrier +is only supported on taskqs serviced by 1 thread, +and may not be called by a task running in the specified taskq. +.Pp It is the responsibility of the caller to provide the .Fn task_set , .Fn task_add , @@ -163,6 +175,8 @@ argument given in and .Fn taskq_destroy can be called during autoconf, or from process context. +.Fn taskq_barrier +can be called from process context. .Fn task_set , .Fn task_add , and Index: share/man/man9/Makefile =================================================================== RCS file: /cvs/src/share/man/man9/Makefile,v retrieving revision 1.262 diff -u -p -r1.262 Makefile --- share/man/man9/Makefile 25 Nov 2015 03:09:57 -0000 1.262 +++ share/man/man9/Makefile 30 Nov 2015 06:24:29 -0000 @@ -397,6 +397,7 @@ MLINKS+=systrace.9 systrace_redirect.9 \ systrace.9 systrace_fork.9 systrace.9 systrace_exit.9 MLINKS+=task_add.9 taskq_create.9 \ task_add.9 taskq_destroy.9 \ + task_add.9 taskq_barrier.9 \ task_add.9 task_set.9 \ task_add.9 task_del.9 \ task_add.9 TASK_INITIALIZER.9 Index: sys/sys/task.h =================================================================== RCS file: /cvs/src/sys/sys/task.h,v retrieving revision 1.8 diff -u -p -r1.8 task.h --- sys/sys/task.h 9 Feb 2015 03:15:41 -0000 1.8 +++ sys/sys/task.h 30 Nov 2015 06:24:29 -0000 @@ -39,6 +39,7 @@ extern struct taskq *const systqmp; struct taskq *taskq_create(const char *, unsigned int, int, unsigned int); void taskq_destroy(struct taskq *); +void taskq_barrier(struct taskq *); void task_set(struct task *, void (*)(void *), void *); int task_add(struct taskq *, struct task *); Index: sys/kern/kern_task.c =================================================================== RCS file: /cvs/src/sys/kern/kern_task.c,v retrieving revision 1.15 diff -u -p -r1.15 kern_task.c --- sys/kern/kern_task.c 19 Nov 2015 13:19:24 -0000 1.15 +++ sys/kern/kern_task.c 30 Nov 2015 06:24:29 -0000 @@ -22,6 +22,7 @@ #include #include #include +#include #define TASK_ONQUEUE 1 @@ -68,6 +69,7 @@ struct taskq *const systqmp = &taskq_sys void taskq_init(void); /* called in init_main.c */ void taskq_create_thread(void *); +void taskq_barrier_task(void *); int taskq_sleep(const volatile void *, struct mutex *, int, const char *, int); int taskq_next_work(struct taskq *, struct task *, sleepfn); @@ -176,6 +178,30 @@ taskq_create_thread(void *arg) } while (tq->tq_running < tq->tq_nthreads); mtx_leave(&tq->tq_mtx); +} + +void +taskq_barrier(struct taskq *tq) +{ + struct sleep_state sls; + unsigned int notdone = 1; + struct task t = TASK_INITIALIZER(taskq_barrier_task, ¬done); + + task_add(tq, &t); + + while (notdone) { + sleep_setup(&sls, ¬done, PWAIT, "tqbar"); + sleep_finish(&sls, notdone); + } +} + +void +taskq_barrier_task(void *p) +{ + unsigned int *notdone = p; + + *notdone = 0; + wakeup_one(notdone); } void