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)
692 * Replacement for pthread_mutex_init()
694 int pthread_mutex_init(bthread_mutex_t *m, const pthread_mutexattr_t *attr)
697 return pthread_mutex_init(&m->mutex, attr);
701 * Replacement for pthread_mutex_destroy()
703 int pthread_mutex_destroy(bthread_mutex_t *m)
705 return pthread_mutex_destroy(&m->mutex);
709 * Replacement for pthread_mutex_lock()
712 int bthread_mutex_lock_p(bthread_mutex_t *m, const char *file, int line)
714 lmgr_thread_t *self = lmgr_get_thread_info();
715 self->pre_P(m, m->priority, file, line);
722 * Replacement for pthread_mutex_unlock()
725 int bthread_mutex_unlock_p(bthread_mutex_t *m, const char *file, int line)
727 lmgr_thread_t *self = lmgr_get_thread_info();
728 self->do_V(m, file, line);
734 * Replacement for pthread_mutex_lock() but with real pthread_mutex_t
737 int bthread_mutex_lock_p(pthread_mutex_t *m, const char *file, int line)
739 lmgr_thread_t *self = lmgr_get_thread_info();
740 self->pre_P(m, 0, file, line);
747 * Replacement for pthread_mutex_unlock() but with real pthread_mutex_t
750 int bthread_mutex_unlock_p(pthread_mutex_t *m, const char *file, int line)
752 lmgr_thread_t *self = lmgr_get_thread_info();
753 self->do_V(m, file, line);
761 int bthread_cond_wait_p(pthread_cond_t *cond,
763 const char *file, int line)
766 lmgr_thread_t *self = lmgr_get_thread_info();
767 self->do_V(m, file, line);
768 ret = pthread_cond_wait(cond, m);
769 self->pre_P(m, 0, file, line);
776 int bthread_cond_timedwait_p(pthread_cond_t *cond,
778 const struct timespec * abstime,
779 const char *file, int line)
782 lmgr_thread_t *self = lmgr_get_thread_info();
783 self->do_V(m, file, line);
784 ret = pthread_cond_timedwait(cond, m, abstime);
785 self->pre_P(m, 0, file, line);
792 int bthread_cond_wait_p(pthread_cond_t *cond,
794 const char *file, int line)
797 lmgr_thread_t *self = lmgr_get_thread_info();
798 self->do_V(m, file, line);
799 ret = pthread_cond_wait(cond, &m->mutex);
800 self->pre_P(m, m->priority, file, line);
807 int bthread_cond_timedwait_p(pthread_cond_t *cond,
809 const struct timespec * abstime,
810 const char *file, int line)
813 lmgr_thread_t *self = lmgr_get_thread_info();
814 self->do_V(m, file, line);
815 ret = pthread_cond_timedwait(cond, &m->mutex, abstime);
816 self->pre_P(m, m->priority, file, line);
822 * Use this function when the caller handle the mutex directly
824 * lmgr_pre_lock(m, 10);
825 * pthread_mutex_lock(m);
828 void lmgr_pre_lock(void *m, int prio, const char *file, int line)
830 lmgr_thread_t *self = lmgr_get_thread_info();
831 self->pre_P(m, prio, file, line);
835 * Use this function when the caller handle the mutex directly
837 void lmgr_post_lock()
839 lmgr_thread_t *self = lmgr_get_thread_info();
844 * Do directly pre_P and post_P (used by trylock)
846 void lmgr_do_lock(void *m, int prio, const char *file, int line)
848 lmgr_thread_t *self = lmgr_get_thread_info();
849 self->pre_P(m, prio, file, line);
854 * Use this function when the caller handle the mutex directly
856 void lmgr_do_unlock(void *m)
858 lmgr_thread_t *self = lmgr_get_thread_info();
863 void *(*start_routine)(void*);
868 void *lmgr_thread_launcher(void *x)
872 pthread_cleanup_push(cln_hdl, NULL);
874 lmgr_thread_arg_t arg;
875 lmgr_thread_arg_t *a = (lmgr_thread_arg_t *)x;
876 arg.start_routine = a->start_routine;
880 ret = arg.start_routine(arg.arg);
881 pthread_cleanup_pop(1);
885 int lmgr_thread_create(pthread_t *thread,
886 const pthread_attr_t *attr,
887 void *(*start_routine)(void*), void *arg)
889 /* lmgr should be active (lmgr_init_thread() call in main()) */
890 ASSERT(lmgr_is_active());
891 /* Will be freed by the child */
892 lmgr_thread_arg_t *a = (lmgr_thread_arg_t*) malloc(sizeof(lmgr_thread_arg_t));
893 a->start_routine = start_routine;
895 return pthread_create(thread, attr, lmgr_thread_launcher, a);
898 #else /* _USE_LOCKMGR */
902 * Use this function is used only after a fatal signal
903 * We don't use locking to display information
905 void dbg_print_lock(FILE *fp)
907 Pmsg0(000, "lockmgr disabled\n");
910 #endif /* _USE_LOCKMGR */
915 #define BTHREAD_MUTEX_NO_PRIORITY {PTHREAD_MUTEX_INITIALIZER, 0}
916 #define BTHREAD_MUTEX_PRIORITY(p) {PTHREAD_MUTEX_INITIALIZER, p}
919 #define P(x) bthread_mutex_lock_p(&(x), __FILE__, __LINE__)
920 #define V(x) bthread_mutex_unlock_p(&(x), __FILE__, __LINE__)
921 #define pthread_create(a, b, c, d) lmgr_thread_create(a,b,c,d)
923 bthread_mutex_t mutex1 = BTHREAD_MUTEX_NO_PRIORITY;
924 bthread_mutex_t mutex2 = BTHREAD_MUTEX_NO_PRIORITY;
925 bthread_mutex_t mutex3 = BTHREAD_MUTEX_NO_PRIORITY;
926 bthread_mutex_t mutex4 = BTHREAD_MUTEX_NO_PRIORITY;
927 bthread_mutex_t mutex5 = BTHREAD_MUTEX_NO_PRIORITY;
928 bthread_mutex_t mutex6 = BTHREAD_MUTEX_NO_PRIORITY;
929 bthread_mutex_t mutex_p1 = BTHREAD_MUTEX_PRIORITY(1);
930 bthread_mutex_t mutex_p2 = BTHREAD_MUTEX_PRIORITY(2);
931 bthread_mutex_t mutex_p3 = BTHREAD_MUTEX_PRIORITY(3);
932 static const char *my_prog;
934 void *self_lock(void *temp)
943 void *nolock(void *temp)
951 void *locker(void *temp)
953 bthread_mutex_t *m = (bthread_mutex_t*) temp;
959 void *rwlocker(void *temp)
961 brwlock_t *m = (brwlock_t*) temp;
970 void *mix_rwl_mutex(void *temp)
972 brwlock_t *m = (brwlock_t*) temp;
981 void *th2(void *temp)
996 void *th1(void *temp)
1013 void *thx(void *temp)
1015 int s= 1 + (int) (500.0 * (rand() / (RAND_MAX + 1.0))) + 200;
1026 void *th3(void *a) {
1028 fprintf(stderr, "undertaker sleep()\n");
1031 if (lmgr_detect_deadlock()) {
1039 void *th_prio(void *a) {
1041 bstrncpy(buf, my_prog, sizeof(buf));
1042 bstrncat(buf, " priority", sizeof(buf));
1043 int ret = system(buf);
1049 void _ok(const char *file, int l, const char *op, int value, const char *label)
1054 printf("ERR %.30s %s:%i on %s\n", label, file, l, op);
1056 printf("OK %.30s\n", label);
1060 #define ok(x, label) _ok(__FILE__, __LINE__, #x, (x), label)
1062 void _nok(const char *file, int l, const char *op, int value, const char *label)
1067 printf("ERR %.30s %s:%i on !%s\n", label, file, l, op);
1069 printf("OK %.30s\n", label);
1073 #define nok(x, label) _nok(__FILE__, __LINE__, #x, (x), label)
1077 printf("Result %i/%i OK\n", nb - err, nb);
1083 * - Must detect multiple lock
1084 * - lock/unlock in wrong order
1085 * - deadlock with 2 or 3 threads
1087 int main(int argc, char **argv)
1090 lmgr_thread_t *self;
1091 pthread_t id1, id2, id3, tab[200];
1092 bthread_mutex_t bmutex1;
1093 pthread_mutex_t pmutex2;
1096 use_undertaker = false;
1098 self = lmgr_get_thread_info();
1100 if (argc == 2) { /* do priority check */
1101 P(mutex_p2); /* not permited */
1103 V(mutex_p1); /* never goes here */
1108 pthread_mutex_init(&bmutex1, NULL);
1109 bthread_mutex_set_priority(&bmutex1, 10);
1111 pthread_mutex_init(&pmutex2, NULL);
1113 ok(self->max_priority == 10, "Check self max_priority");
1115 ok(bmutex1.priority == 10, "Check bmutex_set_priority()");
1118 ok(self->max_priority == 0, "Check self max_priority");
1120 pthread_create(&id1, NULL, self_lock, NULL);
1122 ok(lmgr_detect_deadlock(), "Check self deadlock");
1123 lmgr_v(&mutex1.mutex); /* a bit dirty */
1124 pthread_join(id1, NULL);
1127 pthread_create(&id1, NULL, nolock, NULL);
1129 nok(lmgr_detect_deadlock(), "Check for nolock");
1130 pthread_join(id1, NULL);
1133 pthread_create(&id1, NULL, locker, &mutex1);
1134 pthread_create(&id2, NULL, locker, &mutex1);
1135 pthread_create(&id3, NULL, locker, &mutex1);
1137 nok(lmgr_detect_deadlock(), "Check for multiple lock");
1139 pthread_join(id1, NULL);
1140 pthread_join(id2, NULL);
1141 pthread_join(id3, NULL);
1148 pthread_create(&id1, NULL, rwlocker, &wr);
1149 pthread_create(&id2, NULL, rwlocker, &wr);
1150 pthread_create(&id3, NULL, rwlocker, &wr);
1151 nok(lmgr_detect_deadlock(), "Check for multiple rwlock");
1152 rwl_writeunlock(&wr);
1153 nok(lmgr_detect_deadlock(), "Check for simple rwlock");
1154 rwl_writeunlock(&wr);
1155 nok(lmgr_detect_deadlock(), "Check for multiple rwlock");
1157 pthread_join(id1, NULL);
1158 pthread_join(id2, NULL);
1159 pthread_join(id3, NULL);
1163 pthread_create(&id1, NULL, mix_rwl_mutex, &wr);
1164 nok(lmgr_detect_deadlock(), "Check for mix rwlock/mutex");
1166 nok(lmgr_detect_deadlock(), "Check for mix rwlock/mutex");
1167 rwl_writeunlock(&wr);
1168 nok(lmgr_detect_deadlock(), "Check for mix rwlock/mutex");
1169 pthread_join(id1, NULL);
1176 nok(lmgr_detect_deadlock(), "Check for wrong order");
1178 for(int j=0; j<200; j++) {
1179 pthread_create(&tab[j], NULL, thx, NULL);
1181 for(int j=0; j<200; j++) {
1182 pthread_join(tab[j], NULL);
1183 if (j%3) { lmgr_detect_deadlock();}
1185 nok(lmgr_detect_deadlock(), "Check 200 lockers");
1194 pthread_create(&id1, NULL, th1, NULL);
1196 pthread_create(&id2, NULL, th2, NULL);
1198 ok(lmgr_detect_deadlock(), "Check for deadlock");
1200 pthread_create(&id3, NULL, th_prio, NULL);
1201 pthread_join(id3, &ret);
1202 ok(ret != 0, "Check for priority segfault");
1205 ok(self->max_priority == 1, "Check max_priority 1/4");
1207 ok(self->max_priority == 2, "Check max_priority 2/4");
1209 ok(self->max_priority == 3, "Check max_priority 3/4");
1211 ok(self->max_priority == 3, "Check max_priority 4/4");
1213 ok(self->max_priority == 3, "Check max_priority 1/5");
1215 ok(self->max_priority == 2, "Check max_priority 4/5");
1217 ok(self->max_priority == 1, "Check max_priority 4/5");
1219 ok(self->max_priority == 0, "Check max_priority 5/5");
1226 ok(self->max_priority == 3, "Check max_priority mixed");
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 == 0, "Check max_priority mixed");
1234 ok(self->max_priority == 0, "Check max_priority mixed");
1243 // pthread_create(&id3, NULL, th3, NULL);
1245 // pthread_join(id1, NULL);
1246 // pthread_join(id2, NULL);
1247 lmgr_cleanup_main();
1248 sm_check(__FILE__, __LINE__, false);