Index: sys/task.h =================================================================== RCS file: /cvs/src/sys/sys/task.h,v retrieving revision 1.13 diff -u -p -r1.13 task.h --- sys/task.h 16 Dec 2018 03:36:02 -0000 1.13 +++ sys/task.h 29 Mar 2019 05:18:26 -0000 @@ -20,6 +20,7 @@ #define _SYS_TASK_H_ #include +#include struct taskq; @@ -43,9 +44,23 @@ TAILQ_HEAD(task_list, task); extern struct taskq *const systq; extern struct taskq *const systqmp; -struct taskq *taskq_create(const char *, unsigned int, int, unsigned int); +struct taskq *_taskq_create(const char *, unsigned int, int, unsigned int + LOCK_FL_VARS); +void _taskq_barrier(struct taskq * + LOCK_FL_VARS); +void _taskq_del_barrier(struct taskq *, struct task * + LOCK_FL_VARS); + +#define taskq_create(_nm, _n, _ipl, _fl) \ + _taskq_create((_nm), (_n), (_ipl), (_fl) LOCK_FILE_LINE) + +#define taskq_barrier(_tq) \ + _taskq_barrier((_tq) LOCK_FILE_LINE) + +#define taskq_del_barrier(_tq, _t) \ + _taskq_del_barrier((_tq), (_t) LOCK_FILE_LINE) + 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: kern/kern_task.c =================================================================== RCS file: /cvs/src/sys/kern/kern_task.c,v retrieving revision 1.23 diff -u -p -r1.23 kern_task.c --- kern/kern_task.c 16 Dec 2018 03:36:02 -0000 1.23 +++ kern/kern_task.c 29 Mar 2019 05:18:26 -0000 @@ -23,6 +23,18 @@ #include #include #include +#include + +#ifdef WITNESS + +static struct lock_type taskq_lock_type = { + .lt_name = "taskq" +}; + +#define TASKQ_LOCK_FLAGS LO_WITNESS | LO_INITIALIZED | LO_SLEEPABLE | \ + (LO_CLASS_RWLOCK << LO_CLASSSHIFT) + +#endif /* WITNESS */ struct taskq { enum { @@ -37,26 +49,51 @@ struct taskq { struct mutex tq_mtx; struct task_list tq_worklist; +#ifdef WITNESS + struct lock_object tq_lock_object; + const char *tq_lock_file; + unsigned int tq_lock_line; +#endif }; +static const char taskq_sys_name[] = "systq"; + struct taskq taskq_sys = { TQ_S_CREATED, 0, 1, 0, - "systq", + taskq_sys_name, MUTEX_INITIALIZER(IPL_HIGH), - TAILQ_HEAD_INITIALIZER(taskq_sys.tq_worklist) + TAILQ_HEAD_INITIALIZER(taskq_sys.tq_worklist), +#ifdef WITNESS + { + .lo_name = taskq_sys_name, + .lo_flags = TASKQ_LOCK_FLAGS, + }, + __FILE__, + __LINE__, +#endif }; +static const char taskq_sys_mp_name[] = "systqmp"; + struct taskq taskq_sys_mp = { TQ_S_CREATED, 0, 1, TASKQ_MPSAFE, - "systqmp", + taskq_sys_mp_name, MUTEX_INITIALIZER(IPL_HIGH), - TAILQ_HEAD_INITIALIZER(taskq_sys_mp.tq_worklist) + TAILQ_HEAD_INITIALIZER(taskq_sys_mp.tq_worklist), +#ifdef WITNESS + { + .lo_name = taskq_sys_mp_name, + .lo_flags = TASKQ_LOCK_FLAGS, + }, + __FILE__, + __LINE__, +#endif }; typedef int (*sleepfn)(const volatile void *, struct mutex *, int, @@ -76,13 +113,15 @@ void taskq_thread(void *); void taskq_init(void) { + WITNESS_INIT(&systq->tq_lock_object, &taskq_lock_type); kthread_create_deferred(taskq_create_thread, systq); + WITNESS_INIT(&systqmp->tq_lock_object, &taskq_lock_type); kthread_create_deferred(taskq_create_thread, systqmp); } struct taskq * -taskq_create(const char *name, unsigned int nthreads, int ipl, - unsigned int flags) +_taskq_create(const char *name, unsigned int nthreads, int ipl, + unsigned int flags LOCK_FL_VARS) { struct taskq *tq; @@ -99,6 +138,15 @@ taskq_create(const char *name, unsigned mtx_init_flags(&tq->tq_mtx, ipl, name, 0); TAILQ_INIT(&tq->tq_worklist); +#ifdef WITNESS + bzero(&tq->tq_lock_object, sizeof(tq->tq_lock_object)); + tq->tq_lock_object.lo_name = name; + tq->tq_lock_object.lo_flags = TASKQ_LOCK_FLAGS; + tq->tq_lock_file = file; + tq->tq_lock_line = line; + witness_init(&tq->tq_lock_object, &taskq_lock_type); +#endif + /* try to create a thread to guarantee that tasks will be serviced */ kthread_create_deferred(taskq_create_thread, tq); @@ -179,13 +227,31 @@ taskq_create_thread(void *arg) } void -taskq_barrier(struct taskq *tq) +_taskq_barrier(struct taskq *tq LOCK_FL_VARS) { struct cond c = COND_INITIALIZER(); struct task t = TASK_INITIALIZER(taskq_barrier_task, &c); + WITNESS_CHECKORDER(&tq->tq_lock_object, LOP_NEWORDER, + file, line, NULL); + task_add(tq, &t); + cond_wait(&c, "tqbar"); +} +void +_taskq_del_barrier(struct taskq *tq, struct task *del LOCK_FL_VARS) +{ + struct cond c = COND_INITIALIZER(); + struct task t = TASK_INITIALIZER(taskq_barrier_task, &c); + + WITNESS_CHECKORDER(&tq->tq_lock_object, LOP_NEWORDER, + file, line, NULL); + + if (task_del(tq, del)) + return; + + task_add(tq, &t); cond_wait(&c, "tqbar"); } @@ -304,8 +370,15 @@ taskq_thread(void *xtq) atomic_setbits_int(&curproc->p_flag, P_CANTSLEEP); } + WITNESS_CHECKORDER(&tq->tq_lock_object, LOP_NEWORDER, + tq->tq_lock_file, tq->tq_lock_line, NULL); + while (taskq_next_work(tq, &work, tqsleep)) { + WITNESS_LOCK(&tq->tq_lock_object, 0, + tq->tq_lock_file, tq->tq_lock_line); (*work.t_func)(work.t_arg); + WITNESS_UNLOCK(&tq->tq_lock_object, 0, + tq->tq_lock_file, tq->tq_lock_line); sched_pause(yield); }