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