2 * testcode/checklocks.h - wrapper on locks that checks access.
4 * Copyright (c) 2007, NLnet Labs. All rights reserved.
6 * This software is open source.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
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.
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.
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.
36 #ifndef TESTCODE_CHECK_LOCKS_H
37 #define TESTCODE_CHECK_LOCKS_H
41 * Locks that are checked.
43 * Holds information per lock and per thread.
44 * That information is protected by a mutex (unchecked).
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.
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
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.
66 #ifdef USE_THREAD_DEBUG
68 /* we need the *timed*lock() routines to use for deadlock detection. */
69 #error "Need pthreads for checked locks"
71 /******************* THREAD DEBUG ************************/
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
;
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.
84 struct protected_area
{
85 /** where the memory region starts */
87 /** size of the region */
89 /** backbuffer that holds a copy, of same size. */
91 /** next protected area in list */
92 struct protected_area
* next
;
96 * Per thread information for locking debug wrappers.
101 /** real thread func */
102 void* (*func
)(void*);
105 /** number of thread in list structure */
107 /** instance number - how many locks have been created by thread */
109 /** file to write locking order information to */
112 * List of locks that this thread is holding, double
113 * linked list. The first element is the most recent lock acquired.
114 * So it represents the stack of locks acquired. (of all types).
116 struct checked_lock
*holding_first
, *holding_last
;
117 /** if the thread is currently waiting for a lock, which one */
118 struct checked_lock
* waiting
;
122 * One structure for all types of locks.
124 struct checked_lock
{
125 /** mutex for exclusive access to this structure */
126 pthread_mutex_t lock
;
127 /** list of memory regions protected by this checked lock */
128 struct protected_area
* prot
;
129 /** where was this lock created */
130 const char* create_func
, *create_file
;
131 /** where was this lock created */
133 /** unique instance identifier */
134 int create_thread
, create_instance
;
135 /** contention count */
136 size_t contention_count
;
137 /** number of times locked, ever */
138 size_t history_count
;
139 /** hold count (how many threads are holding this lock) */
141 /** how many threads are waiting for this lock */
143 /** who touched it last */
144 const char* holder_func
, *holder_file
;
145 /** who touched it last */
147 /** who owns the lock now */
148 struct thr_check
* holder
;
149 /** for rwlocks, the writelock holder */
150 struct thr_check
* writeholder
;
152 /** next lock a thread is holding (less recent) */
153 struct checked_lock
* next_held_lock
[THRDEBUG_MAX_THREADS
];
154 /** prev lock a thread is holding (more recent) */
155 struct checked_lock
* prev_held_lock
[THRDEBUG_MAX_THREADS
];
158 enum check_lock_type
{
166 /** the lock itself, see type to disambiguate the union */
169 pthread_mutex_t mutex
;
171 pthread_spinlock_t spinlock
;
173 pthread_rwlock_t rwlock
;
178 * Additional call for the user to specify what areas are protected
179 * @param lock: the lock that protects the area. It can be inside the area.
180 * The lock must be inited. Call with user lock. (any type).
181 * It demangles the lock itself (struct checked_lock**).
182 * @param area: ptr to mem.
183 * @param size: length of area.
184 * You can call it multiple times with the same lock to give several areas.
185 * Call it when you are done initialising the area, since it will be copied
186 * at this time and protected right away against unauthorised changes until
187 * the next lock() call is done.
189 void lock_protect(void* lock
, void* area
, size_t size
);
192 * Remove protected area from lock.
193 * No need to call this when deleting the lock.
194 * @param lock: the lock, any type, (struct checked_lock**).
195 * @param area: pointer to memory.
197 void lock_unprotect(void* lock
, void* area
);
200 * Get memory associated with a checked lock
201 * @param lock: the checked lock, any type. (struct checked_lock**).
202 * @return: in bytes, including protected areas.
204 size_t lock_get_mem(void* lock
);
207 * Initialise checklock. Sets up internal debug structures.
209 void checklock_start(void);
212 * Cleanup internal debug state.
214 void checklock_stop(void);
218 * @param type: what type of lock this is.
219 * @param lock: ptr to user alloced ptr structure. This is inited.
220 * So an alloc is done and the ptr is stored as result.
221 * @param func: caller function name.
222 * @param file: caller file name.
223 * @param line: caller line number.
225 void checklock_init(enum check_lock_type type
, struct checked_lock
** lock
,
226 const char* func
, const char* file
, int line
);
229 * Destroy locks. Free the structure.
230 * @param type: what type of lock this is.
231 * @param lock: ptr to user alloced structure. This is destroyed.
232 * @param func: caller function name.
233 * @param file: caller file name.
234 * @param line: caller line number.
236 void checklock_destroy(enum check_lock_type type
, struct checked_lock
** lock
,
237 const char* func
, const char* file
, int line
);
241 * @param type: what type of lock this is. Had better be a rwlock.
242 * @param lock: ptr to lock.
243 * @param func: caller function name.
244 * @param file: caller file name.
245 * @param line: caller line number.
247 void checklock_rdlock(enum check_lock_type type
, struct checked_lock
* lock
,
248 const char* func
, const char* file
, int line
);
252 * @param type: what type of lock this is. Had better be a rwlock.
253 * @param lock: ptr to lock.
254 * @param func: caller function name.
255 * @param file: caller file name.
256 * @param line: caller line number.
258 void checklock_wrlock(enum check_lock_type type
, struct checked_lock
* lock
,
259 const char* func
, const char* file
, int line
);
263 * @param type: what type of lock this is. Had better be mutex or spinlock.
264 * @param lock: the lock.
265 * @param func: caller function name.
266 * @param file: caller file name.
267 * @param line: caller line number.
269 void checklock_lock(enum check_lock_type type
, struct checked_lock
* lock
,
270 const char* func
, const char* file
, int line
);
274 * @param type: what type of lock this is.
275 * @param lock: the lock.
276 * @param func: caller function name.
277 * @param file: caller file name.
278 * @param line: caller line number.
280 void checklock_unlock(enum check_lock_type type
, struct checked_lock
* lock
,
281 const char* func
, const char* file
, int line
);
285 * @param thr: Thread id, where to store result.
286 * @param func: thread start function.
287 * @param arg: user argument.
289 void checklock_thrcreate(pthread_t
* thr
, void* (*func
)(void*), void* arg
);
292 * Wait for thread to exit. Returns thread return value.
293 * @param thread: thread to wait for.
295 void checklock_thrjoin(pthread_t thread
);
297 /** structures to enable compiler type checking on the locks.
298 * Also the pointer makes it so that the lock can be part of the protected
299 * region without any possible problem (since the ptr will stay the same.)
300 * i.e. there can be contention and readlocks stored in checked_lock, while
301 * the protected area stays the same, even though it contains (ptr to) lock.
303 struct checked_lock_rw
{ struct checked_lock
* c_rw
; };
304 /** structures to enable compiler type checking on the locks. */
305 struct checked_lock_mutex
{ struct checked_lock
* c_m
; };
306 /** structures to enable compiler type checking on the locks. */
307 struct checked_lock_spl
{ struct checked_lock
* c_spl
; };
309 /** debugging rwlock */
310 typedef struct checked_lock_rw lock_rw_t
;
311 #define lock_rw_init(lock) checklock_init(check_lock_rwlock, &((lock)->c_rw), __func__, __FILE__, __LINE__)
312 #define lock_rw_destroy(lock) checklock_destroy(check_lock_rwlock, &((lock)->c_rw), __func__, __FILE__, __LINE__)
313 #define lock_rw_rdlock(lock) checklock_rdlock(check_lock_rwlock, (lock)->c_rw, __func__, __FILE__, __LINE__)
314 #define lock_rw_wrlock(lock) checklock_wrlock(check_lock_rwlock, (lock)->c_rw, __func__, __FILE__, __LINE__)
315 #define lock_rw_unlock(lock) checklock_unlock(check_lock_rwlock, (lock)->c_rw, __func__, __FILE__, __LINE__)
317 /** debugging mutex */
318 typedef struct checked_lock_mutex lock_basic_t
;
319 #define lock_basic_init(lock) checklock_init(check_lock_mutex, &((lock)->c_m), __func__, __FILE__, __LINE__)
320 #define lock_basic_destroy(lock) checklock_destroy(check_lock_mutex, &((lock)->c_m), __func__, __FILE__, __LINE__)
321 #define lock_basic_lock(lock) checklock_lock(check_lock_mutex, (lock)->c_m, __func__, __FILE__, __LINE__)
322 #define lock_basic_unlock(lock) checklock_unlock(check_lock_mutex, (lock)->c_m, __func__, __FILE__, __LINE__)
324 /** debugging spinlock */
325 typedef struct checked_lock_spl lock_quick_t
;
326 #define lock_quick_init(lock) checklock_init(check_lock_spinlock, &((lock)->c_spl), __func__, __FILE__, __LINE__)
327 #define lock_quick_destroy(lock) checklock_destroy(check_lock_spinlock, &((lock)->c_spl), __func__, __FILE__, __LINE__)
328 #define lock_quick_lock(lock) checklock_lock(check_lock_spinlock, (lock)->c_spl, __func__, __FILE__, __LINE__)
329 #define lock_quick_unlock(lock) checklock_unlock(check_lock_spinlock, (lock)->c_spl, __func__, __FILE__, __LINE__)
331 /** we use the pthread id, our thr_check structure is kept behind the scenes */
332 typedef pthread_t ub_thread_t
;
333 #define ub_thread_create(thr, func, arg) checklock_thrcreate(thr, func, arg)
334 #define ub_thread_self() pthread_self()
335 #define ub_thread_join(thread) checklock_thrjoin(thread)
337 typedef pthread_key_t ub_thread_key_t
;
338 #define ub_thread_key_create(key, f) LOCKRET(pthread_key_create(key, f))
339 #define ub_thread_key_set(key, v) LOCKRET(pthread_setspecific(key, v))
340 #define ub_thread_key_get(key) pthread_getspecific(key)
342 #endif /* USE_THREAD_DEBUG */
343 #endif /* TESTCODE_CHECK_LOCKS_H */