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