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 %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 pthread_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 pthread_mutex_destroy(bthread_mutex_t *m)
702 return pthread_mutex_destroy(&m->mutex);
706 * Replacement for pthread_mutex_lock()
709 int bthread_mutex_lock_p(bthread_mutex_t *m, const char *file, int line)
711 lmgr_thread_t *self = lmgr_get_thread_info();
712 self->pre_P(m, m->priority, file, line);
719 * Replacement for pthread_mutex_unlock()
722 int bthread_mutex_unlock_p(bthread_mutex_t *m, const char *file, int line)
724 lmgr_thread_t *self = lmgr_get_thread_info();
725 self->do_V(m, file, line);
731 * Replacement for pthread_mutex_lock() but with real pthread_mutex_t
734 int bthread_mutex_lock_p(pthread_mutex_t *m, const char *file, int line)
736 lmgr_thread_t *self = lmgr_get_thread_info();
737 self->pre_P(m, 0, file, line);
744 * Replacement for pthread_mutex_unlock() but with real pthread_mutex_t
747 int bthread_mutex_unlock_p(pthread_mutex_t *m, const char *file, int line)
749 lmgr_thread_t *self = lmgr_get_thread_info();
750 self->do_V(m, file, line);
758 int bthread_cond_wait_p(pthread_cond_t *cond,
760 const char *file, int line)
763 lmgr_thread_t *self = lmgr_get_thread_info();
764 self->do_V(m, file, line);
765 ret = pthread_cond_wait(cond, m);
766 self->pre_P(m, 0, file, line);
773 int bthread_cond_timedwait_p(pthread_cond_t *cond,
775 const struct timespec * abstime,
776 const char *file, int line)
779 lmgr_thread_t *self = lmgr_get_thread_info();
780 self->do_V(m, file, line);
781 ret = pthread_cond_timedwait(cond, m, abstime);
782 self->pre_P(m, 0, file, line);
789 int bthread_cond_wait_p(pthread_cond_t *cond,
791 const char *file, int line)
794 lmgr_thread_t *self = lmgr_get_thread_info();
795 self->do_V(m, file, line);
796 ret = pthread_cond_wait(cond, &m->mutex);
797 self->pre_P(m, m->priority, file, line);
804 int bthread_cond_timedwait_p(pthread_cond_t *cond,
806 const struct timespec * abstime,
807 const char *file, int line)
810 lmgr_thread_t *self = lmgr_get_thread_info();
811 self->do_V(m, file, line);
812 ret = pthread_cond_timedwait(cond, &m->mutex, abstime);
813 self->pre_P(m, m->priority, file, line);
819 * Use this function when the caller handle the mutex directly
821 * lmgr_pre_lock(m, 10);
822 * pthread_mutex_lock(m);
825 void lmgr_pre_lock(void *m, int prio, const char *file, int line)
827 lmgr_thread_t *self = lmgr_get_thread_info();
828 self->pre_P(m, prio, file, line);
832 * Use this function when the caller handle the mutex directly
834 void lmgr_post_lock()
836 lmgr_thread_t *self = lmgr_get_thread_info();
841 * Do directly pre_P and post_P (used by trylock)
843 void lmgr_do_lock(void *m, int prio, const char *file, int line)
845 lmgr_thread_t *self = lmgr_get_thread_info();
846 self->pre_P(m, prio, file, line);
851 * Use this function when the caller handle the mutex directly
853 void lmgr_do_unlock(void *m)
855 lmgr_thread_t *self = lmgr_get_thread_info();
860 void *(*start_routine)(void*);
865 void *lmgr_thread_launcher(void *x)
869 pthread_cleanup_push(cln_hdl, NULL);
871 lmgr_thread_arg_t arg;
872 lmgr_thread_arg_t *a = (lmgr_thread_arg_t *)x;
873 arg.start_routine = a->start_routine;
877 ret = arg.start_routine(arg.arg);
878 pthread_cleanup_pop(1);
882 int lmgr_thread_create(pthread_t *thread,
883 const pthread_attr_t *attr,
884 void *(*start_routine)(void*), void *arg)
886 /* lmgr should be active (lmgr_init_thread() call in main()) */
887 ASSERT(lmgr_is_active());
888 /* Will be freed by the child */
889 lmgr_thread_arg_t *a = (lmgr_thread_arg_t*) malloc(sizeof(lmgr_thread_arg_t));
890 a->start_routine = start_routine;
892 return pthread_create(thread, attr, lmgr_thread_launcher, a);
895 #else /* _USE_LOCKMGR */
899 * Use this function is used only after a fatal signal
900 * We don't use locking to display information
902 void dbg_print_lock(FILE *fp)
904 Pmsg0(000, "lockmgr disabled\n");
907 #endif /* _USE_LOCKMGR */
912 #define BTHREAD_MUTEX_NO_PRIORITY {PTHREAD_MUTEX_INITIALIZER, 0}
913 #define BTHREAD_MUTEX_PRIORITY_1 {PTHREAD_MUTEX_INITIALIZER, 1}
914 #define BTHREAD_MUTEX_PRIORITY_2 {PTHREAD_MUTEX_INITIALIZER, 2}
915 #define BTHREAD_MUTEX_PRIORITY_3 {PTHREAD_MUTEX_INITIALIZER, 3}
916 #define BTHREAD_MUTEX_PRIORITY_4 {PTHREAD_MUTEX_INITIALIZER, 4}
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);