Index: kern_task.c =================================================================== RCS file: /cvs/src/sys/kern/kern_task.c,v retrieving revision 1.27 diff -u -p -r1.27 kern_task.c --- kern_task.c 19 Dec 2019 17:40:11 -0000 1.27 +++ kern_task.c 4 Jun 2020 23:40:13 -0000 @@ -36,6 +36,14 @@ static struct lock_type taskq_lock_type #endif /* WITNESS */ +struct taskq_thread { + SLIST_ENTRY(taskq_thread) + tt_entry; + struct proc *tt_thread; +}; + +SLIST_HEAD(taskq_threads, taskq_thread); + struct taskq { enum { TQ_S_CREATED, @@ -49,6 +57,7 @@ struct taskq { const char *tq_name; struct mutex tq_mtx; + struct taskq_threads tq_threads; struct task_list tq_worklist; #ifdef WITNESS struct lock_object tq_lock_object; @@ -65,6 +74,7 @@ struct taskq taskq_sys = { 0, taskq_sys_name, MUTEX_INITIALIZER(IPL_HIGH), + SLIST_HEAD_INITIALIZER(taskq_sys.tq_threads), TAILQ_HEAD_INITIALIZER(taskq_sys.tq_worklist), #ifdef WITNESS { @@ -84,6 +94,7 @@ struct taskq taskq_sys_mp = { TASKQ_MPSAFE, taskq_sys_mp_name, MUTEX_INITIALIZER(IPL_HIGH), + SLIST_HEAD_INITIALIZER(taskq_sys_mp.tq_threads), TAILQ_HEAD_INITIALIZER(taskq_sys_mp.tq_worklist), #ifdef WITNESS { @@ -131,6 +152,7 @@ taskq_create(const char *name, unsigned tq->tq_flags = flags; mtx_init_flags(&tq->tq_mtx, ipl, name, 0); + SLIST_INIT(&tq->tq_threads); TAILQ_INIT(&tq->tq_worklist); #ifdef WITNESS @@ -220,13 +242,22 @@ taskq_create_thread(void *arg) mtx_leave(&tq->tq_mtx); } -void -taskq_barrier(struct taskq *tq) +static void +taskq_do_barrier(struct taskq *tq) { struct cond c = COND_INITIALIZER(); struct task t = TASK_INITIALIZER(taskq_barrier_task, &c); + struct proc *thread = curproc; + struct taskq_thread *tt; - WITNESS_CHECKORDER(&tq->tq_lock_object, LOP_NEWORDER, NULL); + mtx_enter(&tq->tq_mtx); + SLIST_FOREACH(tt, &tq->tq_threads, tt_entry) { + if (tt->tt_thread == thread) + break; + } + mtx_leave(&tq->tq_mtx); + if (tt != NULL) + return; SET(t.t_flags, TASK_BARRIER); task_add(tq, &t); @@ -234,19 +265,22 @@ taskq_barrier(struct taskq *tq) } void -taskq_del_barrier(struct taskq *tq, struct task *del) +taskq_barrier(struct taskq *tq) { - struct cond c = COND_INITIALIZER(); - struct task t = TASK_INITIALIZER(taskq_barrier_task, &c); + WITNESS_CHECKORDER(&tq->tq_lock_object, LOP_NEWORDER, NULL); + + taskq_do_barrier(tq); +} +void +taskq_del_barrier(struct taskq *tq, struct task *t) +{ WITNESS_CHECKORDER(&tq->tq_lock_object, LOP_NEWORDER, NULL); - if (task_del(tq, del)) + if (task_del(tq, t)) return; - SET(t.t_flags, TASK_BARRIER); - task_add(tq, &t); - cond_wait(&c, "tqbar"); + taskq_do_barrier(tq); } void @@ -354,6 +388,7 @@ retry: void taskq_thread(void *xtq) { + struct taskq_thread self = { .tt_thread = curproc }; struct taskq *tq = xtq; struct task work; int last; @@ -361,6 +396,10 @@ taskq_thread(void *xtq) if (ISSET(tq->tq_flags, TASKQ_MPSAFE)) KERNEL_UNLOCK(); + mtx_enter(&tq->tq_mtx); + SLIST_INSERT_HEAD(&tq->tq_threads, &self, tt_entry); + mtx_leave(&tq->tq_mtx); + WITNESS_CHECKORDER(&tq->tq_lock_object, LOP_NEWORDER, NULL); while (taskq_next_work(tq, &work)) { @@ -371,6 +410,7 @@ taskq_thread(void *xtq) } mtx_enter(&tq->tq_mtx); + SLIST_REMOVE(&tq->tq_threads, &self, taskq_thread, tt_entry); last = (--tq->tq_running == 0); mtx_leave(&tq->tq_mtx);