From c00e3ee5947324bc41b88ad8619d4c3992b60d9b Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh@NetBSD.org>
Date: Thu, 10 Mar 2022 00:55:42 +0000
Subject: [PATCH 1/2] kern: Use atomic_store_release/atomic_load_consume for
 pid_table.

This is read without the lock, so ordering is required.
---
 sys/kern/kern_proc.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index 90f383ef0fd8..dc5a3d7400fc 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -695,7 +695,7 @@ proc_find_lwp(proc_t *p, pid_t pid)
 	 * memory barrier for dependent loads on alpha.
 	 */
 	s = pserialize_read_enter();
-	pt = &pid_table[pid & pid_tbl_mask];
+	pt = &atomic_load_consume(&pid_table)[pid & pid_tbl_mask];
 	slot = atomic_load_consume(&pt->pt_slot);
 	if (__predict_false(!PT_IS_LWP(slot))) {
 		pserialize_read_exit(s);
@@ -753,7 +753,7 @@ proc_find_lwp_unlocked(proc_t *p, pid_t pid)
 	 * care to read the slot atomically and only once.  This issues a
 	 * memory barrier for dependent loads on alpha.
 	 */
-	pt = &pid_table[pid & pid_tbl_mask];
+	pt = &atomic_load_consume(&pid_table)[pid & pid_tbl_mask];
 	slot = atomic_load_consume(&pt->pt_slot);
 	if (__predict_false(!PT_IS_LWP(slot))) {
 		return NULL;
@@ -1003,7 +1003,7 @@ expand_pid_table(void)
 	/* Save old table size and switch tables */
 	tsz = pt_size * sizeof(struct pid_table);
 	n_pt = pid_table;
-	pid_table = new_pt;
+	atomic_store_release(&pid_table, new_pt);
 	pid_tbl_mask = new_pt_mask;
 
 	/*

From 0975b0fcc8a998909ef7b89e1119a7ddbd742a9e Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh@NetBSD.org>
Date: Thu, 10 Mar 2022 00:57:02 +0000
Subject: [PATCH 2/2] kern: Use atomic_store_release for pid_table::pt_slot.

Not clear the necessary membar was issued in proc_alloc_pid.  Fewer
store-release once at boot, not a big deal.
---
 sys/kern/kern_proc.c | 15 +++------------
 1 file changed, 3 insertions(+), 12 deletions(-)

diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index dc5a3d7400fc..fdbb3338cff8 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -1083,7 +1083,7 @@ proc_alloc_pid_slot(struct proc *p, uintptr_t slot)
 				    p != &proc0)) {
 			KASSERT(PT_IS_PROC(slot));
 			pt = &pid_table[1];
-			pt->pt_slot = slot;
+			atomic_store_release(&pt->pt_slot, slot);
 			return 1;
 		}
 		pt = &pid_table[next_free_pt];
@@ -1107,7 +1107,7 @@ proc_alloc_pid_slot(struct proc *p, uintptr_t slot)
 	KASSERT(pid <= FUTEX_TID_MASK);
 
 	/* Grab table slot */
-	pt->pt_slot = slot;
+	atomic_store_release(&pt->pt_slot, slot);
 
 	KASSERT(pt->pt_pid == 0);
 	pt->pt_pid = pid;
@@ -1143,15 +1143,6 @@ proc_alloc_lwpid(struct proc *p, struct lwp *l)
 	KASSERT(l->l_proc == p);
 	KASSERT(l->l_stat == LSIDL);
 
-	/*
-	 * For unlocked lookup in proc_find_lwp(), make sure l->l_proc
-	 * is globally visible before the LWP becomes visible via the
-	 * pid_table.
-	 */
-#ifndef __HAVE_ATOMIC_AS_MEMBAR
-	membar_producer();
-#endif
-
 	/*
 	 * If the slot for p->p_pid currently points to the proc,
 	 * then we should usurp this ID for the LWP.  This happens
@@ -1166,7 +1157,7 @@ proc_alloc_lwpid(struct proc *p, struct lwp *l)
 	if (PT_IS_PROC(pt->pt_slot)) {
 		KASSERT(PT_GET_PROC(pt->pt_slot) == p);
 		l->l_lid = pid;
-		pt->pt_slot = PT_SET_LWP(l);
+		atomic_store_release(&pt->pt_slot, PT_SET_LWP(l));
 	} else {
 		/* Need to allocate a new slot. */
 		pid = proc_alloc_pid_slot(p, PT_SET_LWP(l));