git: 3a68546d2377 - main - quisce_cpus(): add special handling for PDROP

Konstantin Belousov kib at FreeBSD.org
Mon May 31 15:10:44 UTC 2021


The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=3a68546d2377d6e9776060043372d66f07022543

commit 3a68546d2377d6e9776060043372d66f07022543
Author:     Konstantin Belousov <kib at FreeBSD.org>
AuthorDate: 2021-05-28 17:10:47 +0000
Commit:     Konstantin Belousov <kib at FreeBSD.org>
CommitDate: 2021-05-31 15:09:22 +0000

    quisce_cpus(): add special handling for PDROP
    
    Currently passing PDROP to the quisce_cpus() function does not make sense.
    Add special meaning for it, by not waiting for the idle thread to schedule.
    
    Also avoid allocating u_int[MAXCPU] on the stack.
    
    Reviewed by:    hselasky, markj
    Sponsored by:   Mellanox Technologies/NVidia Networking
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D30468
---
 sys/kern/subr_smp.c | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/sys/kern/subr_smp.c b/sys/kern/subr_smp.c
index d4f8aac9e751..935fb6ee977c 100644
--- a/sys/kern/subr_smp.c
+++ b/sys/kern/subr_smp.c
@@ -943,25 +943,31 @@ smp_rendezvous_cpus_done(struct smp_rendezvous_cpus_retry_arg *arg)
 }
 
 /*
+ * If (prio & PDROP) == 0:
  * Wait for specified idle threads to switch once.  This ensures that even
  * preempted threads have cycled through the switch function once,
  * exiting their codepaths.  This allows us to change global pointers
  * with no other synchronization.
+ * If (prio & PDROP) != 0:
+ * Force the specified CPUs to switch context at least once.
  */
 int
 quiesce_cpus(cpuset_t map, const char *wmesg, int prio)
 {
 	struct pcpu *pcpu;
-	u_int gen[MAXCPU];
+	u_int *gen;
 	int error;
 	int cpu;
 
 	error = 0;
-	for (cpu = 0; cpu <= mp_maxid; cpu++) {
-		if (!CPU_ISSET(cpu, &map) || CPU_ABSENT(cpu))
-			continue;
-		pcpu = pcpu_find(cpu);
-		gen[cpu] = pcpu->pc_idlethread->td_generation;
+	if ((prio & PDROP) == 0) {
+		gen = malloc(sizeof(u_int) * MAXCPU, M_TEMP, M_WAITOK);
+		for (cpu = 0; cpu <= mp_maxid; cpu++) {
+			if (!CPU_ISSET(cpu, &map) || CPU_ABSENT(cpu))
+				continue;
+			pcpu = pcpu_find(cpu);
+			gen[cpu] = pcpu->pc_idlethread->td_generation;
+		}
 	}
 	for (cpu = 0; cpu <= mp_maxid; cpu++) {
 		if (!CPU_ISSET(cpu, &map) || CPU_ABSENT(cpu))
@@ -970,8 +976,10 @@ quiesce_cpus(cpuset_t map, const char *wmesg, int prio)
 		thread_lock(curthread);
 		sched_bind(curthread, cpu);
 		thread_unlock(curthread);
+		if ((prio & PDROP) != 0)
+			continue;
 		while (gen[cpu] == pcpu->pc_idlethread->td_generation) {
-			error = tsleep(quiesce_cpus, prio, wmesg, 1);
+			error = tsleep(quiesce_cpus, prio & ~PDROP, wmesg, 1);
 			if (error != EWOULDBLOCK)
 				goto out;
 			error = 0;
@@ -981,6 +989,8 @@ out:
 	thread_lock(curthread);
 	sched_unbind(curthread);
 	thread_unlock(curthread);
+	if ((prio & PDROP) == 0)
+		free(gen, M_TEMP);
 
 	return (error);
 }


More information about the dev-commits-src-all mailing list