tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: RFC: PERCPU_LIST to fix PR kern/52515
> Date: Tue, 19 Sep 2017 05:44:27 +0000
> From: Taylor R Campbell <campbell+netbsd-tech-kern%mumble.net@localhost>
>
> > Date: Tue, 19 Sep 2017 05:36:40 +0000
> > From: Taylor R Campbell <campbell+netbsd-tech-kern%mumble.net@localhost>
> >
> > I've attached a small patch that might serve as a quicker stop-gap
> > (untested). It's gross, but it doesn't change the ABI, add any header
> > files, &c.
>
> I made sure to forget to attach it so I could keep my klutz
> credentials, but here's the standard followup with the actual
> attachment.
To increase my chances of passing the Klutz^2 certification test, I
mistyped the MIME type of the attachment as `application/pdf'. Here
it is as plain text. (Unless I'm going for a summa klutz laude
degree.)
diff --git a/sys/kern/subr_psref.c b/sys/kern/subr_psref.c
index c3f76ab0e743..bd393def5a4c 100644
--- a/sys/kern/subr_psref.c
+++ b/sys/kern/subr_psref.c
@@ -251,6 +251,7 @@ psref_acquire(struct psref *psref, const struct psref_target *target,
/* Record our reference. */
LIST_INSERT_HEAD(&pcpu->pcpu_head, psref, psref_entry);
+ psref->psref_entry.le_prev = NULL; /* XXX see psref_release */
psref->psref_target = target;
psref->psref_lwp = curlwp;
psref->psref_cpu = curcpu();
@@ -297,12 +298,33 @@ psref_release(struct psref *psref, const struct psref_target *target,
/*
* Block interrupts and remove the psref from the current CPU's
- * list. No need to percpu_getref or get the head of the list,
- * and the caller guarantees that we are bound to a CPU anyway
- * (as does blocking interrupts).
+ * list. No need to percpu_getref or get the head of the list
+ * unless we turn out to be removing the head of the list, and
+ * the caller guarantees that we are bound to a CPU anyway (as
+ * does blocking interrupts).
*/
s = splraiseipl(class->prc_iplcookie);
- LIST_REMOVE(psref, psref_entry);
+ /* XXX begin abstraction violation */
+ /*
+ * XXX We cannot reliably use &pcpu->pcpu_head.lh_first,
+ * because percpu(9) may move it around when allocating other
+ * per-CPU storage. But LIST_REMOVE relies on *le_prev
+ * working. So work around it by getting the prev-pointer from
+ * the percpu if we're at the head of the list.
+ */
+ if (psref->psref_entry.le_prev != NULL) {
+ LIST_REMOVE(psref, psref_entry);
+ } else {
+ struct psref_cpu *pcpu;
+
+ if (LIST_NEXT(psref, psref_entry) != NULL)
+ LIST_NEXT(psref, psref_entry)->psref_entry.le_prev =
+ psref->psref_entry.le_prev;
+ pcpu = perpcu_getref(class->prc_percpu);
+ pcpu->pcpu_head.lh_first = LIST_NEXT(psref, psref_entry);
+ percpu_putref(class->prc_percpu);
+ }
+ /* XXX end abstraction violation */
splx(s);
/* If someone is waiting for users to drain, notify 'em. */
@@ -354,6 +376,7 @@ psref_copy(struct psref *pto, const struct psref *pfrom,
/* Record the new reference. */
LIST_INSERT_HEAD(&pcpu->pcpu_head, pto, psref_entry);
+ pto->psref_entry.le_prev = NULL; /* XXX see psref_release */
pto->psref_target = pfrom->psref_target;
pto->psref_lwp = curlwp;
pto->psref_cpu = curcpu();
Home |
Main Index |
Thread Index |
Old Index