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);
826 /* Test if this mutex is locked by the current thread
829 * 1 - locked by the current thread
830 * 2 - locked by an other thread
832 int lmgr_mutex_is_locked(void *m)
834 lmgr_thread_t *self = lmgr_get_thread_info();
836 for(int i=0; i <= self->current; i++) {
837 if (self->lock_list[i].lock == m) {
838 return 1; /* locked by us */
842 return 0; /* not locked by us */
846 * Use this function when the caller handle the mutex directly
848 * lmgr_pre_lock(m, 10);
849 * pthread_mutex_lock(m);
852 void lmgr_pre_lock(void *m, int prio, const char *file, int line)
854 lmgr_thread_t *self = lmgr_get_thread_info();
855 self->pre_P(m, prio, file, line);
859 * Use this function when the caller handle the mutex directly
861 void lmgr_post_lock()
863 lmgr_thread_t *self = lmgr_get_thread_info();
868 * Do directly pre_P and post_P (used by trylock)
870 void lmgr_do_lock(void *m, int prio, const char *file, int line)
872 lmgr_thread_t *self = lmgr_get_thread_info();
873 self->pre_P(m, prio, file, line);
878 * Use this function when the caller handle the mutex directly
880 void lmgr_do_unlock(void *m)
882 lmgr_thread_t *self = lmgr_get_thread_info();
887 void *(*start_routine)(void*);
892 void *lmgr_thread_launcher(void *x)
896 pthread_cleanup_push(cln_hdl, NULL);
898 lmgr_thread_arg_t arg;
899 lmgr_thread_arg_t *a = (lmgr_thread_arg_t *)x;
900 arg.start_routine = a->start_routine;
904 ret = arg.start_routine(arg.arg);
905 pthread_cleanup_pop(1);
909 int lmgr_thread_create(pthread_t *thread,
910 const pthread_attr_t *attr,
911 void *(*start_routine)(void*), void *arg)
913 /* lmgr should be active (lmgr_init_thread() call in main()) */
914 ASSERT(lmgr_is_active());
915 /* Will be freed by the child */
916 lmgr_thread_arg_t *a = (lmgr_thread_arg_t*) malloc(sizeof(lmgr_thread_arg_t));
917 a->start_routine = start_routine;
919 return pthread_create(thread, attr, lmgr_thread_launcher, a);
922 #else /* _USE_LOCKMGR */
926 * Use this function is used only after a fatal signal
927 * We don't use locking to display information
929 void dbg_print_lock(FILE *fp)
931 Pmsg0(000, "lockmgr disabled\n");
934 #endif /* _USE_LOCKMGR */
939 #define BTHREAD_MUTEX_NO_PRIORITY {PTHREAD_MUTEX_INITIALIZER, 0}
940 #define BTHREAD_MUTEX_PRIORITY(p) {PTHREAD_MUTEX_INITIALIZER, p}
943 #define P(x) bthread_mutex_lock_p(&(x), __FILE__, __LINE__)
944 #define V(x) bthread_mutex_unlock_p(&(x), __FILE__, __LINE__)
945 #define pthread_create(a, b, c, d) lmgr_thread_create(a,b,c,d)
947 bthread_mutex_t mutex1 = BTHREAD_MUTEX_NO_PRIORITY;
948 bthread_mutex_t mutex2 = BTHREAD_MUTEX_NO_PRIORITY;
949 bthread_mutex_t mutex3 = BTHREAD_MUTEX_NO_PRIORITY;
950 bthread_mutex_t mutex4 = BTHREAD_MUTEX_NO_PRIORITY;
951 bthread_mutex_t mutex5 = BTHREAD_MUTEX_NO_PRIORITY;
952 bthread_mutex_t mutex6 = BTHREAD_MUTEX_NO_PRIORITY;
953 bthread_mutex_t mutex_p1 = BTHREAD_MUTEX_PRIORITY(1);
954 bthread_mutex_t mutex_p2 = BTHREAD_MUTEX_PRIORITY(2);
955 bthread_mutex_t mutex_p3 = BTHREAD_MUTEX_PRIORITY(3);
956 static const char *my_prog;
958 void *self_lock(void *temp)
967 void *nolock(void *temp)
975 void *locker(void *temp)
977 bthread_mutex_t *m = (bthread_mutex_t*) temp;
983 void *rwlocker(void *temp)
985 brwlock_t *m = (brwlock_t*) temp;
994 void *mix_rwl_mutex(void *temp)
996 brwlock_t *m = (brwlock_t*) temp;
1005 void *th2(void *temp)
1020 void *th1(void *temp)
1037 void *thx(void *temp)
1039 int s= 1 + (int) (500.0 * (rand() / (RAND_MAX + 1.0))) + 200;
1050 void *th3(void *a) {
1052 fprintf(stderr, "undertaker sleep()\n");
1055 if (lmgr_detect_deadlock()) {
1063 void *th_prio(void *a) {
1065 bstrncpy(buf, my_prog, sizeof(buf));
1066 bstrncat(buf, " priority", sizeof(buf));
1067 int ret = system(buf);
1073 void _ok(const char *file, int l, const char *op, int value, const char *label)
1078 printf("ERR %.30s %s:%i on %s\n", label, file, l, op);
1080 printf("OK %.30s\n", label);
1084 #define ok(x, label) _ok(__FILE__, __LINE__, #x, (x), label)
1086 void _nok(const char *file, int l, const char *op, int value, const char *label)
1091 printf("ERR %.30s %s:%i on !%s\n", label, file, l, op);
1093 printf("OK %.30s\n", label);
1097 #define nok(x, label) _nok(__FILE__, __LINE__, #x, (x), label)
1101 printf("Result %i/%i OK\n", nb - err, nb);
1107 * - Must detect multiple lock
1108 * - lock/unlock in wrong order
1109 * - deadlock with 2 or 3 threads
1111 int main(int argc, char **argv)
1114 lmgr_thread_t *self;
1115 pthread_t id1, id2, id3, tab[200];
1116 bthread_mutex_t bmutex1;
1117 pthread_mutex_t pmutex2;
1120 use_undertaker = false;
1122 self = lmgr_get_thread_info();
1124 if (argc == 2) { /* do priority check */
1125 P(mutex_p2); /* not permited */
1127 V(mutex_p1); /* never goes here */
1132 pthread_mutex_init(&bmutex1, NULL);
1133 bthread_mutex_set_priority(&bmutex1, 10);
1135 pthread_mutex_init(&pmutex2, NULL);
1137 ok(self->max_priority == 10, "Check self max_priority");
1139 ok(bmutex1.priority == 10, "Check bmutex_set_priority()");
1142 ok(self->max_priority == 0, "Check self max_priority");
1144 pthread_create(&id1, NULL, self_lock, NULL);
1146 ok(lmgr_detect_deadlock(), "Check self deadlock");
1147 lmgr_v(&mutex1.mutex); /* a bit dirty */
1148 pthread_join(id1, NULL);
1151 pthread_create(&id1, NULL, nolock, NULL);
1153 nok(lmgr_detect_deadlock(), "Check for nolock");
1154 pthread_join(id1, NULL);
1157 pthread_create(&id1, NULL, locker, &mutex1);
1158 pthread_create(&id2, NULL, locker, &mutex1);
1159 pthread_create(&id3, NULL, locker, &mutex1);
1161 nok(lmgr_detect_deadlock(), "Check for multiple lock");
1163 pthread_join(id1, NULL);
1164 pthread_join(id2, NULL);
1165 pthread_join(id3, NULL);
1172 pthread_create(&id1, NULL, rwlocker, &wr);
1173 pthread_create(&id2, NULL, rwlocker, &wr);
1174 pthread_create(&id3, NULL, rwlocker, &wr);
1175 nok(lmgr_detect_deadlock(), "Check for multiple rwlock");
1176 rwl_writeunlock(&wr);
1177 nok(lmgr_detect_deadlock(), "Check for simple rwlock");
1178 rwl_writeunlock(&wr);
1179 nok(lmgr_detect_deadlock(), "Check for multiple rwlock");
1181 pthread_join(id1, NULL);
1182 pthread_join(id2, NULL);
1183 pthread_join(id3, NULL);
1187 pthread_create(&id1, NULL, mix_rwl_mutex, &wr);
1188 nok(lmgr_detect_deadlock(), "Check for mix rwlock/mutex");
1190 nok(lmgr_detect_deadlock(), "Check for mix rwlock/mutex");
1191 rwl_writeunlock(&wr);
1192 nok(lmgr_detect_deadlock(), "Check for mix rwlock/mutex");
1193 pthread_join(id1, NULL);
1200 nok(lmgr_detect_deadlock(), "Check for wrong order");
1202 for(int j=0; j<200; j++) {
1203 pthread_create(&tab[j], NULL, thx, NULL);
1205 for(int j=0; j<200; j++) {
1206 pthread_join(tab[j], NULL);
1207 if (j%3) { lmgr_detect_deadlock();}
1209 nok(lmgr_detect_deadlock(), "Check 200 lockers");
1214 ok(lmgr_mutex_is_locked(&mutex6) == 1, "Check if mutex is locked");
1216 ok(lmgr_mutex_is_locked(&mutex6) == 0, "Check if mutex is locked");
1220 pthread_create(&id1, NULL, th1, NULL);
1222 pthread_create(&id2, NULL, th2, NULL);
1224 ok(lmgr_detect_deadlock(), "Check for deadlock");
1226 pthread_create(&id3, NULL, th_prio, NULL);
1227 pthread_join(id3, &ret);
1228 ok(ret != 0, "Check for priority segfault");
1231 ok(self->max_priority == 1, "Check max_priority 1/4");
1233 ok(self->max_priority == 2, "Check max_priority 2/4");
1235 ok(self->max_priority == 3, "Check max_priority 3/4");
1237 ok(self->max_priority == 3, "Check max_priority 4/4");
1239 ok(self->max_priority == 3, "Check max_priority 1/5");
1241 ok(self->max_priority == 2, "Check max_priority 4/5");
1243 ok(self->max_priority == 1, "Check max_priority 4/5");
1245 ok(self->max_priority == 0, "Check max_priority 5/5");
1252 ok(self->max_priority == 3, "Check max_priority mixed");
1254 ok(self->max_priority == 3, "Check max_priority mixed");
1256 ok(self->max_priority == 3, "Check max_priority mixed");
1258 ok(self->max_priority == 0, "Check max_priority mixed");
1260 ok(self->max_priority == 0, "Check max_priority mixed");
1269 // pthread_create(&id3, NULL, th3, NULL);
1271 // pthread_join(id1, NULL);
1272 // pthread_join(id2, NULL);
1273 lmgr_cleanup_main();
1274 sm_check(__FILE__, __LINE__, false);