PERFORCE change 99899 for review

Kip Macy kmacy at FreeBSD.org
Fri Jun 23 22:08:19 UTC 2006


http://perforce.freebsd.org/chv.cgi?CH=99899

Change 99899 by kmacy at kmacy_storage:sun4v_work_sleepq on 2006/06/23 22:07:42

	re-factor MUTEX_PROFILING into the lock object to facilitate use by other lock types

Affected files ...

.. //depot/projects/kmacy_sun4v/src/sys/kern/kern_mutex.c#12 edit
.. //depot/projects/kmacy_sun4v/src/sys/sun4v/include/pcpu.h#16 edit
.. //depot/projects/kmacy_sun4v/src/sys/sys/_lock.h#3 edit
.. //depot/projects/kmacy_sun4v/src/sys/sys/_mutex.h#4 edit

Differences ...

==== //depot/projects/kmacy_sun4v/src/sys/kern/kern_mutex.c#12 (text+ko) ====

@@ -59,6 +59,7 @@
 #include <sys/sysctl.h>
 #include <sys/turnstile.h>
 #include <sys/vmmeter.h>
+#include <sys/lock_profile.h>
 
 #include <machine/atomic.h>
 #include <machine/bus.h>
@@ -156,63 +157,34 @@
 #endif
 
 #ifdef MUTEX_PROFILING
-#include <sys/stdint.h>
-
-#ifndef MPROF_HASH_SIZE
-#define	MPROF_HASH_SIZE		4096
-#define MPROF_HASH_MASK		(MPROF_HASH_SIZE - 1)
-#endif
-struct mutex_prof {
-	const char	*name;
-	const char	*file;
-	u_int		namehash;
-	int		line;
-	uintmax_t	cnt_max;
-	uintmax_t	cnt_tot;
-	uintmax_t	cnt_cur;
-	uintmax_t	cnt_contest_holding;
-	uintmax_t	cnt_contest_locking;
-};
 
 /*
  * mprof_buf is a static pool of profiling records to avoid possible
  * reentrance of the memory allocation functions.
  */
-static struct mutex_prof mprof_buf[MPROF_HASH_SIZE];
-static int allocated_mprof_buf;
+struct mutex_prof mprof_buf[MPROF_HASH_SIZE];
+int allocated_mprof_buf;
 /* SWAG: sbuf size = avg stat. line size * number of locks */
-#define MPROF_SBUF_SIZE		256 * 400
-
-/* We keep a smaller pool of spin mutexes for protecting the mprof hash entries */
-#define MPROF_LOCK_SIZE		16	
-#define MPROF_LOCK_MASK		(MPROF_LOCK_SIZE - 1)
-#define MPROF_LHASH(hash)	((hash) & MPROF_LOCK_MASK)
-
-#define MPROF_LOCK(hash)	mtx_lock_spin(&mprof_locks[MPROF_LHASH(hash)])
-#define MPROF_UNLOCK(hash)	mtx_unlock_spin(&mprof_locks[MPROF_LHASH(hash)])
 struct mtx mprof_locks[MPROF_LOCK_SIZE];
 
 SYSCTL_NODE(_debug, OID_AUTO, mutex, CTLFLAG_RD, NULL, "mutex debugging");
 SYSCTL_NODE(_debug_mutex, OID_AUTO, prof, CTLFLAG_RD, NULL, "mutex profiling");
-static int mutex_prof_enable = 0;
+int mutex_prof_enable = 0;
 SYSCTL_INT(_debug_mutex_prof, OID_AUTO, enable, CTLFLAG_RW,
     &mutex_prof_enable, 0, "Enable tracing of mutex holdtime/contention");
-static int mutex_prof_acquisitions;
-SYSCTL_INT(_debug_mutex_prof, OID_AUTO, acquisitions, CTLFLAG_RD,
-    &mutex_prof_acquisitions, 0, "Number of mutex acquistions recorded");
-static int mutex_prof_records;
+int mutex_prof_records;
 SYSCTL_INT(_debug_mutex_prof, OID_AUTO, records, CTLFLAG_RD,
     &mutex_prof_records, 0, "Number of profiling records");
 static int mutex_prof_maxrecords = MPROF_HASH_SIZE;
 SYSCTL_INT(_debug_mutex_prof, OID_AUTO, maxrecords, CTLFLAG_RD,
     &mutex_prof_maxrecords, 0, "Maximum number of profiling records");
