Module Name:    src
Committed By:   riastradh
Date:           Sun Dec 19 11:57:34 UTC 2021

Modified Files:
        src/sys/external/bsd/common/linux: linux_tasklet.c

Log Message:
linux: Use indirection for percpu simpleq.

Simpleq requires pointers into the head to work, but percpu(9) may
move objects around, so we have to allocate the simpleq head
separately with kmem(9).


To generate a diff of this commit:
cvs rdiff -u -r1.7 -r1.8 src/sys/external/bsd/common/linux/linux_tasklet.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/external/bsd/common/linux/linux_tasklet.c
diff -u src/sys/external/bsd/common/linux/linux_tasklet.c:1.7 src/sys/external/bsd/common/linux/linux_tasklet.c:1.8
--- src/sys/external/bsd/common/linux/linux_tasklet.c:1.7	Sun Dec 19 11:49:11 2021
+++ src/sys/external/bsd/common/linux/linux_tasklet.c	Sun Dec 19 11:57:34 2021
@@ -1,7 +1,7 @@
-/*	$NetBSD: linux_tasklet.c,v 1.7 2021/12/19 11:49:11 riastradh Exp $	*/
+/*	$NetBSD: linux_tasklet.c,v 1.8 2021/12/19 11:57:34 riastradh Exp $	*/
 
 /*-
- * Copyright (c) 2018, 2020 The NetBSD Foundation, Inc.
+ * Copyright (c) 2018, 2020, 2021 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
@@ -30,13 +30,14 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_tasklet.c,v 1.7 2021/12/19 11:49:11 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_tasklet.c,v 1.8 2021/12/19 11:57:34 riastradh Exp $");
 
 #include <sys/types.h>
 #include <sys/atomic.h>
 #include <sys/cpu.h>
 #include <sys/errno.h>
 #include <sys/intr.h>
+#include <sys/kmem.h>
 #include <sys/lock.h>
 #include <sys/percpu.h>
 #include <sys/queue.h>
@@ -51,7 +52,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux_taskle
 #define	TASKLET_RUNNING		((unsigned)__BIT(1))
 
 struct tasklet_queue {
-	struct percpu	*tq_percpu;	/* struct tasklet_cpu */
+	struct percpu	*tq_percpu;	/* struct tasklet_cpu * */
 	void		*tq_sih;
 };
 
@@ -114,6 +115,25 @@ linux_tasklets_fini(void)
 	tasklet_queue_fini(&tasklet_queue);
 }
 
+static void
+tasklet_cpu_init(void *ptr, void *cookie, struct cpu_info *ci)
+{
+	struct tasklet_cpu **tcp = ptr, *tc;
+
+	*tcp = tc = kmem_zalloc(sizeof(*tc), KM_SLEEP);
+	SIMPLEQ_INIT(&tc->tc_head);
+}
+
+static void
+tasklet_cpu_fini(void *ptr, void *cookie, struct cpu_info *ci)
+{
+	struct tasklet_cpu **tcp = ptr, *tc = *tcp;
+
+	KASSERT(SIMPLEQ_EMPTY(&tc->tc_head));
+	kmem_free(tc, sizeof(*tc));
+	*tcp = NULL;		/* paranoia */
+}
+
 /*
  * tasklet_queue_init(tq, prio)
  *
@@ -126,7 +146,8 @@ tasklet_queue_init(struct tasklet_queue 
 	int error;
 
 	/* Allocate per-CPU memory.  percpu_alloc cannot fail.  */
-	tq->tq_percpu = percpu_alloc(sizeof(struct tasklet_cpu));
+	tq->tq_percpu = percpu_create(sizeof(struct tasklet_cpu),
+	    tasklet_cpu_init, tasklet_cpu_fini, NULL);
 	KASSERT(tq->tq_percpu != NULL);
 
 	/* Try to establish a softint.  softint_establish may fail.  */
@@ -177,7 +198,7 @@ tasklet_softintr(void *cookie)
 {
 	struct tasklet_queue *const tq = cookie;
 	struct tasklet_head th = SIMPLEQ_HEAD_INITIALIZER(th);
-	struct tasklet_cpu *tc;
+	struct tasklet_cpu **tcp, *tc;
 	int s;
 
 	/*
@@ -186,7 +207,8 @@ tasklet_softintr(void *cookie)
 	 *
 	 * No memory barriers: CPU-local state only.
 	 */
-	tc = percpu_getref(tq->tq_percpu);
+	tcp = percpu_getref(tq->tq_percpu);
+	tc = *tcp;
 	s = splhigh();
 	SIMPLEQ_CONCAT(&th, &tc->tc_head);
 	splx(s);
@@ -282,7 +304,7 @@ tasklet_queue_schedule(struct tasklet_qu
 static void
 tasklet_queue_enqueue(struct tasklet_queue *tq, struct tasklet_struct *tasklet)
 {
-	struct tasklet_cpu *tc;
+	struct tasklet_cpu **tcp, *tc;
 	int s;
 
 	KASSERT(atomic_load_relaxed(&tasklet->tl_state) & TASKLET_SCHEDULED);
@@ -292,7 +314,8 @@ tasklet_queue_enqueue(struct tasklet_que
 	 * blocked, and schedule a soft interrupt to process it.  No
 	 * memory barriers: CPU-local state only.
 	 */
-	tc = percpu_getref(tq->tq_percpu);
+	tcp = percpu_getref(tq->tq_percpu);
+	tc = *tcp;
 	s = splhigh();
 	SIMPLEQ_INSERT_TAIL(&tc->tc_head, tasklet, tl_entry);
 	splx(s);

Reply via email to