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);