From owner-p4-projects@FreeBSD.ORG Fri Jun 23 22:08:18 2006 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id CFF9F16A47E; Fri, 23 Jun 2006 22:08:18 +0000 (UTC) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 850C916A47B for ; Fri, 23 Jun 2006 22:08:18 +0000 (UTC) (envelope-from kmacy@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id B39D843D45 for ; Fri, 23 Jun 2006 22:08:17 +0000 (GMT) (envelope-from kmacy@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.6/8.13.6) with ESMTP id k5NM8Hx8063749 for ; Fri, 23 Jun 2006 22:08:17 GMT (envelope-from kmacy@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.6/8.13.4/Submit) id k5NM8H2X063746 for perforce@freebsd.org; Fri, 23 Jun 2006 22:08:17 GMT (envelope-from kmacy@freebsd.org) Date: Fri, 23 Jun 2006 22:08:17 GMT Message-Id: <200606232208.k5NM8H2X063746@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to kmacy@freebsd.org using -f From: Kip Macy To: Perforce Change Reviews Cc: Subject: PERFORCE change 99899 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 23 Jun 2006 22:08:19 -0000 http://perforce.freebsd.org/chv.cgi?CH=99899 Change 99899 by kmacy@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 #include #include +#include #include #include @@ -156,63 +157,34 @@ #endif #ifdef MUTEX_PROFILING -#include - -#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_ */