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 };
94 
95 /**
96  * Per thread information for locking debug wrappers.
97  */
98 struct thr_check {
99 	/** thread id */
100 	pthread_t id;
101 	/** real thread func */
102 	void* (*func)(void*);
103 	/** func user arg */
104 	void* arg;
105 	/** number of thread in list structure */
106 	int num;
107 	/** instance number - how many locks have been created by thread */
108 	int locks_created;
109 	/** file to write locking order information to */
110 	FILE* order_info;
111 	/**
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).
115 	 */
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;
119 };
120 
121 /**
122  * One structure for all types of locks.
123  */
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 */
132 	int create_line;
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) */
140 	int hold_count;
141 	/** how many threads are waiting for this lock */
142 	int wait_count;
143 	/** who touched it last */
144 	const char* holder_func, *holder_file;
145 	/** who touched it last */
146 	int holder_line;
147 	/** who owns the lock now */
148 	struct thr_check* holder;
149 	/** for rwlocks, the writelock holder */
150 	struct thr_check* writeholder;
151 
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];
156 
157 	/** type of lock */
158 	enum check_lock_type {
159 		/** basic mutex */
160 		check_lock_mutex,
161 		/** fast spinlock */
162 		check_lock_spinlock,
163 		/** rwlock */
164 		check_lock_rwlock
165 	} type;
166 	/** the lock itself, see type to disambiguate the union */
167 	union {
168 		/** mutex */
169 		pthread_mutex_t mutex;
170 		/** spinlock */
171 		pthread_spinlock_t spinlock;
172 		/** rwlock */
173 		pthread_rwlock_t rwlock;
174 	} u;
175 };
176 
177 /**
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 initializing 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.
188  */
189 void lock_protect(void* lock, void* area, size_t size);
190 
191 /**
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.
196  */
197 void lock_unprotect(void* lock, void* area);
198 
199 /**
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.
203  */
204 size_t lock_get_mem(void* lock);
205 
206 /**
207  * Initialise checklock. Sets up internal debug structures.
208  */
209 void checklock_start(void);
210 
211 /**
212  * Cleanup internal debug state.
213  */
214 void checklock_stop(void);
215 
216 /**
217  * Init locks.
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.
224  */
225 void checklock_init(enum check_lock_type type, struct checked_lock** lock,
226 	const char* func, const char* file, int line);
227 
228 /**
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.
235  */
236 void checklock_destroy(enum check_lock_type type, struct checked_lock** lock,
237 	const char* func, const char* file, int line);
238 
239 /**
240  * Acquire readlock.
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.
246  */
247 void checklock_rdlock(enum check_lock_type type, struct checked_lock* lock,
248 	const char* func, const char* file, int line);
249 
250 /**
251  * Acquire writelock.
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.
257  */
258 void checklock_wrlock(enum check_lock_type type, struct checked_lock* lock,
259 	const char* func, const char* file, int line);
260 
261 /**
262  * Locks.
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.
268  */
269 void checklock_lock(enum check_lock_type type, struct checked_lock* lock,
270 	const char* func, const char* file, int line);
271 
272 /**
273  * Unlocks.
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.
279  */
280 void checklock_unlock(enum check_lock_type type, struct checked_lock* lock,
281 	const char* func, const char* file, int line);
282 
283 /**
284  * Create thread.
285  * @param thr: Thread id, where to store result.
286  * @param func: thread start function.
287  * @param arg: user argument.
288  */
289 void checklock_thrcreate(pthread_t* thr, void* (*func)(void*), void* arg);
290 
291 /**
292  * Wait for thread to exit. Returns thread return value.
293  * @param thread: thread to wait for.
294  */
295 void checklock_thrjoin(pthread_t thread);
296 
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.
302  */
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; };
308 
309 /** debugging rwlock */
310 typedef struct checked_lock_rw lock_rw_type;
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__)
316 
317 /** debugging mutex */
318 typedef struct checked_lock_mutex lock_basic_type;
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__)
323 
324 /** debugging spinlock */
325 typedef struct checked_lock_spl lock_quick_type;
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__)
330 
331 /** we use the pthread id, our thr_check structure is kept behind the scenes */
332 typedef pthread_t ub_thread_type;
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)
336 
337 typedef pthread_key_t ub_thread_key_type;
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)
341 
342 #endif /* USE_THREAD_DEBUG */
343 #endif /* TESTCODE_CHECK_LOCKS_H */
344