diff options
author | mtm <mtm@FreeBSD.org> | 2003-02-25 22:28:46 +0000 |
---|---|---|
committer | mtm <mtm@FreeBSD.org> | 2003-02-25 22:28:46 +0000 |
commit | 3a9a3e5e4dff444ec02ee0ad550ccb53883afa7c (patch) | |
tree | da245b1dba1b3d0e309f69aa20ded687c6b80714 /sys/kern/kern_mutex.c | |
parent | cf6c58298298caeb25b29001ebbd42d321e1964d (diff) | |
download | FreeBSD-src-3a9a3e5e4dff444ec02ee0ad550ccb53883afa7c.zip FreeBSD-src-3a9a3e5e4dff444ec02ee0ad550ccb53883afa7c.tar.gz |
Unbreak mutex profiling (at least for me).
o Always check for null when dereferencing the filename component.
o Implement a try-and-backoff method for allocating memory to
dump stats to avoid a spin-lock -> sleep-lock mutex lock order
panic with WITNESS.
Approved by: des, markm (mentor)
Not objected: jhb
Diffstat (limited to 'sys/kern/kern_mutex.c')
-rw-r--r-- | sys/kern/kern_mutex.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/sys/kern/kern_mutex.c b/sys/kern/kern_mutex.c index b9a9099..039621b 100644 --- a/sys/kern/kern_mutex.c +++ b/sys/kern/kern_mutex.c @@ -235,6 +235,8 @@ static struct mutex_prof mprof_buf[NUM_MPROF_BUFFERS]; static int first_free_mprof_buf; #define MPROF_HASH_SIZE 1009 static struct mutex_prof *mprof_hash[MPROF_HASH_SIZE]; +/* SWAG: sbuf size = avg stat. line size * number of locks */ +#define MPROF_SBUF_SIZE 256 * 400 static int mutex_prof_acquisitions; SYSCTL_INT(_debug_mutex_prof, OID_AUTO, acquisitions, CTLFLAG_RD, @@ -275,12 +277,14 @@ dump_mutex_prof_stats(SYSCTL_HANDLER_ARGS) { struct sbuf *sb; int error, i; + static int multiplier = 1; if (first_free_mprof_buf == 0) return (SYSCTL_OUT(req, "No locking recorded", sizeof("No locking recorded"))); - sb = sbuf_new(NULL, NULL, 1024, SBUF_AUTOEXTEND); +retry_sbufops: + sb = sbuf_new(NULL, NULL, MPROF_SBUF_SIZE * multiplier, SBUF_FIXEDLEN); sbuf_printf(sb, "%6s %12s %11s %5s %s\n", "max", "total", "count", "avg", "name"); /* @@ -290,7 +294,7 @@ dump_mutex_prof_stats(SYSCTL_HANDLER_ARGS) * computation here). */ mtx_lock_spin(&mprof_mtx); - for (i = 0; i < first_free_mprof_buf; ++i) + for (i = 0; i < first_free_mprof_buf; ++i) { sbuf_printf(sb, "%6ju %12ju %11ju %5ju %s:%d (%s)\n", mprof_buf[i].cnt_max / 1000, mprof_buf[i].cnt_tot / 1000, @@ -298,6 +302,13 @@ dump_mutex_prof_stats(SYSCTL_HANDLER_ARGS) mprof_buf[i].cnt_cur == 0 ? (uintmax_t)0 : mprof_buf[i].cnt_tot / (mprof_buf[i].cnt_cur * 1000), mprof_buf[i].file, mprof_buf[i].line, mprof_buf[i].name); + if (sbuf_overflowed(sb)) { + mtx_unlock_spin(&mprof_mtx); + sbuf_delete(sb); + multiplier++; + goto retry_sbufops; + } + } mtx_unlock_spin(&mprof_mtx); sbuf_finish(sb); error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1); @@ -360,7 +371,8 @@ _mtx_unlock_flags(struct mtx *m, int opts, const char *file, int line) m->mtx_acqtime = 0; if (now <= acqtime) goto out; - for (p = m->mtx_filename; strncmp(p, "../", 3) == 0; p += 3) + for (p = m->mtx_filename; + p != NULL && strncmp(p, "../", 3) == 0; p += 3) /* nothing */ ; if (p == NULL || *p == '\0') p = unknown; |