2 Bacula® - The Network Backup Solution
4 Copyright (C) 2008-2009 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation, which is
11 listed in the file LICENSE.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of Kern Sibbald.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
30 How to use mutex with bad order usage detection
31 ------------------------------------------------
34 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
40 bthread_mutex_t mutex = BTHREAD_MUTEX_PRIORITY(1);
45 Mutex that doesn't need this extra check can be declared as pthread_mutex_t.
46 You can use this object on pthread_mutex_lock/unlock/cond_wait/cond_timewait.
48 With dynamic creation, you can use:
49 bthread_mutex_t mutex;
50 pthread_mutex_init(&mutex);
51 bthread_mutex_set_priority(&mutex, 10);
52 pthread_mutex_destroy(&mutex);
56 #define _LOCKMGR_COMPLIANT
60 #define ASSERT(x) if (!(x)) { \
62 Pmsg3(000, _("Failed ASSERT: %s\n"), __FILE__, __LINE__, #x); \
65 #define ASSERT_p(x,f,l) if (!(x)) { \
67 Pmsg3(000, _("from %s:%i Failed ASSERT: %s\n"), f, l, #x); \
72 http://www.cs.berkeley.edu/~kamil/teaching/sp03/041403.pdf
74 This lock manager will replace some pthread calls. It can be
75 enabled with _USE_LOCKMGR
77 Some part of the code can't use this manager, for example the
78 rwlock object or the smartalloc lib. To disable LMGR, just add
79 _LOCKMGR_COMPLIANT before the inclusion of "bacula.h"
82 g++ -g -c lockmgr.c -I.. -I../lib -D_USE_LOCKMGR -D_TEST_IT
83 g++ -o lockmgr lockmgr.o -lbac -L../lib/.libs -lssl -lpthread
89 * pthread_mutex_lock for memory allocator and other
90 * parts that are _LOCKMGR_COMPLIANT
92 void lmgr_p(pthread_mutex_t *m)
95 if ((errstat=pthread_mutex_lock(m))) {
97 e_msg(__FILE__, __LINE__, M_ABORT, 0, _("Mutex lock failure. ERR=%s\n"),
98 be.bstrerror(errstat));
102 void lmgr_v(pthread_mutex_t *m)
105 if ((errstat=pthread_mutex_unlock(m))) {
107 e_msg(__FILE__, __LINE__, M_ABORT, 0, _("Mutex unlock failure. ERR=%s\n"),
108 be.bstrerror(errstat));
116 LMGR_WHITE, /* never seen */
117 LMGR_BLACK, /* no loop */
118 LMGR_GREY, /* seen before */
122 * Node used by the Lock Manager
123 * If the lock is GRANTED, we have mutex -> proc, else it's a proc -> mutex
126 * Note, each mutex can be GRANTED once, and each proc can have only one WANTED
129 class lmgr_node_t: public SMARTALLOC
142 lmgr_node_t(void *n, void *c) {
146 void init(void *n, void *c) {
152 void mark_as_seen(lmgr_color_t c) {
156 ~lmgr_node_t() {printf("delete node\n");}
160 LMGR_LOCK_EMPTY = 'E', /* unused */
161 LMGR_LOCK_WANTED = 'W', /* before mutex_lock */
162 LMGR_LOCK_GRANTED = 'G' /* after mutex_lock */
166 * Object associated with each mutex per thread
168 class lmgr_lock_t: public SMARTALLOC
182 state = LMGR_LOCK_EMPTY;
183 priority = max_priority = 0;
186 lmgr_lock_t(void *l) {
188 state = LMGR_LOCK_WANTED;
192 state = LMGR_LOCK_GRANTED;
200 * Get the child list, ret must be already allocated
202 static void search_all_node(dlist *g, lmgr_node_t *v, alist *ret)
205 foreach_dlist(n, g) {
206 if (v->child == n->node) {
212 static bool visite(dlist *g, lmgr_node_t *v)
216 v->mark_as_seen(LMGR_GREY);
218 alist *d = New(alist(5, false)); /* use alist because own=false */
219 search_all_node(g, v, d);
221 //foreach_alist(n, d) {
222 // printf("node n=%p c=%p s=%c\n", n->node, n->child, n->seen);
225 foreach_alist(n, d) {
226 if (n->seen == LMGR_GREY) { /* already seen this node */
229 } else if (n->seen == LMGR_WHITE) {
236 v->mark_as_seen(LMGR_BLACK); /* no loop detected, node is clean */
242 static bool contains_cycle(dlist *g)
245 foreach_dlist(n, g) {
246 if (n->seen == LMGR_WHITE) {
255 /****************************************************************/
257 class lmgr_thread_t: public SMARTALLOC
261 pthread_mutex_t mutex;
263 lmgr_lock_t lock_list[LMGR_MAX_LOCK];
270 if ((status = pthread_mutex_init(&mutex, NULL)) != 0) {
272 Pmsg1(000, _("pthread key create failed: ERR=%s\n"),
273 be.bstrerror(status));
276 thread_id = pthread_self();
282 void _dump(FILE *fp) {
283 fprintf(fp, "threadid=%p max=%i current=%i\n",
284 (void *)thread_id, max, current);
285 for(int i=0; i<=current; i++) {
286 fprintf(fp, " lock=%p state=%s priority=%i %s:%i\n",
288 (lock_list[i].state=='W')?"Wanted ":"Granted",
289 lock_list[i].priority,
290 lock_list[i].file, lock_list[i].line);
294 void dump(FILE *fp) {
303 * Call before a lock operation (mark mutex as WANTED)
305 virtual void pre_P(void *m, int priority,
306 const char *f="*unknown*", int l=0)
308 int max_prio = max_priority;
309 ASSERT_p(current < LMGR_MAX_LOCK, f, l);
310 ASSERT_p(current >= -1, f, l);
314 lock_list[current].lock = m;
315 lock_list[current].state = LMGR_LOCK_WANTED;
316 lock_list[current].file = f;
317 lock_list[current].line = l;
318 lock_list[current].priority = priority;
319 lock_list[current].max_priority = MAX(priority, max_priority);
320 max = MAX(current, max);
321 max_priority = MAX(priority, max_priority);
324 ASSERT_p(!priority || priority >= max_prio, f, l);
328 * Call after the lock operation (mark mutex as GRANTED)
330 virtual void post_P() {
331 ASSERT(current >= 0);
332 ASSERT(lock_list[current].state == LMGR_LOCK_WANTED);
333 lock_list[current].state = LMGR_LOCK_GRANTED;
336 /* Using this function is some sort of bug */
337 void shift_list(int i) {
338 for(int j=i+1; j<=current; j++) {
339 lock_list[i] = lock_list[j];
342 lock_list[current].lock = NULL;
343 lock_list[current].state = LMGR_LOCK_EMPTY;
345 /* rebuild the priority list */
347 for(int j=0; j< current; j++) {
348 max_priority = MAX(lock_list[j].priority, max_priority);
349 lock_list[j].max_priority = max_priority;
354 * Remove the mutex from the list
356 virtual void do_V(void *m, const char *f="*unknown*", int l=0) {
357 ASSERT_p(current >= 0, f, l);
360 if (lock_list[current].lock == m) {
361 lock_list[current].lock = NULL;
362 lock_list[current].state = LMGR_LOCK_EMPTY;
366 Pmsg3(0, "ERROR: wrong P/V order search lock=%p %s:%i\n", m, f, l);
367 Pmsg4(000, "ERROR: wrong P/V order pos=%i lock=%p %s:%i\n",
368 current, lock_list[current].lock, lock_list[current].file,
369 lock_list[current].line);
370 for (int i=current-1; i >= 0; i--) { /* already seen current */
371 Pmsg4(000, "ERROR: wrong P/V order pos=%i lock=%p %s:%i\n",
372 i, lock_list[i].lock, lock_list[i].file, lock_list[i].line);
373 if (lock_list[i].lock == m) {
374 Pmsg3(000, "ERROR: FOUND P pos=%i %s:%i\n", i, f, l);
381 /* reset max_priority to the last one */
383 max_priority = lock_list[current].max_priority;
391 virtual ~lmgr_thread_t() {destroy();}
394 pthread_mutex_destroy(&mutex);
398 class lmgr_dummy_thread_t: public lmgr_thread_t
400 void do_V(void *m, const char *file, int l) {}
402 void pre_P(void *m, int priority, const char *file, int l) {}
406 * LMGR - Lock Manager
412 pthread_once_t key_lmgr_once = PTHREAD_ONCE_INIT;
413 static pthread_key_t lmgr_key; /* used to get lgmr_thread_t object */
415 static dlist *global_mgr = NULL; /* used to store all lgmr_thread_t objects */
416 static pthread_mutex_t lmgr_global_mutex = PTHREAD_MUTEX_INITIALIZER;
417 static pthread_t undertaker;
418 static bool use_undertaker=true;
420 #define lmgr_is_active() (global_mgr != NULL)
423 * Add a new lmgr_thread_t object to the global list
425 void lmgr_register_thread(lmgr_thread_t *item)
427 lmgr_p(&lmgr_global_mutex);
429 global_mgr->prepend(item);
431 lmgr_v(&lmgr_global_mutex);
435 * Call this function to cleanup specific lock thread data
437 void lmgr_unregister_thread(lmgr_thread_t *item)
439 if (!lmgr_is_active()) {
442 lmgr_p(&lmgr_global_mutex);
444 global_mgr->remove(item);
446 lmgr_v(&lmgr_global_mutex);
450 * Search for a deadlock when it's secure to walk across
451 * locks list. (after lmgr_detect_deadlock or a fatal signal)
453 bool lmgr_detect_deadlock_unlocked()
456 lmgr_node_t *node=NULL;
459 dlist *g = New(dlist(node, &node->link));
461 /* First, get a list of all node */
462 foreach_dlist(item, global_mgr) {
463 for(int i=0; i<=item->current; i++) {
465 lock = &item->lock_list[i];
466 /* Depending if the lock is granted or not, it's a child or a root
467 * Granted: Mutex -> Thread
468 * Wanted: Thread -> Mutex
470 * Note: a Mutex can be locked only once, a thread can request only
474 if (lock->state == LMGR_LOCK_GRANTED) {
475 node = New(lmgr_node_t((void*)lock->lock, (void*)item->thread_id));
476 } else if (lock->state == LMGR_LOCK_WANTED) {
477 node = New(lmgr_node_t((void*)item->thread_id, (void*)lock->lock));
485 //foreach_dlist(node, g) {
486 // printf("g n=%p c=%p\n", node->node, node->child);
489 ret = contains_cycle(g);
491 printf("Found a deadlock !!!!\n");
499 * Search for a deadlock in during the runtime
500 * It will lock all thread specific lock manager, nothing
501 * can be locked during this check.
503 bool lmgr_detect_deadlock()
506 if (!lmgr_is_active()) {
510 lmgr_p(&lmgr_global_mutex);
513 foreach_dlist(item, global_mgr) {
514 lmgr_p(&item->mutex);
517 ret = lmgr_detect_deadlock_unlocked();
519 foreach_dlist(item, global_mgr) {
520 lmgr_v(&item->mutex);
523 lmgr_v(&lmgr_global_mutex);
530 * Use this function is used only after a fatal signal
531 * We don't use locking to display the information
533 void dbg_print_lock(FILE *fp)
535 fprintf(fp, "Attempt to dump locks\n");
536 if (!lmgr_is_active()) {
540 foreach_dlist(item, global_mgr) {
546 * Dump each lmgr_thread_t object
550 lmgr_p(&lmgr_global_mutex);
553 foreach_dlist(item, global_mgr) {
557 lmgr_v(&lmgr_global_mutex);
560 void cln_hdl(void *a)
562 lmgr_cleanup_thread();
565 void *check_deadlock(void *)
569 pthread_cleanup_push(cln_hdl, NULL);
571 while (!bmicrosleep(30, 0)) {
572 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old);
573 if (lmgr_detect_deadlock()) {
577 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old);
578 pthread_testcancel();
580 Pmsg0(000, "Undertaker is leaving...\n");
581 pthread_cleanup_pop(1);
585 /* This object is used when LMGR is not initialized */
586 static lmgr_dummy_thread_t dummy_lmgr;
589 * Retrieve the lmgr_thread_t object from the stack
591 inline lmgr_thread_t *lmgr_get_thread_info()
593 if (lmgr_is_active()) {
594 return (lmgr_thread_t *)pthread_getspecific(lmgr_key);
601 * launch once for all threads
603 void create_lmgr_key()
605 int status = pthread_key_create(&lmgr_key, NULL);
608 Pmsg1(000, _("pthread key create failed: ERR=%s\n"),
609 be.bstrerror(status));
613 lmgr_thread_t *n=NULL;
614 global_mgr = New(dlist(n, &n->link));
616 if (use_undertaker) {
617 status = pthread_create(&undertaker, NULL, check_deadlock, NULL);
620 Pmsg1(000, _("pthread_create failed: ERR=%s\n"),
621 be.bstrerror(status));
628 * Each thread have to call this function to put a lmgr_thread_t object
629 * in the stack and be able to call mutex_lock/unlock
631 void lmgr_init_thread()
633 int status = pthread_once(&key_lmgr_once, create_lmgr_key);
636 Pmsg1(000, _("pthread key create failed: ERR=%s\n"),
637 be.bstrerror(status));
640 lmgr_thread_t *l = New(lmgr_thread_t());
641 pthread_setspecific(lmgr_key, l);
642 lmgr_register_thread(l);
646 * Call this function at the end of the thread
648 void lmgr_cleanup_thread()
650 if (!lmgr_is_active()) {
653 lmgr_thread_t *self = lmgr_get_thread_info();
654 lmgr_unregister_thread(self);
659 * This function should be call at the end of the main thread
660 * Some thread like the watchdog are already present, so the global_mgr
661 * list is never empty. Should carefully clear the memory.
663 void lmgr_cleanup_main()
670 if (use_undertaker) {
671 pthread_cancel(undertaker);
673 lmgr_cleanup_thread();
674 lmgr_p(&lmgr_global_mutex);
680 lmgr_v(&lmgr_global_mutex);
684 * Set the priority of the lmgr mutex object
686 void bthread_mutex_set_priority(bthread_mutex_t *m, int prio)
688 #ifdef USE_LOCKMGR_PRIORITY
694 * Replacement for pthread_mutex_init()
696 int pthread_mutex_init(bthread_mutex_t *m, const pthread_mutexattr_t *attr)
699 return pthread_mutex_init(&m->mutex, attr);
703 * Replacement for pthread_mutex_destroy()
705 int pthread_mutex_destroy(bthread_mutex_t *m)
707 return pthread_mutex_destroy(&m->mutex);
711 * Replacement for pthread_mutex_lock()
714 int bthread_mutex_lock_p(bthread_mutex_t *m, const char *file, int line)
716 lmgr_thread_t *self = lmgr_get_thread_info();
717 self->pre_P(m, m->priority, file, line);
724 * Replacement for pthread_mutex_unlock()
727 int bthread_mutex_unlock_p(bthread_mutex_t *m, const char *file, int line)
729 lmgr_thread_t *self = lmgr_get_thread_info();
730 self->do_V(m, file, line);
736 * Replacement for pthread_mutex_lock() but with real pthread_mutex_t
739 int bthread_mutex_lock_p(pthread_mutex_t *m, const char *file, int line)
741 lmgr_thread_t *self = lmgr_get_thread_info();
742 self->pre_P(m, 0, file, line);
749 * Replacement for pthread_mutex_unlock() but with real pthread_mutex_t
752 int bthread_mutex_unlock_p(pthread_mutex_t *m, const char *file, int line)
754 lmgr_thread_t *self = lmgr_get_thread_info();
755 self->do_V(m, file, line);
763 int bthread_cond_wait_p(pthread_cond_t *cond,
765 const char *file, int line)
768 lmgr_thread_t *self = lmgr_get_thread_info();
769 self->do_V(m, file, line);
770 ret = pthread_cond_wait(cond, m);
771 self->pre_P(m, 0, file, line);
778 int bthread_cond_timedwait_p(pthread_cond_t *cond,
780 const struct timespec * abstime,
781 const char *file, int line)
784 lmgr_thread_t *self = lmgr_get_thread_info();
785 self->do_V(m, file, line);
786 ret = pthread_cond_timedwait(cond, m, abstime);
787 self->pre_P(m, 0, file, line);
794 int bthread_cond_wait_p(pthread_cond_t *cond,
796 const char *file, int line)
799 lmgr_thread_t *self = lmgr_get_thread_info();
800 self->do_V(m, file, line);
801 ret = pthread_cond_wait(cond, &m->mutex);
802 self->pre_P(m, m->priority, file, line);
809 int bthread_cond_timedwait_p(pthread_cond_t *cond,
811 const struct timespec * abstime,
812 const char *file, int line)
815 lmgr_thread_t *self = lmgr_get_thread_info();
816 self->do_V(m, file, line);
817 ret = pthread_cond_timedwait(cond, &m->mutex, abstime);
818 self->pre_P(m, m->priority, file, line);
824 * Use this function when the caller handle the mutex directly
826 * lmgr_pre_lock(m, 10);
827 * pthread_mutex_lock(m);
830 void lmgr_pre_lock(void *m, int prio, const char *file, int line)
832 lmgr_thread_t *self = lmgr_get_thread_info();
833 self->pre_P(m, prio, file, line);
837 * Use this function when the caller handle the mutex directly
839 void lmgr_post_lock()
841 lmgr_thread_t *self = lmgr_get_thread_info();
846 * Do directly pre_P and post_P (used by trylock)
848 void lmgr_do_lock(void *m, int prio, const char *file, int line)
850 lmgr_thread_t *self = lmgr_get_thread_info();
851 self->pre_P(m, prio, file, line);
856 * Use this function when the caller handle the mutex directly
858 void lmgr_do_unlock(void *m)
860 lmgr_thread_t *self = lmgr_get_thread_info();
865 void *(*start_routine)(void*);
870 void *lmgr_thread_launcher(void *x)
874 pthread_cleanup_push(cln_hdl, NULL);
876 lmgr_thread_arg_t arg;
877 lmgr_thread_arg_t *a = (lmgr_thread_arg_t *)x;
878 arg.start_routine = a->start_routine;
882 ret = arg.start_routine(arg.arg);
883 pthread_cleanup_pop(1);
887 int lmgr_thread_create(pthread_t *thread,
888 const pthread_attr_t *attr,
889 void *(*start_routine)(void*), void *arg)
891 /* lmgr should be active (lmgr_init_thread() call in main()) */
892 ASSERT(lmgr_is_active());
893 /* Will be freed by the child */
894 lmgr_thread_arg_t *a = (lmgr_thread_arg_t*) malloc(sizeof(lmgr_thread_arg_t));
895 a->start_routine = start_routine;
897 return pthread_create(thread, attr, lmgr_thread_launcher, a);
900 #else /* _USE_LOCKMGR */
904 * Use this function is used only after a fatal signal
905 * We don't use locking to display information
907 void dbg_print_lock(FILE *fp)
909 Pmsg0(000, "lockmgr disabled\n");
912 #endif /* _USE_LOCKMGR */
917 #define BTHREAD_MUTEX_NO_PRIORITY {PTHREAD_MUTEX_INITIALIZER, 0}
918 #define BTHREAD_MUTEX_PRIORITY(p) {PTHREAD_MUTEX_INITIALIZER, p}
921 #define P(x) bthread_mutex_lock_p(&(x), __FILE__, __LINE__)
922 #define V(x) bthread_mutex_unlock_p(&(x), __FILE__, __LINE__)
923 #define pthread_create(a, b, c, d) lmgr_thread_create(a,b,c,d)
925 bthread_mutex_t mutex1 = BTHREAD_MUTEX_NO_PRIORITY;
926 bthread_mutex_t mutex2 = BTHREAD_MUTEX_NO_PRIORITY;
927 bthread_mutex_t mutex3 = BTHREAD_MUTEX_NO_PRIORITY;
928 bthread_mutex_t mutex4 = BTHREAD_MUTEX_NO_PRIORITY;
929 bthread_mutex_t mutex5 = BTHREAD_MUTEX_NO_PRIORITY;
930 bthread_mutex_t mutex6 = BTHREAD_MUTEX_NO_PRIORITY;
931 bthread_mutex_t mutex_p1 = BTHREAD_MUTEX_PRIORITY(1);
932 bthread_mutex_t mutex_p2 = BTHREAD_MUTEX_PRIORITY(2);
933 bthread_mutex_t mutex_p3 = BTHREAD_MUTEX_PRIORITY(3);
934 static const char *my_prog;
936 void *self_lock(void *temp)
945 void *nolock(void *temp)
953 void *locker(void *temp)
955 bthread_mutex_t *m = (bthread_mutex_t*) temp;
961 void *rwlocker(void *temp)
963 brwlock_t *m = (brwlock_t*) temp;
972 void *mix_rwl_mutex(void *temp)
974 brwlock_t *m = (brwlock_t*) temp;
983 void *th2(void *temp)
998 void *th1(void *temp)
1015 void *thx(void *temp)
1017 int s= 1 + (int) (500.0 * (rand() / (RAND_MAX + 1.0))) + 200;
1028 void *th3(void *a) {
1030 fprintf(stderr, "undertaker sleep()\n");
1033 if (lmgr_detect_deadlock()) {
1041 void *th_prio(void *a) {
1043 bstrncpy(buf, my_prog, sizeof(buf));
1044 bstrncat(buf, " priority", sizeof(buf));
1045 int ret = system(buf);
1051 void _ok(const char *file, int l, const char *op, int value, const char *label)
1056 printf("ERR %.30s %s:%i on %s\n", label, file, l, op);
1058 printf("OK %.30s\n", label);
1062 #define ok(x, label) _ok(__FILE__, __LINE__, #x, (x), label)
1064 void _nok(const char *file, int l, const char *op, int value, const char *label)
1069 printf("ERR %.30s %s:%i on !%s\n", label, file, l, op);
1071 printf("OK %.30s\n", label);
1075 #define nok(x, label) _nok(__FILE__, __LINE__, #x, (x), label)
1079 printf("Result %i/%i OK\n", nb - err, nb);
1085 * - Must detect multiple lock
1086 * - lock/unlock in wrong order
1087 * - deadlock with 2 or 3 threads
1089 int main(int argc, char **argv)
1092 lmgr_thread_t *self;
1093 pthread_t id1, id2, id3, tab[200];
1094 bthread_mutex_t bmutex1;
1095 pthread_mutex_t pmutex2;
1098 use_undertaker = false;
1100 self = lmgr_get_thread_info();
1102 if (argc == 2) { /* do priority check */
1103 P(mutex_p2); /* not permited */
1105 V(mutex_p1); /* never goes here */
1110 pthread_mutex_init(&bmutex1, NULL);
1111 bthread_mutex_set_priority(&bmutex1, 10);
1113 pthread_mutex_init(&pmutex2, NULL);
1115 ok(self->max_priority == 10, "Check self max_priority");
1117 ok(bmutex1.priority == 10, "Check bmutex_set_priority()");
1120 ok(self->max_priority == 0, "Check self max_priority");
1122 pthread_create(&id1, NULL, self_lock, NULL);
1124 ok(lmgr_detect_deadlock(), "Check self deadlock");
1125 lmgr_v(&mutex1.mutex); /* a bit dirty */
1126 pthread_join(id1, NULL);
1129 pthread_create(&id1, NULL, nolock, NULL);
1131 nok(lmgr_detect_deadlock(), "Check for nolock");
1132 pthread_join(id1, NULL);
1135 pthread_create(&id1, NULL, locker, &mutex1);
1136 pthread_create(&id2, NULL, locker, &mutex1);
1137 pthread_create(&id3, NULL, locker, &mutex1);
1139 nok(lmgr_detect_deadlock(), "Check for multiple lock");
1141 pthread_join(id1, NULL);
1142 pthread_join(id2, NULL);
1143 pthread_join(id3, NULL);
1150 pthread_create(&id1, NULL, rwlocker, &wr);
1151 pthread_create(&id2, NULL, rwlocker, &wr);
1152 pthread_create(&id3, NULL, rwlocker, &wr);
1153 nok(lmgr_detect_deadlock(), "Check for multiple rwlock");
1154 rwl_writeunlock(&wr);
1155 nok(lmgr_detect_deadlock(), "Check for simple rwlock");
1156 rwl_writeunlock(&wr);
1157 nok(lmgr_detect_deadlock(), "Check for multiple rwlock");
1159 pthread_join(id1, NULL);
1160 pthread_join(id2, NULL);
1161 pthread_join(id3, NULL);
1165 pthread_create(&id1, NULL, mix_rwl_mutex, &wr);
1166 nok(lmgr_detect_deadlock(), "Check for mix rwlock/mutex");
1168 nok(lmgr_detect_deadlock(), "Check for mix rwlock/mutex");
1169 rwl_writeunlock(&wr);
1170 nok(lmgr_detect_deadlock(), "Check for mix rwlock/mutex");
1171 pthread_join(id1, NULL);
1178 nok(lmgr_detect_deadlock(), "Check for wrong order");
1180 for(int j=0; j<200; j++) {
1181 pthread_create(&tab[j], NULL, thx, NULL);
1183 for(int j=0; j<200; j++) {
1184 pthread_join(tab[j], NULL);
1185 if (j%3) { lmgr_detect_deadlock();}
1187 nok(lmgr_detect_deadlock(), "Check 200 lockers");
1196 pthread_create(&id1, NULL, th1, NULL);
1198 pthread_create(&id2, NULL, th2, NULL);
1200 ok(lmgr_detect_deadlock(), "Check for deadlock");
1202 pthread_create(&id3, NULL, th_prio, NULL);
1203 pthread_join(id3, &ret);
1204 ok(ret != 0, "Check for priority segfault");
1207 ok(self->max_priority == 1, "Check max_priority 1/4");
1209 ok(self->max_priority == 2, "Check max_priority 2/4");
1211 ok(self->max_priority == 3, "Check max_priority 3/4");
1213 ok(self->max_priority == 3, "Check max_priority 4/4");
1215 ok(self->max_priority == 3, "Check max_priority 1/5");
1217 ok(self->max_priority == 2, "Check max_priority 4/5");
1219 ok(self->max_priority == 1, "Check max_priority 4/5");
1221 ok(self->max_priority == 0, "Check max_priority 5/5");
1228 ok(self->max_priority == 3, "Check max_priority mixed");
1230 ok(self->max_priority == 3, "Check max_priority mixed");
1232 ok(self->max_priority == 3, "Check max_priority mixed");
1234 ok(self->max_priority == 0, "Check max_priority mixed");
1236 ok(self->max_priority == 0, "Check max_priority mixed");
1245 // pthread_create(&id3, NULL, th3, NULL);
1247 // pthread_join(id1, NULL);
1248 // pthread_join(id2, NULL);
1249 lmgr_cleanup_main();
1250 sm_check(__FILE__, __LINE__, false);