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); // you can also use bthread_mutex_init()
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 %s:%i\n",
288 (lock_list[i].state=='W')?"Wanted ":"Granted",
289 lock_list[i].file, lock_list[i].line);
293 void dump(FILE *fp) {
302 * Call before a lock operation (mark mutex as WANTED)
304 virtual void pre_P(void *m, int priority,
305 const char *f="*unknown*", int l=0) {
306 ASSERT_p(current < LMGR_MAX_LOCK, f, l);
307 ASSERT_p(current >= -1, f, l);
308 ASSERT_p(!priority || priority >= max_priority, f, l);
312 lock_list[current].lock = m;
313 lock_list[current].state = LMGR_LOCK_WANTED;
314 lock_list[current].file = f;
315 lock_list[current].line = l;
316 lock_list[current].priority = priority;
317 lock_list[current].max_priority = MAX(priority, max_priority);
318 max = MAX(current, max);
319 max_priority = MAX(priority, max_priority);
325 * Call after the lock operation (mark mutex as GRANTED)
327 virtual void post_P() {
328 ASSERT(current >= 0);
329 ASSERT(lock_list[current].state == LMGR_LOCK_WANTED);
330 lock_list[current].state = LMGR_LOCK_GRANTED;
333 /* Using this function is some sort of bug */
334 void shift_list(int i) {
335 for(int j=i+1; j<=current; j++) {
336 lock_list[i] = lock_list[j];
339 lock_list[current].lock = NULL;
340 lock_list[current].state = LMGR_LOCK_EMPTY;
342 /* rebuild the priority list */
344 for(int j=0; j< current; j++) {
345 max_priority = MAX(lock_list[j].priority, max_priority);
346 lock_list[j].max_priority = max_priority;
351 * Remove the mutex from the list
353 virtual void do_V(void *m, const char *f="*unknown*", int l=0) {
354 ASSERT_p(current >= 0, f, l);
357 if (lock_list[current].lock == m) {
358 lock_list[current].lock = NULL;
359 lock_list[current].state = LMGR_LOCK_EMPTY;
363 Pmsg3(0, "ERROR: wrong P/V order search lock=%p %s:%i\n", m, f, l);
364 Pmsg4(000, "ERROR: wrong P/V order pos=%i lock=%p %s:%i\n",
365 current, lock_list[current].lock, lock_list[current].file,
366 lock_list[current].line);
367 for (int i=current-1; i >= 0; i--) { /* already seen current */
368 Pmsg4(000, "ERROR: wrong P/V order pos=%i lock=%p %s:%i\n",
369 i, lock_list[i].lock, lock_list[i].file, lock_list[i].line);
370 if (lock_list[i].lock == m) {
371 Pmsg3(000, "ERROR: FOUND P pos=%i %s:%i\n", i, f, l);
378 /* reset max_priority to the last one */
380 max_priority = lock_list[current].max_priority;
388 virtual ~lmgr_thread_t() {destroy();}
391 pthread_mutex_destroy(&mutex);
395 class lmgr_dummy_thread_t: public lmgr_thread_t
397 void do_V(void *m, const char *file, int l) {}
399 void pre_P(void *m, int priority, const char *file, int l) {}
403 * LMGR - Lock Manager
409 pthread_once_t key_lmgr_once = PTHREAD_ONCE_INIT;
410 static pthread_key_t lmgr_key; /* used to get lgmr_thread_t object */
412 static dlist *global_mgr = NULL; /* used to store all lgmr_thread_t objects */
413 static pthread_mutex_t lmgr_global_mutex = PTHREAD_MUTEX_INITIALIZER;
414 static pthread_t undertaker;
415 static bool use_undertaker=true;
417 #define lmgr_is_active() (global_mgr != NULL)
420 * Add a new lmgr_thread_t object to the global list
422 void lmgr_register_thread(lmgr_thread_t *item)
424 lmgr_p(&lmgr_global_mutex);
426 global_mgr->prepend(item);
428 lmgr_v(&lmgr_global_mutex);
432 * Call this function to cleanup specific lock thread data
434 void lmgr_unregister_thread(lmgr_thread_t *item)
436 if (!lmgr_is_active()) {
439 lmgr_p(&lmgr_global_mutex);
441 global_mgr->remove(item);
443 lmgr_v(&lmgr_global_mutex);
447 * Search for a deadlock when it's secure to walk across
448 * locks list. (after lmgr_detect_deadlock or a fatal signal)
450 bool lmgr_detect_deadlock_unlocked()
453 lmgr_node_t *node=NULL;
456 dlist *g = New(dlist(node, &node->link));
458 /* First, get a list of all node */
459 foreach_dlist(item, global_mgr) {
460 for(int i=0; i<=item->current; i++) {
462 lock = &item->lock_list[i];
463 /* Depending if the lock is granted or not, it's a child or a root
464 * Granted: Mutex -> Thread
465 * Wanted: Thread -> Mutex
467 * Note: a Mutex can be locked only once, a thread can request only
471 if (lock->state == LMGR_LOCK_GRANTED) {
472 node = New(lmgr_node_t((void*)lock->lock, (void*)item->thread_id));
473 } else if (lock->state == LMGR_LOCK_WANTED) {
474 node = New(lmgr_node_t((void*)item->thread_id, (void*)lock->lock));
482 //foreach_dlist(node, g) {
483 // printf("g n=%p c=%p\n", node->node, node->child);
486 ret = contains_cycle(g);
488 printf("Found a deadlock !!!!\n");
496 * Search for a deadlock in during the runtime
497 * It will lock all thread specific lock manager, nothing
498 * can be locked during this check.
500 bool lmgr_detect_deadlock()
503 if (!lmgr_is_active()) {
507 lmgr_p(&lmgr_global_mutex);
510 foreach_dlist(item, global_mgr) {
511 lmgr_p(&item->mutex);
514 ret = lmgr_detect_deadlock_unlocked();
516 foreach_dlist(item, global_mgr) {
517 lmgr_v(&item->mutex);
520 lmgr_v(&lmgr_global_mutex);
527 * Use this function is used only after a fatal signal
528 * We don't use locking to display the information
530 void dbg_print_lock(FILE *fp)
532 fprintf(fp, "Attempt to dump locks\n");
533 if (!lmgr_is_active()) {
537 foreach_dlist(item, global_mgr) {
543 * Dump each lmgr_thread_t object
547 lmgr_p(&lmgr_global_mutex);
550 foreach_dlist(item, global_mgr) {
554 lmgr_v(&lmgr_global_mutex);
557 void cln_hdl(void *a)
559 lmgr_cleanup_thread();
562 void *check_deadlock(void *)
566 pthread_cleanup_push(cln_hdl, NULL);
568 while (!bmicrosleep(30, 0)) {
569 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old);
570 if (lmgr_detect_deadlock()) {
574 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old);
575 pthread_testcancel();
577 Pmsg0(000, "Undertaker is leaving...\n");
578 pthread_cleanup_pop(1);
582 /* This object is used when LMGR is not initialized */
583 static lmgr_dummy_thread_t dummy_lmgr;
586 * Retrieve the lmgr_thread_t object from the stack
588 inline lmgr_thread_t *lmgr_get_thread_info()
590 if (lmgr_is_active()) {
591 return (lmgr_thread_t *)pthread_getspecific(lmgr_key);
598 * launch once for all threads
600 void create_lmgr_key()
602 int status = pthread_key_create(&lmgr_key, NULL);
605 Pmsg1(000, _("pthread key create failed: ERR=%s\n"),
606 be.bstrerror(status));
610 lmgr_thread_t *n=NULL;
611 global_mgr = New(dlist(n, &n->link));
613 if (use_undertaker) {
614 status = pthread_create(&undertaker, NULL, check_deadlock, NULL);
617 Pmsg1(000, _("pthread_create failed: ERR=%s\n"),
618 be.bstrerror(status));
625 * Each thread have to call this function to put a lmgr_thread_t object
626 * in the stack and be able to call mutex_lock/unlock
628 void lmgr_init_thread()
630 int status = pthread_once(&key_lmgr_once, create_lmgr_key);
633 Pmsg1(000, _("pthread key create failed: ERR=%s\n"),
634 be.bstrerror(status));
637 lmgr_thread_t *l = New(lmgr_thread_t());
638 pthread_setspecific(lmgr_key, l);
639 lmgr_register_thread(l);
643 * Call this function at the end of the thread
645 void lmgr_cleanup_thread()
647 if (!lmgr_is_active()) {
650 lmgr_thread_t *self = lmgr_get_thread_info();
651 lmgr_unregister_thread(self);
656 * This function should be call at the end of the main thread
657 * Some thread like the watchdog are already present, so the global_mgr
658 * list is never empty. Should carefully clear the memory.
660 void lmgr_cleanup_main()
667 if (use_undertaker) {
668 pthread_cancel(undertaker);
670 lmgr_cleanup_thread();
671 lmgr_p(&lmgr_global_mutex);
677 lmgr_v(&lmgr_global_mutex);
681 * Set the priority of the lmgr mutex object
683 void bthread_mutex_set_priority(bthread_mutex_t *m, int prio)
689 * Replacement for pthread_mutex_init()
691 int bthread_mutex_init(bthread_mutex_t *m, const pthread_mutexattr_t *attr)
694 return pthread_mutex_init(&m->mutex, attr);
698 * Replacement for pthread_mutex_destroy()
700 int bthread_mutex_destroy(bthread_mutex_t *m)
702 return pthread_mutex_destroy(&m->mutex);
706 * Replacement for pthread_mutex_init() for pthread_mutex_t
708 int bthread_mutex_init(pthread_mutex_t *m, const pthread_mutexattr_t *attr)
710 return pthread_mutex_init(m, attr);
714 * Replacement for pthread_mutex_destroy() for pthread_mutex_t
716 int bthread_mutex_destroy(pthread_mutex_t *m)
718 return pthread_mutex_destroy(m);
723 * Replacement for pthread_mutex_lock()
726 int bthread_mutex_lock_p(bthread_mutex_t *m, const char *file, int line)
728 lmgr_thread_t *self = lmgr_get_thread_info();
729 self->pre_P(m, m->priority, file, line);
736 * Replacement for pthread_mutex_unlock()
739 int bthread_mutex_unlock_p(bthread_mutex_t *m, const char *file, int line)
741 lmgr_thread_t *self = lmgr_get_thread_info();
742 self->do_V(m, file, line);
748 * Replacement for pthread_mutex_lock() but with real pthread_mutex_t
751 int bthread_mutex_lock_p(pthread_mutex_t *m, const char *file, int line)
753 lmgr_thread_t *self = lmgr_get_thread_info();
754 self->pre_P(m, 0, file, line);
761 * Replacement for pthread_mutex_unlock() but with real pthread_mutex_t
764 int bthread_mutex_unlock_p(pthread_mutex_t *m, const char *file, int line)
766 lmgr_thread_t *self = lmgr_get_thread_info();
767 self->do_V(m, file, line);
775 int bthread_cond_wait_p(pthread_cond_t *cond,
777 const char *file, int line)
780 lmgr_thread_t *self = lmgr_get_thread_info();
781 self->do_V(m, file, line);
782 ret = pthread_cond_wait(cond, m);
783 self->pre_P(m, 0, file, line);
790 int bthread_cond_timedwait_p(pthread_cond_t *cond,
792 const struct timespec * abstime,
793 const char *file, int line)
796 lmgr_thread_t *self = lmgr_get_thread_info();
797 self->do_V(m, file, line);
798 ret = pthread_cond_timedwait(cond, m, abstime);
799 self->pre_P(m, 0, file, line);
806 int bthread_cond_wait_p(pthread_cond_t *cond,
808 const char *file, int line)
811 lmgr_thread_t *self = lmgr_get_thread_info();
812 self->do_V(m, file, line);
813 ret = pthread_cond_wait(cond, &m->mutex);
814 self->pre_P(m, m->priority, file, line);
821 int bthread_cond_timedwait_p(pthread_cond_t *cond,
823 const struct timespec * abstime,
824 const char *file, int line)
827 lmgr_thread_t *self = lmgr_get_thread_info();
828 self->do_V(m, file, line);
829 ret = pthread_cond_timedwait(cond, &m->mutex, abstime);
830 self->pre_P(m, m->priority, file, line);
836 * Use this function when the caller handle the mutex directly
838 * lmgr_pre_lock(m, 10);
839 * pthread_mutex_lock(m);
842 void lmgr_pre_lock(void *m, int prio, const char *file, int line)
844 lmgr_thread_t *self = lmgr_get_thread_info();
845 self->pre_P(m, prio, file, line);
849 * Use this function when the caller handle the mutex directly
851 void lmgr_post_lock()
853 lmgr_thread_t *self = lmgr_get_thread_info();
858 * Do directly pre_P and post_P (used by trylock)
860 void lmgr_do_lock(void *m, int prio, const char *file, int line)
862 lmgr_thread_t *self = lmgr_get_thread_info();
863 self->pre_P(m, prio, file, line);
868 * Use this function when the caller handle the mutex directly
870 void lmgr_do_unlock(void *m)
872 lmgr_thread_t *self = lmgr_get_thread_info();
877 void *(*start_routine)(void*);
882 void *lmgr_thread_launcher(void *x)
886 pthread_cleanup_push(cln_hdl, NULL);
888 lmgr_thread_arg_t arg;
889 lmgr_thread_arg_t *a = (lmgr_thread_arg_t *)x;
890 arg.start_routine = a->start_routine;
894 ret = arg.start_routine(arg.arg);
895 pthread_cleanup_pop(1);
899 int lmgr_thread_create(pthread_t *thread,
900 const pthread_attr_t *attr,
901 void *(*start_routine)(void*), void *arg)
903 /* lmgr should be active (lmgr_init_thread() call in main()) */
904 ASSERT(lmgr_is_active());
905 /* Will be freed by the child */
906 lmgr_thread_arg_t *a = (lmgr_thread_arg_t*) malloc(sizeof(lmgr_thread_arg_t));
907 a->start_routine = start_routine;
909 return pthread_create(thread, attr, lmgr_thread_launcher, a);
912 #else /* _USE_LOCKMGR */
916 * Use this function is used only after a fatal signal
917 * We don't use locking to display information
919 void dbg_print_lock(FILE *fp)
921 Pmsg0(000, "lockmgr disabled\n");
924 #endif /* _USE_LOCKMGR */
929 #define BTHREAD_MUTEX_NO_PRIORITY {PTHREAD_MUTEX_INITIALIZER, 0}
930 #define BTHREAD_MUTEX_PRIORITY_1 {PTHREAD_MUTEX_INITIALIZER, 1}
931 #define BTHREAD_MUTEX_PRIORITY_2 {PTHREAD_MUTEX_INITIALIZER, 2}
932 #define BTHREAD_MUTEX_PRIORITY_3 {PTHREAD_MUTEX_INITIALIZER, 3}
933 #define BTHREAD_MUTEX_PRIORITY_4 {PTHREAD_MUTEX_INITIALIZER, 4}
936 #define P(x) bthread_mutex_lock_p(&(x), __FILE__, __LINE__)
937 #define V(x) bthread_mutex_unlock_p(&(x), __FILE__, __LINE__)
938 #define pthread_create(a, b, c, d) lmgr_thread_create(a,b,c,d)
940 bthread_mutex_t mutex1 = BTHREAD_MUTEX_NO_PRIORITY;
941 bthread_mutex_t mutex2 = BTHREAD_MUTEX_NO_PRIORITY;
942 bthread_mutex_t mutex3 = BTHREAD_MUTEX_NO_PRIORITY;
943 bthread_mutex_t mutex4 = BTHREAD_MUTEX_NO_PRIORITY;
944 bthread_mutex_t mutex5 = BTHREAD_MUTEX_NO_PRIORITY;
945 bthread_mutex_t mutex6 = BTHREAD_MUTEX_NO_PRIORITY;
946 bthread_mutex_t mutex_p1 = BTHREAD_MUTEX_PRIORITY_1;
947 bthread_mutex_t mutex_p2 = BTHREAD_MUTEX_PRIORITY_2;
948 bthread_mutex_t mutex_p3 = BTHREAD_MUTEX_PRIORITY_3;
949 static const char *my_prog;
951 void *self_lock(void *temp)
960 void *nolock(void *temp)
968 void *locker(void *temp)
970 bthread_mutex_t *m = (bthread_mutex_t*) temp;
976 void *rwlocker(void *temp)
978 brwlock_t *m = (brwlock_t*) temp;
987 void *mix_rwl_mutex(void *temp)
989 brwlock_t *m = (brwlock_t*) temp;
998 void *th2(void *temp)
1013 void *th1(void *temp)
1030 void *thx(void *temp)
1032 int s= 1 + (int) (500.0 * (rand() / (RAND_MAX + 1.0))) + 200;
1043 void *th3(void *a) {
1045 fprintf(stderr, "undertaker sleep()\n");
1048 if (lmgr_detect_deadlock()) {
1056 void *th_prio(void *a) {
1058 bstrncpy(buf, my_prog, sizeof(buf));
1059 bstrncat(buf, " priority", sizeof(buf));
1060 int ret = system(buf);
1066 void _ok(const char *file, int l, const char *op, int value, const char *label)
1071 printf("ERR %.30s %s:%i on %s\n", label, file, l, op);
1073 printf("OK %.30s\n", label);
1077 #define ok(x, label) _ok(__FILE__, __LINE__, #x, (x), label)
1079 void _nok(const char *file, int l, const char *op, int value, const char *label)
1084 printf("ERR %.30s %s:%i on !%s\n", label, file, l, op);
1086 printf("OK %.30s\n", label);
1090 #define nok(x, label) _nok(__FILE__, __LINE__, #x, (x), label)
1094 printf("Result %i/%i OK\n", nb - err, nb);
1100 * - Must detect multiple lock
1101 * - lock/unlock in wrong order
1102 * - deadlock with 2 or 3 threads
1104 int main(int argc, char **argv)
1107 lmgr_thread_t *self;
1108 pthread_t id1, id2, id3, tab[200];
1111 use_undertaker = false;
1114 if (argc == 2) { /* do priority check */
1115 P(mutex_p2); /* not permited */
1117 V(mutex_p1); /* never goes here */
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");
1206 self = lmgr_get_thread_info();
1208 ok(self->max_priority == 1, "Check max_priority 1/4");
1210 ok(self->max_priority == 2, "Check max_priority 2/4");
1212 ok(self->max_priority == 3, "Check max_priority 3/4");
1214 ok(self->max_priority == 3, "Check max_priority 4/4");
1216 ok(self->max_priority == 3, "Check max_priority 1/5");
1218 ok(self->max_priority == 2, "Check max_priority 4/5");
1220 ok(self->max_priority == 1, "Check max_priority 4/5");
1222 ok(self->max_priority == 0, "Check max_priority 5/5");
1229 ok(self->max_priority == 3, "Check max_priority mixed");
1231 ok(self->max_priority == 3, "Check max_priority mixed");
1233 ok(self->max_priority == 3, "Check max_priority mixed");
1235 ok(self->max_priority == 0, "Check max_priority mixed");
1237 ok(self->max_priority == 0, "Check max_priority mixed");
1246 // pthread_create(&id3, NULL, th3, NULL);
1248 // pthread_join(id1, NULL);
1249 // pthread_join(id2, NULL);
1250 lmgr_cleanup_main();
1251 sm_check(__FILE__, __LINE__, false);