> Date: Tue, 19 Sep 2017 05:44:27 +0000 > From: Taylor R Campbell <campbell+netbsd-tech-k...@mumble.net> > > > Date: Tue, 19 Sep 2017 05:36:40 +0000 > > From: Taylor R Campbell <campbell+netbsd-tech-k...@mumble.net> > > > > 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();