Module Name:    src
Committed By:   riastradh
Date:           Sun Feb  9 22:57:27 UTC 2020

Modified Files:
        src/sys/kern: kern_threadpool.c

Log Message:
Teach threadpool(9) to use percpu_create, mostly.


To generate a diff of this commit:
cvs rdiff -u -r1.15 -r1.16 src/sys/kern/kern_threadpool.c

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

Modified files:

Index: src/sys/kern/kern_threadpool.c
diff -u src/sys/kern/kern_threadpool.c:1.15 src/sys/kern/kern_threadpool.c:1.16
--- src/sys/kern/kern_threadpool.c:1.15	Thu Jan 17 10:18:52 2019
+++ src/sys/kern/kern_threadpool.c	Sun Feb  9 22:57:26 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_threadpool.c,v 1.15 2019/01/17 10:18:52 hannken Exp $	*/
+/*	$NetBSD: kern_threadpool.c,v 1.16 2020/02/09 22:57:26 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2014, 2018 The NetBSD Foundation, Inc.
@@ -81,7 +81,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_threadpool.c,v 1.15 2019/01/17 10:18:52 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_threadpool.c,v 1.16 2020/02/09 22:57:26 riastradh Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -132,6 +132,9 @@ static void	threadpool_rele(struct threa
 
 static int	threadpool_percpu_create(struct threadpool_percpu **, pri_t);
 static void	threadpool_percpu_destroy(struct threadpool_percpu *);
+static void	threadpool_percpu_init(void *, void *, struct cpu_info *);
+static void	threadpool_percpu_ok(void *, void *, struct cpu_info *);
+static void	threadpool_percpu_fini(void *, void *, struct cpu_info *);
 
 static threadpool_job_fn_t threadpool_job_dead;
 
@@ -576,80 +579,77 @@ static int
 threadpool_percpu_create(struct threadpool_percpu **pool_percpup, pri_t pri)
 {
 	struct threadpool_percpu *pool_percpu;
-	struct cpu_info *ci;
-	CPU_INFO_ITERATOR cii;
-	unsigned int i, j;
-	int error;
+	bool ok = true;
 
 	pool_percpu = kmem_zalloc(sizeof(*pool_percpu), KM_SLEEP);
-	if (pool_percpu == NULL) {
-		error = ENOMEM;
-		goto fail0;
-	}
 	pool_percpu->tpp_pri = pri;
+	pool_percpu->tpp_percpu = percpu_create(sizeof(struct threadpool *),
+	    threadpool_percpu_init, threadpool_percpu_fini,
+	    (void *)(intptr_t)pri);
 
-	pool_percpu->tpp_percpu = percpu_alloc(sizeof(struct threadpool *));
-	if (pool_percpu->tpp_percpu == NULL) {
-		error = ENOMEM;
-		goto fail1;
-	}
-
-	for (i = 0, CPU_INFO_FOREACH(cii, ci), i++) {
-		struct threadpool *pool;
-
-		pool = kmem_zalloc(sizeof(*pool), KM_SLEEP);
-		error = threadpool_create(pool, ci, pri);
-		if (error) {
-			kmem_free(pool, sizeof(*pool));
-			goto fail2;
-		}
-		percpu_traverse_enter();
-		struct threadpool **const poolp =
-		    percpu_getptr_remote(pool_percpu->tpp_percpu, ci);
-		*poolp = pool;
-		percpu_traverse_exit();
-	}
+	/*
+	 * Verify that all of the CPUs were initialized.
+	 *
+	 * XXX What to do if we add CPU hotplug?
+	 */
+	percpu_foreach(pool_percpu->tpp_percpu, &threadpool_percpu_ok, &ok);
+	if (!ok)
+		goto fail;
 
 	/* Success!  */
 	*pool_percpup = (struct threadpool_percpu *)pool_percpu;
 	return 0;
 
-fail2:	for (j = 0, CPU_INFO_FOREACH(cii, ci), j++) {
-		if (i <= j)
-			break;
-		percpu_traverse_enter();
-		struct threadpool **const poolp =
-		    percpu_getptr_remote(pool_percpu->tpp_percpu, ci);
-		struct threadpool *const pool = *poolp;
-		percpu_traverse_exit();
-		threadpool_destroy(pool);
-		kmem_free(pool, sizeof(*pool));
-	}
-	percpu_free(pool_percpu->tpp_percpu, sizeof(struct taskthread_pool *));
-fail1:	kmem_free(pool_percpu, sizeof(*pool_percpu));
-fail0:	return error;
+fail:	percpu_free(pool_percpu->tpp_percpu, sizeof(struct threadpool *));
+	kmem_free(pool_percpu, sizeof(*pool_percpu));
+	return ENOMEM;
 }
 
 static void
 threadpool_percpu_destroy(struct threadpool_percpu *pool_percpu)
 {
-	struct cpu_info *ci;
-	CPU_INFO_ITERATOR cii;
-
-	for (CPU_INFO_FOREACH(cii, ci)) {
-		percpu_traverse_enter();
-		struct threadpool **const poolp =
-		    percpu_getptr_remote(pool_percpu->tpp_percpu, ci);
-		struct threadpool *const pool = *poolp;
-		percpu_traverse_exit();
-		threadpool_destroy(pool);
-		kmem_free(pool, sizeof(*pool));
-	}
 
 	percpu_free(pool_percpu->tpp_percpu, sizeof(struct threadpool *));
 	kmem_free(pool_percpu, sizeof(*pool_percpu));
 }
 
+static void
+threadpool_percpu_init(void *vpoolp, void *vpri, struct cpu_info *ci)
+{
+	struct threadpool **const poolp = vpoolp;
+	pri_t pri = (intptr_t)(void *)vpri;
+	int error;
+
+	*poolp = kmem_zalloc(sizeof(**poolp), KM_SLEEP);
+	error = threadpool_create(*poolp, ci, pri);
+	if (error) {
+		KASSERT(error == ENOMEM);
+		kmem_free(*poolp, sizeof(**poolp));
+		*poolp = NULL;
+	}
+}
+
+static void
+threadpool_percpu_ok(void *vpoolp, void *vokp, struct cpu_info *ci)
+{
+	struct threadpool **const poolp = vpoolp;
+	bool *okp = vokp;
+
+	if (*poolp == NULL)
+		atomic_store_relaxed(okp, false);
+}
+
+static void
+threadpool_percpu_fini(void *vpoolp, void *vprip, struct cpu_info *ci)
+{
+	struct threadpool **const poolp = vpoolp;
+
+	if (*poolp == NULL)	/* initialization failed */
+		return;
+	threadpool_destroy(*poolp);
+	kmem_free(*poolp, sizeof(**poolp));
+}
+
 /* Thread pool jobs */
 
 void __printflike(4,5)

Reply via email to