> On 30 Nov 2015, at 5:54 PM, Mark Kettenis <mark.kette...@xs4all.nl> wrote: > >> Date: Mon, 30 Nov 2015 16:28:55 +1000 >> From: David Gwynne <da...@gwynne.id.au> >> >> while playing with some options around running an interfaces send >> queue, i came up with the following. if you've deferred work to a >> taskq and you're not reference counting, this can help you guarantee >> that any work before a point has completed before proceeding. >> >> think of it like intr_barrier. >> >> i dont currently have a need for this right now, so there's no real >> pressure to put this in. it's more a backup. >> >> if someone oks it i will happily commit it though. > > Never been a big fan of adding interfaces before we have an actual use > case. I might have one though in inteldrm(4). But I'll need to look > a little bit deeper into that.
the diff is successfully backed up now though ;) > > One problem with the interface is that it doesn't really work for a > taskq that has multiple worker threads isn't it? the current implementation is restricted like that. i had a version that was supposed to work for multiple threads but was a smorgasbord of use after frees. i have an idea for another way of doing it if you think it is necessary. dlg > >> 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 <sys/mutex.h> >> #include <sys/kthread.h> >> #include <sys/task.h> >> +#include <sys/proc.h> >> >> #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 >> >>