lock_profile.h revision 164167
1/*- 2 * Copyright (c) 2006 Kip Macy kmacy@FreeBSD.org 3 * Copyright (c) 2006 Dag-Erling Smorgrav des@des.no 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHAL THE AUTHORS BE LIABLE FOR ANY 18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: head/sys/sys/lock_profile.h 164167 2006-11-11 07:52:38Z kmacy $ 27 */ 28 29 30#ifndef _SYS_LOCK_PROFILE_H_ 31#define _SYS_LOCK_PROFILE_H_ 32 33#ifdef LOCK_PROFILING 34#include <sys/stdint.h> 35#include <sys/ktr.h> 36#include <sys/mutex.h> 37#include <machine/cpufunc.h> 38 39#ifndef LPROF_HASH_SIZE 40#define LPROF_HASH_SIZE 4096 41#define LPROF_HASH_MASK (LPROF_HASH_SIZE - 1) 42#endif 43 44#ifndef USE_CPU_NANOSECONDS 45u_int64_t nanoseconds(void); 46#endif 47 48struct lock_prof { 49 const char *name; 50 const char *file; 51 u_int namehash; 52 int line; 53 uintmax_t cnt_max; 54 uintmax_t cnt_tot; 55 uintmax_t cnt_wait; 56 uintmax_t cnt_cur; 57 uintmax_t cnt_contest_holding; 58 uintmax_t cnt_contest_locking; 59}; 60 61extern struct lock_prof lprof_buf[LPROF_HASH_SIZE]; 62extern int allocated_lprof_buf; 63#define LPROF_SBUF_SIZE 256 * 400 64 65/* We keep a smaller pool of spin mutexes for protecting the lprof hash entries */ 66#define LPROF_LOCK_SIZE 16 67#define LPROF_LOCK_MASK (LPROF_LOCK_SIZE - 1) 68#define LPROF_LHASH(hash) ((hash) & LPROF_LOCK_MASK) 69 70#define LPROF_LOCK(hash) mtx_lock_spin(&lprof_locks[LPROF_LHASH(hash)]) 71#define LPROF_UNLOCK(hash) mtx_unlock_spin(&lprof_locks[LPROF_LHASH(hash)]) 72 73extern struct mtx lprof_locks[LPROF_LOCK_SIZE]; 74extern int lock_prof_enable; 75extern int lock_prof_records; 76extern int lock_prof_rejected; 77extern int lock_prof_collisions; 78 79void _lock_profile_obtain_lock_success(struct lock_object *lo, uint64_t waittime, const char *file, int line); 80void _lock_profile_update_wait(struct lock_object *lo, uint64_t waitstart); 81void _lock_profile_release_lock(struct lock_object *lo); 82 83static inline void lock_profile_init(void) 84{ 85 int i; 86 /* Initialize the mutex profiling locks */ 87 for (i = 0; i < LPROF_LOCK_SIZE; i++) { 88 mtx_init(&lprof_locks[i], "mprof lock", 89 NULL, MTX_SPIN|MTX_QUIET|MTX_NOPROFILE); 90 } 91} 92 93static inline void lock_profile_object_init(struct lock_object *lo, const char *name) { 94 const char *p; 95 u_int hash = 0; 96 struct lock_profile_object *l = &lo->lo_profile_obj; 97 98 lo->lo_flags = 0; 99 lo->lo_name = name; 100 l->lpo_acqtime = 0; 101 l->lpo_waittime = 0; 102 l->lpo_filename = NULL; 103 l->lpo_lineno = 0; 104 l->lpo_contest_holding = 0; 105 l->lpo_contest_locking = 0; 106 107 /* Hash the mutex name to an int so we don't have to strcmp() it repeatedly */ 108 for (p = name; *p != '\0'; p++) 109 hash = 31 * hash + *p; 110 l->lpo_namehash = hash; 111#if 0 112 if (opts & MTX_PROFILE) 113 l->lpo_stack = stack_create(); 114#endif 115} 116 117 118static inline void 119lock_profile_object_destroy(struct lock_object *lo) 120{ 121#if 0 122 struct lock_profile_object *l = &lo->lo_profile_obj; 123 if (lo->lo_flags & LO_PROFILE) 124 stack_destroy(l->lpo_stack); 125#endif 126} 127 128static inline void lock_profile_waitstart(uint64_t *waittime) 129{ 130 if (lock_prof_enable) 131 *waittime = nanoseconds(); 132} 133 134static inline void lock_profile_obtain_lock_failed(struct lock_object *lo, int *contested) 135{ 136 struct lock_profile_object *l = &lo->lo_profile_obj; 137 if (lock_prof_enable) { 138 *contested = 1; 139 atomic_add_int(&l->lpo_contest_holding, 1); 140 } 141} 142 143static inline void lock_profile_obtain_lock_success(struct lock_object *lo, uint64_t waittime, const char *file, int line) 144{ 145 if (lock_prof_enable) 146 _lock_profile_obtain_lock_success(lo, waittime, file, line); 147} 148 149static inline void lock_profile_update_wait(struct lock_object *lo, uint64_t waitstart) 150{ 151 if (lock_prof_enable) 152 _lock_profile_update_wait(lo, waitstart); 153} 154 155static inline void lock_profile_release_lock(struct lock_object *lo) 156{ 157 struct lock_profile_object *l = &lo->lo_profile_obj; 158 if (lock_prof_enable || l->lpo_acqtime) 159 _lock_profile_release_lock(lo); 160} 161 162#else /* !LOCK_PROFILING */ 163 164static inline void lock_profile_init(void) {;} 165static inline void lock_profile_update_wait(struct lock_object *lo, uint64_t waitstart) {;} 166static inline void lock_profile_waitstart(uint64_t *waittime) {;} 167static inline void lock_profile_release_lock(struct lock_object *lo) {;} 168static inline void lock_profile_obtain_lock_failed(struct lock_object *lo, int *contested) {;} 169static inline void lock_profile_obtain_lock_success(struct lock_object *lo, uint64_t waittime, 170 const char *file, int line) {;} 171static inline void lock_profile_object_destroy(struct lock_object *lo) {;} 172static inline void lock_profile_object_init(struct lock_object *lo, const char *name) {;} 173 174#endif /* !LOCK_PROFILING */ 175 176#endif /* _SYS_LOCK_PROFILE_H_ */ 177