summaryrefslogtreecommitdiff
path: root/sys/dev/sysmon
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/sysmon')
-rw-r--r--sys/dev/sysmon/sysmon_taskq.c91
-rw-r--r--sys/dev/sysmon/sysmon_taskq.h3
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_ */