-static int mutex_prof_rejected;
+int mutex_prof_rejected;
 SYSCTL_INT(_debug_mutex_prof, OID_AUTO, rejected, CTLFLAG_RD,
     &mutex_prof_rejected, 0, "Number of rejected profiling records");
 static int mutex_prof_hashsize = MPROF_HASH_SIZE;
 SYSCTL_INT(_debug_mutex_prof, OID_AUTO, hashsize, CTLFLAG_RD,
     &mutex_prof_hashsize, 0, "Hash size");
-static int mutex_prof_collisions = 0;
+int mutex_prof_collisions = 0;
 SYSCTL_INT(_debug_mutex_prof, OID_AUTO, collisions, CTLFLAG_RD,
     &mutex_prof_collisions, 0, "Number of hash collisions");
 #ifdef KTR
@@ -221,148 +193,6 @@
     &stack_scale, 0, "How often to sample stack traces");
 #endif
 
-
-
-static inline void 
-mtx_profile_init(struct mtx *m, const char *name) {
-	const char *p;
-	u_int hash = 0;
-
-	m->mtx_acqtime = 0;
-	m->mtx_filename = NULL;
-	m->mtx_lineno = 0;
-	m->mtx_contest_holding = 0;
-	m->mtx_contest_locking = 0;
-
-	/* Hash the mutex name to an int so we don't have to strcmp() it repeatedly */
-	for (p = name; *p != '\0'; p++)
-		hash = 31 * hash + *p;
-	m->mtx_namehash = hash;
-#if 0
-	if (opts & MTX_PROFILE)
-		m->mtx_stack = stack_create();
-#endif
-}
-
-static inline void 
-mtx_profile_destroy(struct mtx *m) 
-{
-#if 0
-	if (m->mtx_object.lo_flags & LO_PROFILE)
-		stack_destroy(m->mtx_stack);
-#endif
-}
-
-static inline void 
-mutex_profile_init(void) 
-{
-	int i;
-	/* Initialize the mutex profiling locks */
-	for (i = 0; i < MPROF_LOCK_SIZE; i++) {
-		mtx_init(&mprof_locks[i], "mprof lock",
-		    NULL, MTX_SPIN|MTX_QUIET);
-	}
-}
-
-static inline void 
-mtx_profile_obtain_lock_failed(struct mtx *m, int *contested) 
-{
-	if (mutex_prof_enable) {
-		*contested = 1;
-		atomic_add_int(&m->mtx_contest_holding, 1);
-	}
-}
-
-static inline void 
-mtx_profile_obtain_lock_success(struct mtx *m, const char *file, int line) 
-{
-	/* don't reset the timer when/if recursing */
-	if (mutex_prof_enable && m->mtx_acqtime == 0) {
-		m->mtx_filename = file;
-		m->mtx_lineno = line;
-		m->mtx_acqtime = rd(tick); /* substitute for more general TSC read */
-#if 0
-		++mutex_prof_acquisitions;
-#endif
-	}
-}
-
-static void 
-mtx_profile_release_lock(struct mtx *m) 
-{
-
-	if (m->mtx_acqtime) {
-		const char *unknown = "(unknown)";
-		struct mutex_prof *mpp;
-		u_int64_t acqtime, now;
-		u_int hash;
-		const char *p = m->mtx_filename;
-		int collision = 0;
-
-		now = rd(tick);
-		acqtime = m->mtx_acqtime;
-		m->mtx_acqtime = 0;
-		if (now <= acqtime)
-			return;
-		if (p == NULL || *p == '\0')
-			p = unknown;
-		hash = (m->mtx_namehash * 31 * 31 + (uintptr_t)p * 31 + m->mtx_lineno) & MPROF_HASH_MASK;
-		CTR5(KTR_SPARE1, "Hashing %s(%x) %s:%d to %d", mtx_name(m), m->mtx_namehash, p, m->mtx_lineno, hash);
-		mpp = &mprof_buf[hash];
-		while (mpp->name != NULL) {
-			if (mpp->line == m->mtx_lineno &&
-			  mpp->file == p &&
-			  mpp->namehash == m->mtx_namehash)
-				break;
-			/* If the mprof_hash entry is allocated to someone else, try the next one */
-			collision = 1;
-			CTR4(KTR_SPARE1, "Hash collision, %s:%d %s(%x)", mpp->file, mpp->line, mpp->name, mpp->namehash);
-			hash = (hash + 1) & MPROF_HASH_MASK;
-			mpp = &mprof_buf[hash];
-		}
-		if (mpp->name == NULL) {
-			int buf;
-
-			buf = atomic_fetchadd_int(&allocated_mprof_buf, 1);
-			/* Just exit if we cannot get a trace buffer */
-			if (buf >= MPROF_HASH_SIZE) {
-				++mutex_prof_rejected;
-				return;
-			}
-			mpp->file = p;
-			mpp->line = m->mtx_lineno;
-			mpp->name = mtx_name(m);
-			mpp->namehash = m->mtx_namehash;
-			if (collision)
-				++mutex_prof_collisions;
-			/* We might have raced someone else but who cares, they'll try again next time */
-			++mutex_prof_records;
-		}
-		MPROF_LOCK(hash);
-		/*
-		 * Record if the mutex has been held longer now than ever
-		 * before.
-		 */
-		if (now - acqtime > mpp->cnt_max)
-			mpp->cnt_max = now - acqtime;
-		mpp->cnt_tot += now - acqtime;
-		mpp->cnt_cur++;
-		/*
-		 * There's a small race, really we should cmpxchg
-		 * 0 with the current value, but that would bill
-		 * the contention to the wrong lock instance if
-		 * it followed this also.
-		 */
-		mpp->cnt_contest_holding += m->mtx_contest_holding;
-		m->mtx_contest_holding = 0;
-		mpp->cnt_contest_locking += m->mtx_contest_locking;
-		m->mtx_contest_locking = 0;
-		MPROF_UNLOCK(hash);
-	}
-}
-
-
-
 static int
 dump_mutex_prof_stats(SYSCTL_HANDLER_ARGS)
 {
@@ -433,14 +263,6 @@
 SYSCTL_PROC(_debug_mutex_prof, OID_AUTO, reset, CTLTYPE_INT | CTLFLAG_RW,
     NULL, 0, reset_mutex_prof_stats, "I", "Reset mutex profiling statistics");
 
-#else
-static inline void mtx_profile_init(struct mtx *m, const char *name) {;}
-static inline void mtx_profile_destroy(struct mtx *m) {;}
-static inline void mtx_profile_obtain_lock_failed(struct mtx *m, int *contested) {;}
-static inline void mtx_profile_obtain_lock_success(struct mtx *m, const char *file, int line) {;}
-static inline void mtx_profile_release_lock(struct mtx *m) {;}
-
-static inline void mutex_profile_init(void) {;}
 #endif
 
 /*
@@ -461,7 +283,7 @@
 	LOCK_LOG_LOCK("LOCK", &m->mtx_object, opts, m->mtx_recurse, file,
 	    line);
 	WITNESS_LOCK(&m->mtx_object, opts | LOP_EXCLUSIVE, file, line);
-	mtx_profile_obtain_lock_success(m, file, line);
+	mtx_profile_obtain_lock_success(&m->mtx_object, file, line);
 }
 
 void
@@ -477,7 +299,7 @@
 	    line);
 	mtx_assert(m, MA_OWNED);
 
-	mtx_profile_release_lock(m);
+	mtx_profile_release_lock(&m->mtx_object);
 	_rel_sleep_lock(m, curthread, opts, file, line);
 }
 
@@ -580,7 +402,7 @@
 		    m->mtx_object.lo_name, (void *)m->mtx_lock, file, line);
 
 	while (!_obtain_lock(m, tid)) {
-		mtx_profile_obtain_lock_failed(m, &contested);
+		mtx_profile_obtain_lock_failed(&m->mtx_object, &contested);
 		turnstile_lock(&m->mtx_object);
 		v = m->mtx_lock;
 
@@ -664,8 +486,8 @@
 #endif
 #ifdef MUTEX_PROFILING
 	if (mutex_prof_enable) {
-		m->mtx_contest_locking = contested;
-		atomic_store_rel_int(&m->mtx_contest_holding,0);
+		m->mtx_object.lo_profile_obj.lpo_contest_locking = contested;
+		atomic_store_rel_int(&m->mtx_object.lo_profile_obj.lpo_contest_holding, 0);
 	}
 #endif
 	return;
@@ -968,7 +790,7 @@
 	m->mtx_lock = MTX_UNOWNED;
 	m->mtx_recurse = 0;
 
-	mtx_profile_init(m, name);
+	mtx_profile_init(&m->mtx_object, name);
 	lock_init(&m->mtx_object, class, name, type, flags);
 }
 
@@ -996,7 +818,7 @@
 		    __LINE__);
 	}
 	
-	mtx_profile_destroy(m);
+	mtx_profile_destroy(&m->mtx_object);
 	lock_destroy(&m->mtx_object);
 }
 

==== //depot/projects/kmacy_sun4v/src/sys/sun4v/include/pcpu.h#16 (text+ko) ====

@@ -39,6 +39,14 @@
 #define	ALT_STACK_SIZE	128
 
 struct pmap;
+#if defined(WITNESS)
+#define SUN4V_PAD 7
+
+#elif defined(MUTEX_PROFILING)
+#define SUN4V_PAD 4
+#else
+#define SUN4V_PAD 0
+#endif
 
 /*
  * Inside the kernel, the globally reserved register g7 is used to
@@ -79,7 +87,7 @@
 	struct rwindow pc_tsbwbuf[2];                                   \
 	u_int   pc_node;                                                \
         uint16_t pc_cpulist[MAXCPU];                                    \
-        uint64_t pad[7];
+        uint64_t pad[SUN4V_PAD];
 
 	/* XXX SUN4V_FIXME - as we access the *_ra and *_size fields in quick
 	 * succession we _really_ want them to be L1 cache line size aligned

==== //depot/projects/kmacy_sun4v/src/sys/sys/_lock.h#3 (text+ko) ====

@@ -31,14 +31,39 @@
 #ifndef _SYS__LOCK_H_
 #define	_SYS__LOCK_H_
 
+struct lock_profile_object {
+        /*
+         * This does not result in variant structure sizes because
+         * MUTEX_PROFILING is in opt_global.h
+         */
+        u_int64_t               lpo_acqtime;
+        const char              *lpo_filename;
+        u_int                   lpo_namehash;
+        int                     lpo_lineno;
+        /*
+         * Fields relating to measuring contention on mutexes.
+         * holding must be accessed atomically since it's
+         * modified by threads that don't yet hold the mutex.
+         * locking is only modified and referenced while
+         * the mutex is held.
+         */
+        u_int                   lpo_contest_holding;
+        u_int                   lpo_contest_locking;
+};
+
 struct lock_object {
 	const	char *lo_name;		/* Individual lock name. */
 	const	char *lo_type;		/* General lock type. */
 	u_int	lo_flags;
+#ifdef MUTEX_PROFILING
+	struct  lock_profile_object lo_profile_obj;
+#endif
+#ifdef WITNESS
 	union {				/* Data for witness. */
 		STAILQ_ENTRY(lock_object) lod_list;
 		struct	witness *lod_witness;
 	} lo_witness_data;
+#endif
 };
 
 #endif /* !_SYS__LOCK_H_ */

==== //depot/projects/kmacy_sun4v/src/sys/sys/_mutex.h#4 (text+ko) ====

@@ -38,27 +38,6 @@
 	struct lock_object	mtx_object;	/* Common lock properties. */
 	volatile uintptr_t	mtx_lock;	/* Owner and flags. */
 	volatile u_int		mtx_recurse;	/* Number of recursive holds. */
-
-#ifdef MUTEX_PROFILING
-	/*
-	 * This does not result in variant structure sizes because
-	 * MUTEX_PROFILING is in opt_global.h
-	 */
-	u_int64_t		mtx_acqtime;
-	u_int			mtx_namehash;
-	const char		*mtx_filename;
-	int			mtx_lineno;
-	/*
-	 * Fields relating to measuring contention on mutexes.
-	 * holding must be accessed atomically since it's
-	 * modified by threads that don't yet hold the mutex.
-	 * locking is only modified and referenced while
-	 * the mutex is held.
-	 */
-	u_int			mtx_contest_holding;
-	u_int			mtx_contest_locking;
-	struct stack		*mtx_stack;
-#endif
 };
 
 #endif /* !_SYS__MUTEX_H_ */


More information about the p4-projects mailing list