Index | Thread | Search

From:
Martin Pieuchot <mpi@grenadille.net>
Subject:
Use a FIFO for the reaper
To:
tech@openbsd.org
Date:
Wed, 14 May 2025 18:54:57 +0200

Download raw body.

Thread
Instead of adding dead threads at the head of the deadproc list insert
them at the tail.

This improve latency and reduce variance when building with 24 CPUs.

While here remove a comment talking about per-CPU reapers.

ok?

Index: kern/kern_exit.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_exit.c,v
diff -u -p -r1.245 kern_exit.c
--- kern/kern_exit.c	2 May 2025 05:04:38 -0000	1.245
+++ kern/kern_exit.c	14 May 2025 16:12:52 -0000
@@ -257,7 +257,7 @@ exit1(struct proc *p, int xexit, int xsi
         /*
 	 * Remove proc from pidhash chain and allproc so looking
 	 * it up won't work.  We will put the proc on the
-	 * deadproc list later (using the p_hash member), and
+	 * deadproc list later (using the p_runq member), and
 	 * wake up the reaper when we do.  If this is the last
 	 * thread of a process that isn't PS_NOZOMBIE, we'll put
 	 * the process on the zombprocess list below.
@@ -396,21 +396,21 @@ exit1(struct proc *p, int xexit, int xsi
 }
 
 /*
- * Locking of this proclist is special; it's accessed in a
+ * Locking of this prochead is special; it's accessed in a
  * critical section of process exit, and thus locking it can't
  * modify interrupt state.  We use a simple spin lock for this
- * proclist.  We use the p_hash member to linkup to deadproc.
+ * prochead.  We use the p_runq member to linkup to deadproc.
  */
 struct mutex deadproc_mutex =
     MUTEX_INITIALIZER_FLAGS(IPL_NONE, "deadproc", MTX_NOWITNESS);
-struct proclist deadproc = LIST_HEAD_INITIALIZER(deadproc);
+struct prochead deadproc = TAILQ_HEAD_INITIALIZER(deadproc);
 
 /*
  * We are called from sched_idle() once it is safe to schedule the
  * dead process's resources to be freed. So this is not allowed to sleep.
  *
  * We lock the deadproc list, place the proc on that list (using
- * the p_hash member), and wake up the reaper.
+ * the p_runq member), and wake up the reaper.
  */
 void
 exit2(struct proc *p)
@@ -421,7 +421,7 @@ exit2(struct proc *p)
 	mtx_leave(&p->p_p->ps_mtx);
 
 	mtx_enter(&deadproc_mutex);
-	LIST_INSERT_HEAD(&deadproc, p, p_hash);
+	TAILQ_INSERT_TAIL(&deadproc, p, p_runq);
 	mtx_leave(&deadproc_mutex);
 
 	wakeup(&deadproc);
@@ -451,12 +451,12 @@ reaper(void *arg)
 
 	for (;;) {
 		mtx_enter(&deadproc_mutex);
-		while ((p = LIST_FIRST(&deadproc)) == NULL)
+		while ((p = TAILQ_FIRST(&deadproc)) == NULL)
 			msleep_nsec(&deadproc, &deadproc_mutex, PVM, "reaper",
 			    INFSLP);
 
 		/* Remove us from the deadproc list. */
-		LIST_REMOVE(p, p_hash);
+		TAILQ_REMOVE(&deadproc, p, p_runq);
 		mtx_leave(&deadproc_mutex);
 
 		WITNESS_THREAD_EXIT(p);
Index: kern/kern_sched.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_sched.c,v
diff -u -p -r1.104 kern_sched.c
--- kern/kern_sched.c	10 Mar 2025 09:28:56 -0000	1.104
+++ kern/kern_sched.c	14 May 2025 16:12:52 -0000
@@ -95,7 +95,7 @@ sched_init_cpu(struct cpu_info *ci)
 
 	kthread_create_deferred(sched_kthreads_create, ci);
 
-	LIST_INIT(&spc->spc_deadproc);
+	TAILQ_INIT(&spc->spc_deadproc);
 	SIMPLEQ_INIT(&spc->spc_deferred);
 
 	/*
@@ -167,8 +167,8 @@ sched_idle(void *v)
 			mi_switch();
 			SCHED_UNLOCK();
 
-			while ((dead = LIST_FIRST(&spc->spc_deadproc))) {
-				LIST_REMOVE(dead, p_hash);
+			while ((dead = TAILQ_FIRST(&spc->spc_deadproc))) {
+				TAILQ_REMOVE(&spc->spc_deadproc, dead, p_runq);
 				exit2(dead);
 			}
 		}
@@ -206,15 +206,13 @@ sched_idle(void *v)
  * stack torn from under us before we manage to switch to another proc.
  * Therefore we have a per-cpu list of dead processes where we put this
  * proc and have idle clean up that list and move it to the reaper list.
- * All this will be unnecessary once we can bind the reaper this cpu
- * and not risk having it switch to another in case it sleeps.
  */
 void
 sched_exit(struct proc *p)
 {
 	struct schedstate_percpu *spc = &curcpu()->ci_schedstate;
 
-	LIST_INSERT_HEAD(&spc->spc_deadproc, p, p_hash);
+	TAILQ_INSERT_TAIL(&spc->spc_deadproc, p, p_runq);
 
 	tuagg_add_runtime();
 
Index: sys/sched.h
===================================================================
RCS file: /cvs/src/sys/sys/sched.h,v
diff -u -p -r1.73 sched.h
--- sys/sched.h	8 Jul 2024 14:46:47 -0000	1.73
+++ sys/sched.h	14 May 2025 16:12:52 -0000
@@ -108,7 +108,7 @@ struct smr_entry;
 struct schedstate_percpu {
 	struct proc *spc_idleproc;	/* idle proc for this cpu */
 	TAILQ_HEAD(prochead, proc) spc_qs[SCHED_NQS];
-	LIST_HEAD(,proc) spc_deadproc;
+	TAILQ_HEAD(,proc) spc_deadproc;
 	struct timespec spc_runtime;	/* time curproc started running */
 	volatile int spc_schedflags;	/* flags; see below */
 	u_int spc_schedticks;		/* ticks for schedclock() */