2 Bacula® - The Network Backup Solution
4 Copyright (C) 2008-2010 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 ------------------------------------------------
33 Note: see file mutex_list.h for current mutexes with
37 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
43 bthread_mutex_t mutex = BTHREAD_MUTEX_PRIORITY(1);
48 Mutex that doesn't need this extra check can be declared as pthread_mutex_t.
49 You can use this object on pthread_mutex_lock/unlock/cond_wait/cond_timewait.
51 With dynamic creation, you can use:
52 bthread_mutex_t mutex;
53 pthread_mutex_init(&mutex);
54 bthread_mutex_set_priority(&mutex, 10);
55 pthread_mutex_destroy(&mutex);
59 #define _LOCKMGR_COMPLIANT
63 #define ASSERT(x) if (!(x)) { \
65 Pmsg3(000, _("ASSERT failed at %s:%i: %s\n"), __FILE__, __LINE__, #x); \
68 #define ASSERT_p(x,f,l) if (!(x)) { \
70 Pmsg3(000, _("ASSERT failed at %s:%i: %s \n"), f, l, #x); \
75 http://www.cs.berkeley.edu/~kamil/teaching/sp03/041403.pdf
77 This lock manager will replace some pthread calls. It can be
78 enabled with _USE_LOCKMGR
80 Some part of the code can't use this manager, for example the
81 rwlock object or the smartalloc lib. To disable LMGR, just add
82 _LOCKMGR_COMPLIANT before the inclusion of "bacula.h"
85 g++ -g -c lockmgr.c -I.. -I../lib -D_USE_LOCKMGR -D_TEST_IT
86 g++ -o lockmgr lockmgr.o -lbac -L../lib/.libs -lssl -lpthread
92 * pthread_mutex_lock for memory allocator and other
93 * parts that are _LOCKMGR_COMPLIANT
95 void lmgr_p(pthread_mutex_t *m)
98 if ((errstat=pthread_mutex_lock(m))) {
100 e_msg(__FILE__, __LINE__, M_ABORT, 0, _("Mutex lock failure. ERR=%s\n"),
101 be.bstrerror(errstat));
105 void lmgr_v(pthread_mutex_t *m)
108 if ((errstat=pthread_mutex_unlock(m))) {
110 e_msg(__FILE__, __LINE__, M_ABORT, 0, _("Mutex unlock failure. ERR=%s\n"),
111 be.bstrerror(errstat));
119 LMGR_WHITE, /* never seen */
120 LMGR_BLACK, /* no loop */
121 LMGR_GREY, /* seen before */
125 * Node used by the Lock Manager
126 * If the lock is GRANTED, we have mutex -> proc, else it's a proc -> mutex
129 * Note, each mutex can be GRANTED once, and each proc can have only one WANTED
132 class lmgr_node_t: public SMARTALLOC
145 lmgr_node_t(void *n, void *c) {
149 void init(void *n, void *c) {
155 void mark_as_seen(lmgr_color_t c) {
159 ~lmgr_node_t() {printf("delete node\n");}
163 LMGR_LOCK_EMPTY = 'E', /* unused */
164 LMGR_LOCK_WANTED = 'W', /* before mutex_lock */
165 LMGR_LOCK_GRANTED = 'G' /* after mutex_lock */
169 * Object associated with each mutex per thread
171 class lmgr_lock_t: public SMARTALLOC
185 state = LMGR_LOCK_EMPTY;
186 priority = max_priority = 0;
189 lmgr_lock_t(void *l) {
191 state = LMGR_LOCK_WANTED;
195 state = LMGR_LOCK_GRANTED;
203 * Get the child list, ret must be already allocated
205 static void search_all_node(dlist *g, lmgr_node_t *v, alist *ret)
208 foreach_dlist(n, g) {
209 if (v->child == n->node) {
215 static bool visite(dlist *g, lmgr_node_t *v)
219 v->mark_as_seen(LMGR_GREY);
221 alist *d = New(alist(5, false)); /* use alist because own=false */
222 search_all_node(g, v, d);
224 //foreach_alist(n, d) {
225 // printf("node n=%p c=%p s=%c\n", n->node, n->child, n->seen);
228 foreach_alist(n, d) {
229 if (n->seen == LMGR_GREY) { /* already seen this node */
232 } else if (n->seen == LMGR_WHITE) {
239 v->mark_as_seen(LMGR_BLACK); /* no loop detected, node is clean */
245 static bool contains_cycle(dlist *g)
248 foreach_dlist(n, g) {
249 if (n->seen == LMGR_WHITE) {
258 /****************************************************************/
260 class lmgr_thread_t: public SMARTALLOC
264 pthread_mutex_t mutex;
266 lmgr_lock_t lock_list[LMGR_MAX_LOCK];
273 if ((status = pthread_mutex_init(&mutex, NULL)) != 0) {
275 Pmsg1(000, _("pthread key create failed: ERR=%s\n"),
276 be.bstrerror(status));
279 thread_id = pthread_self();
285 void _dump(FILE *fp) {
286 fprintf(fp, "threadid=%p max=%i current=%i\n",
287 (void *)thread_id, max, current);
288 for(int i=0; i<=current; i++) {
289 fprintf(fp, " lock=%p state=%s priority=%i %s:%i\n",
291 (lock_list[i].state=='W')?"Wanted ":"Granted",
292 lock_list[i].priority,
293 lock_list[i].file, lock_list[i].line);
297 void dump(FILE *fp) {
306 * Call before a lock operation (mark mutex as WANTED)
308 virtual void pre_P(void *m, int priority,
309 const char *f="*unknown*", int l=0)
311 int max_prio = max_priority;
312 ASSERT_p(current < LMGR_MAX_LOCK, f, l);
313 ASSERT_p(current >= -1, f, l);
317 lock_list[current].lock = m;
318 lock_list[current].state = LMGR_LOCK_WANTED;
319 lock_list[current].file = f;
320 lock_list[current].line = l;
321 lock_list[current].priority = priority;
322 lock_list[current].max_priority = MAX(priority, max_priority);
323 max = MAX(current, max);
324 max_priority = MAX(priority, max_priority);
327 ASSERT_p(!priority || priority >= max_prio, f, l);
331 * Call after the lock operation (mark mutex as GRANTED)
333 virtual void post_P() {
334 ASSERT(current >= 0);
335 ASSERT(lock_list[current].state == LMGR_LOCK_WANTED);
336 lock_list[current].state = LMGR_LOCK_GRANTED;
339 /* Using this function is some sort of bug */
340 void shift_list(int i) {
341 for(int j=i+1; j<=current; j++) {
342 lock_list[i] = lock_list[j];
345 lock_list[current].lock = NULL;
346 lock_list[current].state = LMGR_LOCK_EMPTY;
348 /* rebuild the priority list */
350 for(int j=0; j< current; j++) {
351 max_priority = MAX(lock_list[j].priority, max_priority);
352 lock_list[j].max_priority = max_priority;
357 * Remove the mutex from the list
359 virtual void do_V(void *m, const char *f="*unknown*", int l=0) {
360 ASSERT_p(current >= 0, f, l);
363 if (lock_list[current].lock == m) {
364 lock_list[current].lock = NULL;
365 lock_list[current].state = LMGR_LOCK_EMPTY;
369 Pmsg3(0, "ERROR: wrong P/V order search lock=%p %s:%i\n", m, f, l);
370 Pmsg4(000, "ERROR: wrong P/V order pos=%i lock=%p %s:%i\n",
371 current, lock_list[current].lock, lock_list[current].file,
372 lock_list[current].line);
373 for (int i=current-1; i >= 0; i--) { /* already seen current */
374 Pmsg4(000, "ERROR: wrong P/V order pos=%i lock=%p %s:%i\n",
375 i, lock_list[i].lock, lock_list[i].file, lock_list[i].line);
376 if (lock_list[i].lock == m) {
377 Pmsg3(000, "ERROR: FOUND P pos=%i %s:%i\n", i, f, l);
384 /* reset max_priority to the last one */
386 max_priority = lock_list[current].max_priority;
394 virtual ~lmgr_thread_t() {destroy();}
397 pthread_mutex_destroy(&mutex);
401 class lmgr_dummy_thread_t: public lmgr_thread_t
403 void do_V(void *m, const char *file, int l) {}
405 void pre_P(void *m, int priority, const char *file, int l) {}
409 * LMGR - Lock Manager
415 pthread_once_t key_lmgr_once = PTHREAD_ONCE_INIT;
416 static pthread_key_t lmgr_key; /* used to get lgmr_thread_t object */
418 static dlist *global_mgr = NULL; /* used to store all lgmr_thread_t objects */
419 static pthread_mutex_t lmgr_global_mutex = PTHREAD_MUTEX_INITIALIZER;
420 static pthread_t undertaker;
421 static bool use_undertaker=true;
423 #define lmgr_is_active() (global_mgr != NULL)
426 * Add a new lmgr_thread_t object to the global list
428 void lmgr_register_thread(lmgr_thread_t *item)
430 lmgr_p(&lmgr_global_mutex);
432 global_mgr->prepend(item);
434 lmgr_v(&lmgr_global_mutex);
438 * Call this function to cleanup specific lock thread data
440 void lmgr_unregister_thread(lmgr_thread_t *item)
442 if (!lmgr_is_active()) {
445 lmgr_p(&lmgr_global_mutex);
447 global_mgr->remove(item);
449 lmgr_v(&lmgr_global_mutex);
453 * Search for a deadlock when it's secure to walk across
454 * locks list. (after lmgr_detect_deadlock or a fatal signal)
456 bool lmgr_detect_deadlock_unlocked()
459 lmgr_node_t *node=NULL;
462 dlist *g = New(dlist(node, &node->link));
464 /* First, get a list of all node */
465 foreach_dlist(item, global_mgr) {
466 for(int i=0; i<=item->current; i++) {
468 lock = &item->lock_list[i];
469 /* Depending if the lock is granted or not, it's a child or a root
470 * Granted: Mutex -> Thread
471 * Wanted: Thread -> Mutex
473 * Note: a Mutex can be locked only once, a thread can request only
477 if (lock->state == LMGR_LOCK_GRANTED) {
478 node = New(lmgr_node_t((void*)lock->lock, (void*)item->thread_id));
479 } else if (lock->state == LMGR_LOCK_WANTED) {
480 node = New(lmgr_node_t((void*)item->thread_id, (void*)lock->lock));
488 //foreach_dlist(node, g) {
489 // printf("g n=%p c=%p\n", node->node, node->child);
492 ret = contains_cycle(g);
494 printf("Found a deadlock !!!!\n");
502 * Search for a deadlock in during the runtime
503 * It will lock all thread specific lock manager, nothing
504 * can be locked during this check.
506 bool lmgr_detect_deadlock()
509 if (!lmgr_is_active()) {
513 lmgr_p(&lmgr_global_mutex);
516 foreach_dlist(item, global_mgr) {
517 lmgr_p(&item->mutex);
520 ret = lmgr_detect_deadlock_unlocked();
522 foreach_dlist(item, global_mgr) {
523 lmgr_v(&item->mutex);
526 lmgr_v(&lmgr_global_mutex);
533 * Use this function is used only after a fatal signal
534 * We don't use locking to display the information
536 void dbg_print_lock(FILE *fp)
538 fprintf(fp, "Attempt to dump locks\n");
539 if (!lmgr_is_active()) {
543 foreach_dlist(item, global_mgr) {
549 * Dump each lmgr_thread_t object
553 lmgr_p(&lmgr_global_mutex);
556 foreach_dlist(item, global_mgr) {
560 lmgr_v(&lmgr_global_mutex);
563 void cln_hdl(void *a)
565 lmgr_cleanup_thread();
568 void *check_deadlock(void *)
572 pthread_cleanup_push(cln_hdl, NULL);
574 while (!bmicrosleep(30, 0)) {
575 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old);
576 if (lmgr_detect_deadlock()) {
580 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old);
581 pthread_testcancel();
583 Dmsg0(100, "Exit check_deadlock.\n");
584 pthread_cleanup_pop(1);
588 /* This object is used when LMGR is not initialized */
589 static lmgr_dummy_thread_t dummy_lmgr;
592 * Retrieve the lmgr_thread_t object from the stack
594 inline lmgr_thread_t *lmgr_get_thread_info()
596 if (lmgr_is_active()) {
597 return (lmgr_thread_t *)pthread_getspecific(lmgr_key);
604 * launch once for all threads
606 void create_lmgr_key()
608 int status = pthread_key_create(&lmgr_key, NULL);
611 Pmsg1(000, _("pthread key create failed: ERR=%s\n"),
612 be.bstrerror(status));
616 lmgr_thread_t *n=NULL;
617 global_mgr = New(dlist(n, &n->link));
619 if (use_undertaker) {
620 status = pthread_create(&undertaker, NULL, check_deadlock, NULL);
623 Pmsg1(000, _("pthread_create failed: ERR=%s\n"),
624 be.bstrerror(status));
631 * Each thread have to call this function to put a lmgr_thread_t object
632 * in the stack and be able to call mutex_lock/unlock
634 void lmgr_init_thread()
636 int status = pthread_once(&key_lmgr_once, create_lmgr_key);
639 Pmsg1(000, _("pthread key create failed: ERR=%s\n"),
640 be.bstrerror(status));
643 lmgr_thread_t *l = New(lmgr_thread_t());
644 pthread_setspecific(lmgr_key, l);
645 lmgr_register_thread(l);
649 * Call this function at the end of the thread
651 void lmgr_cleanup_thread()
653 if (!lmgr_is_active()) {
656 lmgr_thread_t *self = lmgr_get_thread_info();
657 lmgr_unregister_thread(self);
662 * This function should be call at the end of the main thread
663 * Some thread like the watchdog are already present, so the global_mgr
664 * list is never empty. Should carefully clear the memory.
666 void lmgr_cleanup_main()
673 if (use_undertaker) {
674 pthread_cancel(undertaker);
676 lmgr_cleanup_thread();
677 lmgr_p(&lmgr_global_mutex);
683 lmgr_v(&lmgr_global_mutex);
687 * Set the priority of the lmgr mutex object
689 void bthread_mutex_set_priority(bthread_mutex_t *m, int prio)
691 #ifdef USE_LOCKMGR_PRIORITY
697 * Replacement for pthread_mutex_init()
699 int pthread_mutex_init(bthread_mutex_t *m, const pthread_mutexattr_t *attr)
702 return pthread_mutex_init(&m->mutex, attr);
706 * Replacement for pthread_mutex_destroy()
708 int pthread_mutex_destroy(bthread_mutex_t *m)
710 return pthread_mutex_destroy(&m->mutex);
714 * Replacement for pthread_mutex_lock()
717 int bthread_mutex_lock_p(bthread_mutex_t *m, const char *file, int line)
719 lmgr_thread_t *self = lmgr_get_thread_info();
720 self->pre_P(m, m->priority, file, line);
727 * Replacement for pthread_mutex_unlock()
730 int bthread_mutex_unlock_p(bthread_mutex_t *m, const char *file, int line)
732 lmgr_thread_t *self = lmgr_get_thread_info();
733 self->do_V(m, file, line);
739 * Replacement for pthread_mutex_lock() but with real pthread_mutex_t
742 int bthread_mutex_lock_p(pthread_mutex_t *m, const char *file, int line)
744 lmgr_thread_t *self = lmgr_get_thread_info();
745 self->pre_P(m, 0, file, line);
752 * Replacement for pthread_mutex_unlock() but with real pthread_mutex_t
755 int bthread_mutex_unlock_p(pthread_mutex_t *m, const char *file, int line)
757 lmgr_thread_t *self = lmgr_get_thread_info();
758 self->do_V(m, file, line);
766 int bthread_cond_wait_p(pthread_cond_t *cond,
768 const char *file, int line)
771 lmgr_thread_t *self = lmgr_get_thread_info();
772 self->do_V(m, file, line);
773 ret = pthread_cond_wait(cond, m);
774 self->pre_P(m, 0, file, line);
781 int bthread_cond_timedwait_p(pthread_cond_t *cond,
783 const struct timespec * abstime,
784 const char *file, int line)
787 lmgr_thread_t *self = lmgr_get_thread_info();
788 self->do_V(m, file, line);
789 ret = pthread_cond_timedwait(cond, m, abstime);
790 self->pre_P(m, 0, file, line);
797 int bthread_cond_wait_p(pthread_cond_t *cond,
799 const char *file, int line)
802 lmgr_thread_t *self = lmgr_get_thread_info();
803 self->do_V(m, file, line);
804 ret = pthread_cond_wait(cond, &m->mutex);
805 self->pre_P(m, m->priority, file, line);
812 int bthread_cond_timedwait_p(pthread_cond_t *cond,
814 const struct timespec * abstime,
815 const char *file, int line)
818 lmgr_thread_t *self = lmgr_get_thread_info();
819 self->do_V(m, file, line);
820 ret = pthread_cond_timedwait(cond, &m->mutex, abstime);
821 self->pre_P(m, m->priority, file, line);
827 * Use this function when the caller handle the mutex directly
829 * lmgr_pre_lock(m, 10);
830 * pthread_mutex_lock(m);
833 void lmgr_pre_lock(void *m, int prio, const char *file, int line)
835 lmgr_thread_t *self = lmgr_get_thread_info();
836 self->pre_P(m, prio, file, line);
840 * Use this function when the caller handle the mutex directly
842 void lmgr_post_lock()
844 lmgr_thread_t *self = lmgr_get_thread_info();
849 * Do directly pre_P and post_P (used by trylock)
851 void lmgr_do_lock(void *m, int prio, const char *file, int line)
853 lmgr_thread_t *self = lmgr_get_thread_info();
854 self->pre_P(m, prio, file, line);
859 * Use this function when the caller handle the mutex directly
861 void lmgr_do_unlock(void *m)
863 lmgr_thread_t *self = lmgr_get_thread_info();
868 void *(*start_routine)(void*);
873 void *lmgr_thread_launcher(void *x)
877 pthread_cleanup_push(cln_hdl, NULL);
879 lmgr_thread_arg_t arg;
880 lmgr_thread_arg_t *a = (lmgr_thread_arg_t *)x;
881 arg.start_routine = a->start_routine;
885 ret = arg.start_routine(arg.arg);
886 pthread_cleanup_pop(1);
890 int lmgr_thread_create(pthread_t *thread,
891 const pthread_attr_t *attr,
892 void *(*start_routine)(void*), void *arg)
894 /* lmgr should be active (lmgr_init_thread() call in main()) */
895 ASSERT(lmgr_is_active());
896 /* Will be freed by the child */
897 lmgr_thread_arg_t *a = (lmgr_thread_arg_t*) malloc(sizeof(lmgr_thread_arg_t));
898 a->start_routine = start_routine;
900 return pthread_create(thread, attr, lmgr_thread_launcher, a);
903 #else /* _USE_LOCKMGR */
907 * Use this function is used only after a fatal signal
908 * We don't use locking to display information
910 void dbg_print_lock(FILE *fp)
912 Pmsg0(000, "lockmgr disabled\n");
915 #endif /* _USE_LOCKMGR */
920 #define BTHREAD_MUTEX_NO_PRIORITY {PTHREAD_MUTEX_INITIALIZER, 0}
921 #define BTHREAD_MUTEX_PRIORITY(p) {PTHREAD_MUTEX_INITIALIZER, p}
924 #define P(x) bthread_mutex_lock_p(&(x), __FILE__, __LINE__)
925 #define V(x) bthread_mutex_unlock_p(&(x), __FILE__, __LINE__)
926 #define pthread_create(a, b, c, d) lmgr_thread_create(a,b,c,d)
928 bthread_mutex_t mutex1 = BTHREAD_MUTEX_NO_PRIORITY;
929 bthread_mutex_t mutex2 = BTHREAD_MUTEX_NO_PRIORITY;
930 bthread_mutex_t mutex3 = BTHREAD_MUTEX_NO_PRIORITY;
931 bthread_mutex_t mutex4 = BTHREAD_MUTEX_NO_PRIORITY;
932 bthread_mutex_t mutex5 = BTHREAD_MUTEX_NO_PRIORITY;
933 bthread_mutex_t mutex6 = BTHREAD_MUTEX_NO_PRIORITY;
934 bthread_mutex_t mutex_p1 = BTHREAD_MUTEX_PRIORITY(1);
935 bthread_mutex_t mutex_p2 = BTHREAD_MUTEX_PRIORITY(2);
936 bthread_mutex_t mutex_p3 = BTHREAD_MUTEX_PRIORITY(3);
937 static const char *my_prog;
939 void *self_lock(void *temp)
948 void *nolock(void *temp)
956 void *locker(void *temp)
958 bthread_mutex_t *m = (bthread_mutex_t*) temp;
964 void *rwlocker(void *temp)
966 brwlock_t *m = (brwlock_t*) temp;
975 void *mix_rwl_mutex(void *temp)
977 brwlock_t *m = (brwlock_t*) temp;
986 void *th2(void *temp)
1001 void *th1(void *temp)
1018 void *thx(void *temp)
1020 int s= 1 + (int) (500.0 * (rand() / (RAND_MAX + 1.0))) + 200;
1031 void *th3(void *a) {
1033 fprintf(stderr, "undertaker sleep()\n");
1036 if (lmgr_detect_deadlock()) {
1044 void *th_prio(void *a) {
1046 bstrncpy(buf, my_prog, sizeof(buf));
1047 bstrncat(buf, " priority", sizeof(buf));
1048 int ret = system(buf);
1054 void _ok(const char *file, int l, const char *op, int value, const char *label)
1059 printf("ERR %.30s %s:%i on %s\n", label, file, l, op);
1061 printf("OK %.30s\n", label);
1065 #define ok(x, label) _ok(__FILE__, __LINE__, #x, (x), label)
1067 void _nok(const char *file, int l, const char *op, int value, const char *label)
1072 printf("ERR %.30s %s:%i on !%s\n", label, file, l, op);
1074 printf("OK %.30s\n", label);
1078 #define nok(x, label) _nok(__FILE__, __LINE__, #x, (x), label)
1082 printf("Result %i/%i OK\n", nb - err, nb);
1088 * - Must detect multiple lock
1089 * - lock/unlock in wrong order
1090 * - deadlock with 2 or 3 threads
1092 int main(int argc, char **argv)
1095 lmgr_thread_t *self;
1096 pthread_t id1, id2, id3, tab[200];
1097 bthread_mutex_t bmutex1;
1098 pthread_mutex_t pmutex2;
1101 use_undertaker = false;
1103 self = lmgr_get_thread_info();
1105 if (argc == 2) { /* do priority check */
1106 P(mutex_p2); /* not permited */
1108 V(mutex_p1); /* never goes here */
1113 pthread_mutex_init(&bmutex1, NULL);
1114 bthread_mutex_set_priority(&bmutex1, 10);
1116 pthread_mutex_init(&pmutex2, NULL);
1118 ok(self->max_priority == 10, "Check self max_priority");
1120 ok(bmutex1.priority == 10, "Check bmutex_set_priority()");
1123 ok(self->max_priority == 0, "Check self max_priority");
1125 pthread_create(&id1, NULL, self_lock, NULL);
1127 ok(lmgr_detect_deadlock(), "Check self deadlock");
1128 lmgr_v(&mutex1.mutex); /* a bit dirty */
1129 pthread_join(id1, NULL);
1132 pthread_create(&id1, NULL, nolock, NULL);
1134 nok(lmgr_detect_deadlock(), "Check for nolock");
1135 pthread_join(id1, NULL);
1138 pthread_create(&id1, NULL, locker, &mutex1);
1139 pthread_create(&id2, NULL, locker, &mutex1);
1140 pthread_create(&id3, NULL, locker, &mutex1);
1142 nok(lmgr_detect_deadlock(), "Check for multiple lock");
1144 pthread_join(id1, NULL);
1145 pthread_join(id2, NULL);
1146 pthread_join(id3, NULL);
1153 pthread_create(&id1, NULL, rwlocker, &wr);
1154 pthread_create(&id2, NULL, rwlocker, &wr);
1155 pthread_create(&id3, NULL, rwlocker, &wr);
1156 nok(lmgr_detect_deadlock(), "Check for multiple rwlock");
1157 rwl_writeunlock(&wr);
1158 nok(lmgr_detect_deadlock(), "Check for simple rwlock");
1159 rwl_writeunlock(&wr);
1160 nok(lmgr_detect_deadlock(), "Check for multiple rwlock");
1162 pthread_join(id1, NULL);
1163 pthread_join(id2, NULL);
1164 pthread_join(id3, NULL);
1168 pthread_create(&id1, NULL, mix_rwl_mutex, &wr);
1169 nok(lmgr_detect_deadlock(), "Check for mix rwlock/mutex");
1171 nok(lmgr_detect_deadlock(), "Check for mix rwlock/mutex");
1172 rwl_writeunlock(&wr);
1173 nok(lmgr_detect_deadlock(), "Check for mix rwlock/mutex");
1174 pthread_join(id1, NULL);
1181 nok(lmgr_detect_deadlock(), "Check for wrong order");
1183 for(int j=0; j<200; j++) {
1184 pthread_create(&tab[j], NULL, thx, NULL);
1186 for(int j=0; j<200; j++) {
1187 pthread_join(tab[j], NULL);
1188 if (j%3) { lmgr_detect_deadlock();}
1190 nok(lmgr_detect_deadlock(), "Check 200 lockers");
1199 pthread_create(&id1, NULL, th1, NULL);
1201 pthread_create(&id2, NULL, th2, NULL);
1203 ok(lmgr_detect_deadlock(), "Check for deadlock");
1205 pthread_create(&id3, NULL, th_prio, NULL);
1206 pthread_join(id3, &ret);
1207 ok(ret != 0, "Check for priority segfault");
1210 ok(self->max_priority == 1, "Check max_priority 1/4");
1212 ok(self->max_priority == 2, "Check max_priority 2/4");
1214 ok(self->max_priority == 3, "Check max_priority 3/4");
1216 ok(self->max_priority == 3, "Check max_priority 4/4");
1218 ok(self->max_priority == 3, "Check max_priority 1/5");
1220 ok(self->max_priority == 2, "Check max_priority 4/5");
1222 ok(self->max_priority == 1, "Check max_priority 4/5");
1224 ok(self->max_priority == 0, "Check max_priority 5/5");
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 == 3, "Check max_priority mixed");
1237 ok(self->max_priority == 0, "Check max_priority mixed");
1239 ok(self->max_priority == 0, "Check max_priority mixed");
1248 // pthread_create(&id3, NULL, th3, NULL);
1250 // pthread_join(id1, NULL);
1251 // pthread_join(id2, NULL);
1252 lmgr_cleanup_main();
1253 sm_check(__FILE__, __LINE__, false);