diff options
| author | riastradh <riastradh@NetBSD.org> | 2021-12-31 14:22:10 +0000 |
|---|---|---|
| committer | riastradh <riastradh@NetBSD.org> | 2021-12-31 14:22:10 +0000 |
| commit | 2cf4e92a9f6aa33edcc7d984ecce97e38d561afa (patch) | |
| tree | 9bd521d2f187cd283fb22701d18beca1840eb01d /sys/dev/sysmon | |
| parent | 1106b4e3b76fcf4699d2ba21aba10c47c7b81066 (diff) | |
sysmon(9): New sysmon_task_queue_barrier(pri) function.
This waits for the completion of all tasks at priority pri or lower
that are currently queued at the time of the call.
Diffstat (limited to 'sys/dev/sysmon')
| -rw-r--r-- | sys/dev/sysmon/sysmon_taskq.c | 91 | ||||
| -rw-r--r-- | sys/dev/sysmon/sysmon_taskq.h | 3 |
2 files changed, 78 insertions, 16 deletions
diff --git a/sys/dev/sysmon/sysmon_taskq.c b/sys/dev/sysmon/sysmon_taskq.c index 81e878a8f4c..56af82f02fc 100644 --- a/sys/dev/sysmon/sysmon_taskq.c +++ b/sys/dev/sysmon/sysmon_taskq.c @@ -1,4 +1,4 @@ -/* $NetBSD: sysmon_taskq.c,v 1.21 2021/12/31 11:05:41 riastradh Exp $ */ +/* $NetBSD: sysmon_taskq.c,v 1.22 2021/12/31 14:22:11 riastradh Exp $ */ /* * Copyright (c) 2001, 2003 Wasabi Systems, Inc. @@ -41,7 +41,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sysmon_taskq.c,v 1.21 2021/12/31 11:05:41 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sysmon_taskq.c,v 1.22 2021/12/31 14:22:11 riastradh Exp $"); #include <sys/param.h> #include <sys/malloc.h> @@ -202,6 +202,26 @@ sysmon_task_queue_thread(void *arg) kthread_exit(0); } +static void +sysmon_task_queue_sched_task(struct sysmon_task *st) +{ + struct sysmon_task *lst; + + mutex_enter(&sysmon_task_queue_mtx); + TAILQ_FOREACH(lst, &sysmon_task_queue, st_list) { + if (st->st_pri > lst->st_pri) { + TAILQ_INSERT_BEFORE(lst, st, st_list); + break; + } + } + + if (lst == NULL) + TAILQ_INSERT_TAIL(&sysmon_task_queue, st, st_list); + + cv_broadcast(&sysmon_task_queue_cv); + mutex_exit(&sysmon_task_queue_mtx); +} + /* * sysmon_task_queue_sched: * @@ -210,7 +230,7 @@ sysmon_task_queue_thread(void *arg) int sysmon_task_queue_sched(u_int pri, void (*func)(void *), void *arg) { - struct sysmon_task *st, *lst; + struct sysmon_task *st; (void)RUN_ONCE(&once_tq, tq_preinit); @@ -229,21 +249,62 @@ sysmon_task_queue_sched(u_int pri, void (*func)(void *), void *arg) st->st_arg = arg; st->st_pri = pri; - mutex_enter(&sysmon_task_queue_mtx); - TAILQ_FOREACH(lst, &sysmon_task_queue, st_list) { - if (st->st_pri > lst->st_pri) { - TAILQ_INSERT_BEFORE(lst, st, st_list); - break; - } - } + sysmon_task_queue_sched_task(st); - if (lst == NULL) - TAILQ_INSERT_TAIL(&sysmon_task_queue, st, st_list); + return 0; +} - cv_broadcast(&sysmon_task_queue_cv); - mutex_exit(&sysmon_task_queue_mtx); +struct tqbarrier { + kmutex_t lock; + kcondvar_t cv; + bool done; +}; - return 0; +static void +tqbarrier_task(void *cookie) +{ + struct tqbarrier *bar = cookie; + + mutex_enter(&bar->lock); + bar->done = true; + cv_broadcast(&bar->cv); + mutex_exit(&bar->lock); +} + +/* + * sysmon_task_queue_barrier: + * + * Wait for the completion of all tasks at priority pri or lower + * currently queued at the time of the call. + */ +void +sysmon_task_queue_barrier(u_int pri) +{ + struct sysmon_task st; + struct tqbarrier bar; + + (void)RUN_ONCE(&once_tq, tq_preinit); + + KASSERT(sysmon_task_queue_lwp); + KASSERT(curlwp != sysmon_task_queue_lwp); + + mutex_init(&bar.lock, MUTEX_DEFAULT, IPL_NONE); + cv_init(&bar.cv, "sysmontq"); + bar.done = false; + + st.st_func = &tqbarrier_task; + st.st_arg = &bar; + st.st_pri = pri; + + sysmon_task_queue_sched_task(&st); + + mutex_enter(&bar.lock); + while (!bar.done) + cv_wait(&bar.cv, &bar.lock); + mutex_exit(&bar.lock); + + cv_destroy(&bar.cv); + mutex_destroy(&bar.lock); } static int diff --git a/sys/dev/sysmon/sysmon_taskq.h b/sys/dev/sysmon/sysmon_taskq.h index 32a4fcd7a2f..821a68d2ee8 100644 --- a/sys/dev/sysmon/sysmon_taskq.h +++ b/sys/dev/sysmon/sysmon_taskq.h @@ -1,4 +1,4 @@ -/* $NetBSD: sysmon_taskq.h,v 1.4 2015/04/27 07:51:28 pgoyette Exp $ */ +/* $NetBSD: sysmon_taskq.h,v 1.5 2021/12/31 14:22:11 riastradh Exp $ */ /* * Copyright (c) 2003 Wasabi Systems, Inc. @@ -41,5 +41,6 @@ void sysmon_task_queue_init(void); int sysmon_task_queue_fini(void); int sysmon_task_queue_sched(u_int, void (*)(void *), void *); +void sysmon_task_queue_barrier(u_int); #endif /* _DEV_SYSMON_SYSMON_TASKQ_H_ */ |
