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