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(p) {PTHREAD_MUTEX_INITIALIZER, p}
916 #define P(x) bthread_mutex_lock_p(&(x), __FILE__, __LINE__)
917 #define V(x) bthread_mutex_unlock_p(&(x), __FILE__, __LINE__)
918 #define pthread_create(a, b, c, d) lmgr_thread_create(a,b,c,d)
920 bthread_mutex_t mutex1 = BTHREAD_MUTEX_NO_PRIORITY;
921 bthread_mutex_t mutex2 = BTHREAD_MUTEX_NO_PRIORITY;
922 bthread_mutex_t mutex3 = BTHREAD_MUTEX_NO_PRIORITY;
923 bthread_mutex_t mutex4 = BTHREAD_MUTEX_NO_PRIORITY;
924 bthread_mutex_t mutex5 = BTHREAD_MUTEX_NO_PRIORITY;
925 bthread_mutex_t mutex6 = BTHREAD_MUTEX_NO_PRIORITY;
926 bthread_mutex_t mutex_p1 = BTHREAD_MUTEX_PRIORITY(1);
927 bthread_mutex_t mutex_p2 = BTHREAD_MUTEX_PRIORITY(2);
928 bthread_mutex_t mutex_p3 = BTHREAD_MUTEX_PRIORITY(3);
929 static const char *my_prog;
931 void *self_lock(void *temp)
940 void *nolock(void *temp)
948 void *locker(void *temp)
950 bthread_mutex_t *m = (bthread_mutex_t*) temp;
956 void *rwlocker(void *temp)
958 brwlock_t *m = (brwlock_t*) temp;
967 void *mix_rwl_mutex(void *temp)
969 brwlock_t *m = (brwlock_t*) temp;
978 void *th2(void *temp)
993 void *th1(void *temp)
1010 void *thx(void *temp)
1012 int s= 1 + (int) (500.0 * (rand() / (RAND_MAX + 1.0))) + 200;
1023 void *th3(void *a) {
1025 fprintf(stderr, "undertaker sleep()\n");
1028 if (lmgr_detect_deadlock()) {
1036 void *th_prio(void *a) {
1038 bstrncpy(buf, my_prog, sizeof(buf));
1039 bstrncat(buf, " priority", sizeof(buf));
1040 int ret = system(buf);
1046 void _ok(const char *file, int l, const char *op, int value, const char *label)
1051 printf("ERR %.30s %s:%i on %s\n", label, file, l, op);
1053 printf("OK %.30s\n", label);
1057 #define ok(x, label) _ok(__FILE__, __LINE__, #x, (x), label)
1059 void _nok(const char *file, int l, const char *op, int value, const char *label)
1064 printf("ERR %.30s %s:%i on !%s\n", label, file, l, op);
1066 printf("OK %.30s\n", label);
1070 #define nok(x, label) _nok(__FILE__, __LINE__, #x, (x), label)
1074 printf("Result %i/%i OK\n", nb - err, nb);
1080 * - Must detect multiple lock
1081 * - lock/unlock in wrong order
1082 * - deadlock with 2 or 3 threads
1084 int main(int argc, char **argv)
1087 lmgr_thread_t *self;
1088 pthread_t id1, id2, id3, tab[200];
1089 bthread_mutex_t bmutex1;
1090 pthread_mutex_t pmutex2;
1093 use_undertaker = false;
1095 self = lmgr_get_thread_info();
1097 if (argc == 2) { /* do priority check */
1098 P(mutex_p2); /* not permited */
1100 V(mutex_p1); /* never goes here */
1105 pthread_mutex_init(&bmutex1, NULL);
1106 bthread_mutex_set_priority(&bmutex1, 10);
1108 pthread_mutex_init(&pmutex2, NULL);
1110 ok(self->max_priority == 10, "Check self max_priority");
1112 ok(bmutex1.priority == 10, "Check bmutex_set_priority()");
1115 ok(self->max_priority == 0, "Check self max_priority");
1117 pthread_create(&id1, NULL, self_lock, NULL);
1119 ok(lmgr_detect_deadlock(), "Check self deadlock");
1120 lmgr_v(&mutex1.mutex); /* a bit dirty */
1121 pthread_join(id1, NULL);
1124 pthread_create(&id1, NULL, nolock, NULL);
1126 nok(lmgr_detect_deadlock(), "Check for nolock");
1127 pthread_join(id1, NULL);
1130 pthread_create(&id1, NULL, locker, &mutex1);
1131 pthread_create(&id2, NULL, locker, &mutex1);
1132 pthread_create(&id3, NULL, locker, &mutex1);
1134 nok(lmgr_detect_deadlock(), "Check for multiple lock");
1136 pthread_join(id1, NULL);
1137 pthread_join(id2, NULL);
1138 pthread_join(id3, NULL);
1145 pthread_create(&id1, NULL, rwlocker, &wr);
1146 pthread_create(&id2, NULL, rwlocker, &wr);
1147 pthread_create(&id3, NULL, rwlocker, &wr);
1148 nok(lmgr_detect_deadlock(), "Check for multiple rwlock");
1149 rwl_writeunlock(&wr);
1150 nok(lmgr_detect_deadlock(), "Check for simple rwlock");
1151 rwl_writeunlock(&wr);
1152 nok(lmgr_detect_deadlock(), "Check for multiple rwlock");
1154 pthread_join(id1, NULL);
1155 pthread_join(id2, NULL);
1156 pthread_join(id3, NULL);
1160 pthread_create(&id1, NULL, mix_rwl_mutex, &wr);
1161 nok(lmgr_detect_deadlock(), "Check for mix rwlock/mutex");
1163 nok(lmgr_detect_deadlock(), "Check for mix rwlock/mutex");
1164 rwl_writeunlock(&wr);
1165 nok(lmgr_detect_deadlock(), "Check for mix rwlock/mutex");
1166 pthread_join(id1, NULL);
1173 nok(lmgr_detect_deadlock(), "Check for wrong order");
1175 for(int j=0; j<200; j++) {
1176 pthread_create(&tab[j], NULL, thx, NULL);
1178 for(int j=0; j<200; j++) {
1179 pthread_join(tab[j], NULL);
1180 if (j%3) { lmgr_detect_deadlock();}
1182 nok(lmgr_detect_deadlock(), "Check 200 lockers");
1191 pthread_create(&id1, NULL, th1, NULL);
1193 pthread_create(&id2, NULL, th2, NULL);
1195 ok(lmgr_detect_deadlock(), "Check for deadlock");
1197 pthread_create(&id3, NULL, th_prio, NULL);
1198 pthread_join(id3, &ret);
1199 ok(ret != 0, "Check for priority segfault");
1202 ok(self->max_priority == 1, "Check max_priority 1/4");
1204 ok(self->max_priority == 2, "Check max_priority 2/4");
1206 ok(self->max_priority == 3, "Check max_priority 3/4");
1208 ok(self->max_priority == 3, "Check max_priority 4/4");
1210 ok(self->max_priority == 3, "Check max_priority 1/5");
1212 ok(self->max_priority == 2, "Check max_priority 4/5");
1214 ok(self->max_priority == 1, "Check max_priority 4/5");
1216 ok(self->max_priority == 0, "Check max_priority 5/5");
1223 ok(self->max_priority == 3, "Check max_priority mixed");
1225 ok(self->max_priority == 3, "Check max_priority mixed");
1227 ok(self->max_priority == 3, "Check max_priority mixed");
1229 ok(self->max_priority == 0, "Check max_priority mixed");
1231 ok(self->max_priority == 0, "Check max_priority mixed");
1240 // pthread_create(&id3, NULL, th3, NULL);
1242 // pthread_join(id1, NULL);
1243 // pthread_join(id2, NULL);
1244 lmgr_cleanup_main();
1245 sm_check(__FILE__, __LINE__, false);