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