Module Name:    src
Committed By:   hannken
Date:           Tue Jun 11 09:05:33 UTC 2019

Modified Files:
        src/external/cddl/osnet/sys/kern: taskq.c

Log Message:
There is no 1:1 relation between cv_signal() and cv_timedwait() as
the latter implicitly calls cv_signal() on error.

This leads to "tq_waiting > 0" with "tq_running == 0" and the
taskq stalls.

Change task_executor() to increment and decrement "tq_waiting"
and always check and run the queue after cv_timedwait().

Use mstohz(), fix timeout and sort includes.

Addresses PR port-xen/54273: "zpool create pool xbd2" panics DOMU kernel


To generate a diff of this commit:
cvs rdiff -u -r1.9 -r1.10 src/external/cddl/osnet/sys/kern/taskq.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/external/cddl/osnet/sys/kern/taskq.c
diff -u src/external/cddl/osnet/sys/kern/taskq.c:1.9 src/external/cddl/osnet/sys/kern/taskq.c:1.10
--- src/external/cddl/osnet/sys/kern/taskq.c:1.9	Tue May  7 08:49:59 2019
+++ src/external/cddl/osnet/sys/kern/taskq.c	Tue Jun 11 09:05:33 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: taskq.c,v 1.9 2019/05/07 08:49:59 hannken Exp $	*/
+/*	$NetBSD: taskq.c,v 1.10 2019/06/11 09:05:33 hannken Exp $	*/
 
 /*-
  * Copyright (c) 2019 The NetBSD Foundation, Inc.
@@ -30,9 +30,11 @@
  */
 
 #include <sys/types.h>
-#include <sys/mutex.h>
+#include <sys/param.h>
 #include <sys/kcondvar.h>
+#include <sys/kernel.h>
 #include <sys/kmem.h>
+#include <sys/mutex.h>
 #include <sys/proc.h>
 #include <sys/threadpool.h>
 
@@ -65,7 +67,7 @@ static specificdata_key_t taskq_lwp_key;
 
 /*
  * Threadpool job to service tasks from task queue.
- * Runs until the task queue gets destroyed or the queue is empty for 5 secs.
+ * Runs until the task queue gets destroyed or the queue is empty for 10 secs.
  */
 static void
 task_executor(struct threadpool_job *job)
@@ -73,22 +75,27 @@ task_executor(struct threadpool_job *job
 	struct taskq_executor *state = (struct taskq_executor *)job;
 	taskq_t *tq = state->te_self;
 	taskq_ent_t *tqe; 
+	int error;
 
 	lwp_setspecific(taskq_lwp_key, tq);
 
 	mutex_enter(&tq->tq_lock);
 	while (!tq->tq_destroyed) {
-		tqe = SIMPLEQ_FIRST(&tq->tq_list);
-		if (tqe == NULL) {
+		if (SIMPLEQ_EMPTY(&tq->tq_list)) {
 			if (ISSET(tq->tq_flags, TASKQ_DYNAMIC))
 				break;
 			tq->tq_waiting++;
-			if (cv_timedwait(&tq->tq_cv, &tq->tq_lock, 5000) != 0) {
-				tq->tq_waiting--;
-				break;
+			error = cv_timedwait(&tq->tq_cv, &tq->tq_lock,
+			    mstohz(10000));
+			tq->tq_waiting--;
+			if (SIMPLEQ_EMPTY(&tq->tq_list)) {
+				if (error)
+					break;
+				continue;
 			}
-			continue;
 		}
+		tqe = SIMPLEQ_FIRST(&tq->tq_list);
+		KASSERT(tqe != NULL);
 		SIMPLEQ_REMOVE_HEAD(&tq->tq_list, tqent_list);
 		tqe->tqent_queued = 0;
 		mutex_exit(&tq->tq_lock);
@@ -144,7 +151,6 @@ taskq_dispatch_common(taskq_t *tq, taskq
 	tq->tq_active++;
 	if (tq->tq_waiting) {
 		cv_signal(&tq->tq_cv);
-		tq->tq_waiting--;
 		mutex_exit(&tq->tq_lock);
 		return;
 	}

Reply via email to