Super User's BSD Cross Reference: /OpenBSD/usr.sbin/unbound/testcode/checklocks.h

1 /**
2 * testcode/checklocks.h - wrapper on locks that checks access.
3 *
4 * Copyright (c) 2007, NLnet Labs. All rights reserved.
5 *
6 * This software is open source.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 *
15 * Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 *
19 * Neither the name of the NLNET LABS nor the names of its contributors may
20 * be used to endorse or promote products derived from this software without
21 * specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36#ifndef TESTCODE_CHECK_LOCKS_H
37#define TESTCODE_CHECK_LOCKS_H
38
39 /**
40 * \file
41 * Locks that are checked.
42 *
43 * Holds information per lock and per thread.
44 * That information is protected by a mutex (unchecked).
45 *
46 * Checks:
47 * o which func, file, line created the lock.
48 * o contention count, measures amount of contention on the lock.
49 * o the memory region(s) that the lock protects are
50 * memcmp'ed to ascertain no race conditions.
51 * o checks that locks are unlocked properly (before deletion).
52 * keeps which func, file, line that locked it.
53 * o checks deadlocks with timeout so it can print errors for them.
54 *
55 * Limitations:
56 * o Detects unprotected memory access when the lock is locked or freed,
57 * which detects races only if they happen, and only if in protected
58 * memory areas.
59 * o Detects deadlocks by timeout, so approximately, as they happen.
60 * o Does not check order of locking.
61 * o Uses a lot of memory.
62 * o The checks use locks themselves, changing scheduling,
63 * thus changing what races you see.
64 */
65
66#ifdef USE_THREAD_DEBUG
67#ifndef HAVE_PTHREAD
68 /* we need the *timed*lock() routines to use for deadlock detection. */
69#error "Need pthreads for checked locks"
70#endif
71 /******************* THREAD DEBUG ************************/
72#include <pthread.h>
73
74 /** How many threads to allocate for */
75#define THRDEBUG_MAX_THREADS 32 /* threads */
76 /** do we check locking order */
77 extern int check_locking_order;
78
79 /**
80 * Protection memory area.
81 * It is copied to a holding buffer to compare against later.
82 * Note that it may encompass the lock structure.
83 */
84 struct protected_area {
85 /** where the memory region starts */
86 void* region;
87 /** size of the region */
88 size_t size;
89 /** backbuffer that holds a copy, of same size. */
90 void* hold;
91 /** next protected area in list */
92 struct protected_area* next;
93 /** the place where the lock_protect is made, at init. */
94 const char* def_func;
95 /** the file where the lock_protect is made */
96 const char* def_file;
97 /** the line number where the lock_protect is made */
98 int def_line;
99 /** the text string for the area that is protected, at init call. */
100 const char* def_area;
101};
102
103 /**
104 * Per thread information for locking debug wrappers.
105 */
106 struct thr_check {
107 /** thread id */
108 pthread_t id;
109 /** real thread func */
110 void* (*func)(void*);
111 /** func user arg */
112 void* arg;
113 /** number of thread in list structure */
114 int num;
115 /** instance number - how many locks have been created by thread */
116 int locks_created;
117 /** file to write locking order information to */
118 FILE* order_info;
119 /**
120 * List of locks that this thread is holding, double
121 * linked list. The first element is the most recent lock acquired.
122 * So it represents the stack of locks acquired. (of all types).
123 */
124 struct checked_lock *holding_first, *holding_last;
125 /** if the thread is currently waiting for a lock, which one */
126 struct checked_lock* waiting;
127};
128
129 /**
130 * One structure for all types of locks.
131 */
132 struct checked_lock {
133 /** mutex for exclusive access to this structure */
134 pthread_mutex_t lock;
135 /** list of memory regions protected by this checked lock */
136 struct protected_area* prot;
137 /** where was this lock created */
138 const char* create_func, *create_file;
139 /** where was this lock created */
140 int create_line;
141 /** unique instance identifier */
142 int create_thread, create_instance;
143 /** contention count */
144 size_t contention_count;
145 /** number of times locked, ever */
146 size_t history_count;
147 /** hold count (how many threads are holding this lock) */
148 int hold_count;
149 /** how many threads are waiting for this lock */
150 int wait_count;
151 /** who touched it last */
152 const char* holder_func, *holder_file;
153 /** who touched it last */
154 int holder_line;
155 /** who owns the lock now */
156 struct thr_check* holder;
157 /** for rwlocks, the writelock holder */
158 struct thr_check* writeholder;
159
160 /** next lock a thread is holding (less recent) */
161 struct checked_lock* next_held_lock[THRDEBUG_MAX_THREADS];
162 /** prev lock a thread is holding (more recent) */
163 struct checked_lock* prev_held_lock[THRDEBUG_MAX_THREADS];
164
165 /** type of lock */
166 enum check_lock_type {
167 /** basic mutex */
168 check_lock_mutex,
169 /** fast spinlock */
170 check_lock_spinlock,
171 /** rwlock */
172 check_lock_rwlock
173 } type;
174 /** the lock itself, see type to disambiguate the union */
175 union {
176 /** mutex */
177 pthread_mutex_t mutex;
178 /** spinlock */
179 pthread_spinlock_t spinlock;
180 /** rwlock */
181 pthread_rwlock_t rwlock;
182 } u;
183};
184
185 /**
186 * Additional call for the user to specify what areas are protected
187 * @param lock: the lock that protects the area. It can be inside the area.
188 * The lock must be inited. Call with user lock. (any type).
189 * It demangles the lock itself (struct checked_lock**).
190 * @param area: ptr to mem.
191 * @param size: length of area.
192 * @param def_func: function where the lock_protect() line is.
193 * @param def_file: file where the lock_protect() line is.
194 * @param def_line: line where the lock_protect() line is.
195 * @param def_area: area string
196 * You can call it multiple times with the same lock to give several areas.
197 * Call it when you are done initializing the area, since it will be copied
198 * at this time and protected right away against unauthorised changes until
199 * the next lock() call is done.
200 */
201 void lock_protect_place(void* lock, void* area, size_t size,
202 const char* def_func, const char* def_file, int def_line,
203 const char* def_area);
204#define lock_protect(lock, area, size) lock_protect_place(lock, area, size, __func__, __FILE__, __LINE__, #area)
205
206 /**
207 * Remove protected area from lock.
208 * No need to call this when deleting the lock.
209 * @param lock: the lock, any type, (struct checked_lock**).
210 * @param area: pointer to memory.
211 */
212 void lock_unprotect(void* lock, void* area);
213
214 /**
215 * Get memory associated with a checked lock
216 * @param lock: the checked lock, any type. (struct checked_lock**).
217 * @return: in bytes, including protected areas.
218 */
219 size_t lock_get_mem(void* lock);
220
221 /**
222 * Set the output name, prefix, of the lock check output file(s).
223 * Call it before the checklock_start or thread creation. Pass a fixed string.
224 * @param name: string to use for output data file names.
225 */
226 void checklock_set_output_name(const char* name);
227
228 /**
229 * Initialise checklock. Sets up internal debug structures.
230 */
231 void checklock_start(void);
232
233 /**
234 * Cleanup internal debug state.
235 */
236 void checklock_stop(void);
237
238 /**
239 * Init locks.
240 * @param type: what type of lock this is.
241 * @param lock: ptr to user alloced ptr structure. This is inited.
242 * So an alloc is done and the ptr is stored as result.
243 * @param func: caller function name.
244 * @param file: caller file name.
245 * @param line: caller line number.
246 */
247 void checklock_init(enum check_lock_type type, struct checked_lock** lock,
248 const char* func, const char* file, int line);
249
250 /**
251 * Destroy locks. Free the structure.
252 * @param type: what type of lock this is.
253 * @param lock: ptr to user alloced structure. This is destroyed.
254 * @param func: caller function name.
255 * @param file: caller file name.
256 * @param line: caller line number.
257 */
258 void checklock_destroy(enum check_lock_type type, struct checked_lock** lock,
259 const char* func, const char* file, int line);
260
261 /**
262 * Acquire readlock.
263 * @param type: what type of lock this is. Had better be a rwlock.
264 * @param lock: ptr to lock.
265 * @param func: caller function name.
266 * @param file: caller file name.
267 * @param line: caller line number.
268 */
269 void checklock_rdlock(enum check_lock_type type, struct checked_lock* lock,
270 const char* func, const char* file, int line);
271
272 /**
273 * Acquire writelock.
274 * @param type: what type of lock this is. Had better be a rwlock.
275 * @param lock: ptr to lock.
276 * @param func: caller function name.
277 * @param file: caller file name.
278 * @param line: caller line number.
279 */
280 void checklock_wrlock(enum check_lock_type type, struct checked_lock* lock,
281 const char* func, const char* file, int line);
282
283 /**
284 * Locks.
285 * @param type: what type of lock this is. Had better be mutex or spinlock.
286 * @param lock: the lock.
287 * @param func: caller function name.
288 * @param file: caller file name.
289 * @param line: caller line number.
290 */
291 void checklock_lock(enum check_lock_type type, struct checked_lock* lock,
292 const char* func, const char* file, int line);
293
294 /**
295 * Unlocks.
296 * @param type: what type of lock this is.
297 * @param lock: the lock.
298 * @param func: caller function name.
299 * @param file: caller file name.
300 * @param line: caller line number.
301 */
302 void checklock_unlock(enum check_lock_type type, struct checked_lock* lock,
303 const char* func, const char* file, int line);
304
305 /**
306 * Create thread.
307 * @param thr: Thread id, where to store result.
308 * @param func: thread start function.
309 * @param arg: user argument.
310 */
311 void checklock_thrcreate(pthread_t* thr, void* (*func)(void*), void* arg);
312
313 /**
314 * Wait for thread to exit. Returns thread return value.
315 * @param thread: thread to wait for.
316 */
317 void checklock_thrjoin(pthread_t thread);
318
319 /** structures to enable compiler type checking on the locks.
320 * Also the pointer makes it so that the lock can be part of the protected
321 * region without any possible problem (since the ptr will stay the same.)
322 * i.e. there can be contention and readlocks stored in checked_lock, while
323 * the protected area stays the same, even though it contains (ptr to) lock.
324 */
325 struct checked_lock_rw { struct checked_lock* c_rw; };
326 /** structures to enable compiler type checking on the locks. */
327 struct checked_lock_mutex { struct checked_lock* c_m; };
328 /** structures to enable compiler type checking on the locks. */
329 struct checked_lock_spl { struct checked_lock* c_spl; };
330
331 /** debugging rwlock */
332 typedef struct checked_lock_rw lock_rw_type;
333#define lock_rw_init(lock) checklock_init(check_lock_rwlock, &((lock)->c_rw), __func__, __FILE__, __LINE__)
334#define lock_rw_destroy(lock) checklock_destroy(check_lock_rwlock, &((lock)->c_rw), __func__, __FILE__, __LINE__)
335#define lock_rw_rdlock(lock) checklock_rdlock(check_lock_rwlock, (lock)->c_rw, __func__, __FILE__, __LINE__)
336#define lock_rw_wrlock(lock) checklock_wrlock(check_lock_rwlock, (lock)->c_rw, __func__, __FILE__, __LINE__)
337#define lock_rw_unlock(lock) checklock_unlock(check_lock_rwlock, (lock)->c_rw, __func__, __FILE__, __LINE__)
338
339 /** debugging mutex */
340 typedef struct checked_lock_mutex lock_basic_type;
341#define lock_basic_init(lock) checklock_init(check_lock_mutex, &((lock)->c_m), __func__, __FILE__, __LINE__)
342#define lock_basic_destroy(lock) checklock_destroy(check_lock_mutex, &((lock)->c_m), __func__, __FILE__, __LINE__)
343#define lock_basic_lock(lock) checklock_lock(check_lock_mutex, (lock)->c_m, __func__, __FILE__, __LINE__)
344#define lock_basic_unlock(lock) checklock_unlock(check_lock_mutex, (lock)->c_m, __func__, __FILE__, __LINE__)
345
346 /** debugging spinlock */
347 typedef struct checked_lock_spl lock_quick_type;
348#define lock_quick_init(lock) checklock_init(check_lock_spinlock, &((lock)->c_spl), __func__, __FILE__, __LINE__)
349#define lock_quick_destroy(lock) checklock_destroy(check_lock_spinlock, &((lock)->c_spl), __func__, __FILE__, __LINE__)
350#define lock_quick_lock(lock) checklock_lock(check_lock_spinlock, (lock)->c_spl, __func__, __FILE__, __LINE__)
351#define lock_quick_unlock(lock) checklock_unlock(check_lock_spinlock, (lock)->c_spl, __func__, __FILE__, __LINE__)
352
353 /** we use the pthread id, our thr_check structure is kept behind the scenes */
354 typedef pthread_t ub_thread_type;
355#define ub_thread_create(thr, func, arg) checklock_thrcreate(thr, func, arg)
356#define ub_thread_self() pthread_self()
357#define ub_thread_join(thread) checklock_thrjoin(thread)
358
359 typedef pthread_key_t ub_thread_key_type;
360#define ub_thread_key_create(key, f) LOCKRET(pthread_key_create(key, f))
361#define ub_thread_key_set(key, v) LOCKRET(pthread_setspecific(key, v))
362#define ub_thread_key_get(key) pthread_getspecific(key)
363
364#endif /* USE_THREAD_DEBUG */
365#endif /* TESTCODE_CHECK_LOCKS_H */
366 

AltStyle によって変換されたページ (->オリジナル) /