> 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, &notdone);
>> +
>> +    task_add(tq, &t);
>> +
>> +    while (notdone) {
>> +            sleep_setup(&sls, &notdone, PWAIT, "tqbar");
>> +            sleep_finish(&sls, notdone);
>> +    }
>> +}
>> +
>> +void
>> +taskq_barrier_task(void *p)
>> +{
>> +    unsigned int *notdone = p;
>> +
>> +    *notdone = 0;
>> +    wakeup_one(notdone);
>> }
>> 
>> void
>> 
>> 

Reply via email to