svn commit: r355231 - head/sys/kern

Mateusz Guzik mjg at FreeBSD.org
Sat Nov 30 17:24:43 UTC 2019


Author: mjg
Date: Sat Nov 30 17:24:42 2019
New Revision: 355231
URL: https://svnweb.freebsd.org/changeset/base/355231

Log:
  lockprof: use IPI-injecetd fences to fix hangs on stat dump and reset
  
  The previously used quiesce_all_cpus walks all CPUs and waits until curthread
  can run on them. Even on contemporary machines this becomes a significant
  problem under load when it can literally take minutes for the operation to
  complete. With the patch the stall is normally less than 1 second.
  
  Reviewed by:	kib, jeff (previous version)
  Sponsored by:	The FreeBSD Foundation
  Differential Revision:	https://reviews.freebsd.org/D21740

Modified:
  head/sys/kern/subr_lock.c

Modified: head/sys/kern/subr_lock.c
==============================================================================
--- head/sys/kern/subr_lock.c	Sat Nov 30 17:22:10 2019	(r355230)
+++ head/sys/kern/subr_lock.c	Sat Nov 30 17:24:42 2019	(r355231)
@@ -324,8 +324,14 @@ lock_prof_reset(void)
 	atomic_store_rel_int(&lock_prof_resetting, 1);
 	enabled = lock_prof_enable;
 	lock_prof_enable = 0;
-	quiesce_all_cpus("profreset", 0);
 	/*
+	 * This both publishes lock_prof_enable as disabled and makes sure
+	 * everyone else reads it if they are not far enough. We wait for the
+	 * rest down below.
+	 */
+	cpus_fence_seq_cst();
+	quiesce_all_critical();
+	/*
 	 * Some objects may have migrated between CPUs.  Clear all links
 	 * before we zero the structures.  Some items may still be linked
 	 * into per-thread lists as well.
@@ -343,6 +349,9 @@ lock_prof_reset(void)
 		lock_prof_init_type(&lpc->lpc_types[0]);
 		lock_prof_init_type(&lpc->lpc_types[1]);
 	}
+	/*
+	 * Paired with the fence from cpus_fence_seq_cst()
+	 */
 	atomic_store_rel_int(&lock_prof_resetting, 0);
 	lock_prof_enable = enabled;
 }
@@ -433,12 +442,17 @@ dump_lock_prof_stats(SYSCTL_HANDLER_ARGS)
 	    "max", "wait_max", "total", "wait_total", "count", "avg", "wait_avg", "cnt_hold", "cnt_lock", "name");
 	enabled = lock_prof_enable;
 	lock_prof_enable = 0;
-	quiesce_all_cpus("profstat", 0);
+	/*
+	 * See the comment in lock_prof_reset
+	 */
+	cpus_fence_seq_cst();
+	quiesce_all_critical();
 	t = ticks;
 	CPU_FOREACH(cpu) {
 		lock_prof_type_stats(&LP_CPU(cpu)->lpc_types[0], sb, 0, t);
 		lock_prof_type_stats(&LP_CPU(cpu)->lpc_types[1], sb, 1, t);
 	}
+	atomic_thread_fence_rel();
 	lock_prof_enable = enabled;
 
 	error = sbuf_finish(sb);
@@ -591,6 +605,10 @@ lock_profile_obtain_lock_success(struct lock_object *l
 	else
 		l->lpo_waittime = 0;
 out:
+	/*
+	 * Paired with cpus_fence_seq_cst().
+	 */
+	atomic_thread_fence_rel();
 	critical_exit();
 }
 
@@ -677,6 +695,10 @@ release:
 	type = &LP_CPU_SELF->lpc_types[spin];
 	LIST_INSERT_HEAD(&type->lpt_lpoalloc, l, lpo_link);
 out:
+	/*
+	 * Paired with cpus_fence_seq_cst().
+	 */
+	atomic_thread_fence_rel();
 	critical_exit();
 }
 


More information about the svn-src-head mailing list