Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/external/bsd/common/linux linux: Use indirection for per...



details:   https://anonhg.NetBSD.org/src/rev/338ea76ba159
branches:  trunk
changeset: 1028758:338ea76ba159
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Sun Dec 19 11:57:34 2021 +0000

description:
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).

diffstat:

 sys/external/bsd/common/linux/linux_tasklet.c |  41 +++++++++++++++++++++-----
 1 files changed, 32 insertions(+), 9 deletions(-)

diffs (112 lines):

diff -r 4d3a484c726d -r 338ea76ba159 sys/external/bsd/common/linux/linux_tasklet.c
--- a/sys/external/bsd/common/linux/linux_tasklet.c     Sun Dec 19 11:57:27 2021 +0000
+++ b/sys/external/bsd/common/linux/linux_tasklet.c     Sun Dec 19 11:57:34 2021 +0000
@@ -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 @@
 #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 @@
        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 @@
        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 @@
 {
        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 @@
         *
         * 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 @@
 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 @@
         * 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);



Home | Main Index | Thread Index | Old Index