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.
29 #define _LOCKMGR_COMPLIANT
33 #define ASSERT(x) if (!(x)) { \
35 Pmsg3(000, _("Failed ASSERT: %s\n"), __FILE__, __LINE__, #x); \
38 #define ASSERT_p(x,f,l) if (!(x)) { \
40 Pmsg3(000, _("from %s:%i Failed ASSERT: %s\n"), f, l, #x); \
45 http://www.cs.berkeley.edu/~kamil/teaching/sp03/041403.pdf
47 This lock manager will replace some pthread calls. It can be
48 enabled with _USE_LOCKMGR
50 Some part of the code can't use this manager, for example the
51 rwlock object or the smartalloc lib. To disable LMGR, just add
52 _LOCKMGR_COMPLIANT before the inclusion of "bacula.h"
55 g++ -g -c lockmgr.c -I.. -I../lib -D_USE_LOCKMGR -D_TEST_IT
56 g++ -o lockmgr lockmgr.o -lbac -L../lib/.libs -lssl -lpthread
62 * pthread_mutex_lock for memory allocator and other
63 * parts that are _LOCKMGR_COMPLIANT
65 void lmgr_p(pthread_mutex_t *m)
68 if ((errstat=pthread_mutex_lock(m))) {
70 e_msg(__FILE__, __LINE__, M_ABORT, 0, _("Mutex lock failure. ERR=%s\n"),
71 be.bstrerror(errstat));
75 void lmgr_v(pthread_mutex_t *m)
78 if ((errstat=pthread_mutex_unlock(m))) {
80 e_msg(__FILE__, __LINE__, M_ABORT, 0, _("Mutex unlock failure. ERR=%s\n"),
81 be.bstrerror(errstat));
89 LMGR_WHITE, /* never seen */
90 LMGR_BLACK, /* no loop */
91 LMGR_GREY, /* seen before */
95 * Node used by the Lock Manager
96 * If the lock is GRANTED, we have mutex -> proc, else it's a proc -> mutex
99 * Note, each mutex can be GRANTED once, and each proc can have only one WANTED
102 class lmgr_node_t: public SMARTALLOC
115 lmgr_node_t(void *n, void *c) {
119 void init(void *n, void *c) {
125 void mark_as_seen(lmgr_color_t c) {
129 ~lmgr_node_t() {printf("delete node\n");}
133 LMGR_LOCK_EMPTY = 'E', /* unused */
134 LMGR_LOCK_WANTED = 'W', /* before mutex_lock */
135 LMGR_LOCK_GRANTED = 'G' /* after mutex_lock */
139 * Object associated with each mutex per thread
141 class lmgr_lock_t: public SMARTALLOC
155 state = LMGR_LOCK_EMPTY;
156 priority = max_priority = 0;
159 lmgr_lock_t(void *l) {
161 state = LMGR_LOCK_WANTED;
165 state = LMGR_LOCK_GRANTED;
173 * Get the child list, ret must be already allocated
175 static void search_all_node(dlist *g, lmgr_node_t *v, alist *ret)
178 foreach_dlist(n, g) {
179 if (v->child == n->node) {
185 static bool visite(dlist *g, lmgr_node_t *v)
189 v->mark_as_seen(LMGR_GREY);
191 alist *d = New(alist(5, false)); /* use alist because own=false */
192 search_all_node(g, v, d);
194 //foreach_alist(n, d) {
195 // printf("node n=%p c=%p s=%c\n", n->node, n->child, n->seen);
198 foreach_alist(n, d) {
199 if (n->seen == LMGR_GREY) { /* already seen this node */
202 } else if (n->seen == LMGR_WHITE) {
209 v->mark_as_seen(LMGR_BLACK); /* no loop detected, node is clean */
215 static bool contains_cycle(dlist *g)
218 foreach_dlist(n, g) {
219 if (n->seen == LMGR_WHITE) {
228 /****************************************************************/
230 class lmgr_thread_t: public SMARTALLOC
234 pthread_mutex_t mutex;
236 lmgr_lock_t lock_list[LMGR_MAX_LOCK];
243 if ((status = pthread_mutex_init(&mutex, NULL)) != 0) {
245 Pmsg1(000, _("pthread key create failed: ERR=%s\n"),
246 be.bstrerror(status));
249 thread_id = pthread_self();
255 void _dump(FILE *fp) {
256 fprintf(fp, "threadid=%p max=%i current=%i\n",
257 (void *)thread_id, max, current);
258 for(int i=0; i<=current; i++) {
259 fprintf(fp, " lock=%p state=%s %s:%i\n",
261 (lock_list[i].state=='W')?"Wanted ":"Granted",
262 lock_list[i].file, lock_list[i].line);
266 void dump(FILE *fp) {
275 * Call before a lock operation (mark mutex as WANTED)
277 virtual void pre_P(void *m, int priority,
278 const char *f="*unknown*", int l=0) {
279 ASSERT_p(current < LMGR_MAX_LOCK, f, l);
280 ASSERT_p(current >= -1, f, l);
281 ASSERT_p(!priority || priority >= max_priority, f, l);
285 lock_list[current].lock = m;
286 lock_list[current].state = LMGR_LOCK_WANTED;
287 lock_list[current].file = f;
288 lock_list[current].line = l;
289 lock_list[current].priority = priority;
290 lock_list[current].max_priority = MAX(priority, max_priority);
291 max = MAX(current, max);
292 max_priority = MAX(priority, max_priority);
298 * Call after the lock operation (mark mutex as GRANTED)
300 virtual void post_P() {
301 ASSERT(current >= 0);
302 ASSERT(lock_list[current].state == LMGR_LOCK_WANTED);
303 lock_list[current].state = LMGR_LOCK_GRANTED;
306 /* Using this function is some sort of bug */
307 void shift_list(int i) {
308 for(int j=i+1; j<=current; j++) {
309 lock_list[i] = lock_list[j];
312 lock_list[current].lock = NULL;
313 lock_list[current].state = LMGR_LOCK_EMPTY;
315 /* rebuild the priority list */
317 for(int j=0; j< current; j++) {
318 max_priority = MAX(lock_list[j].priority, max_priority);
319 lock_list[j].max_priority = max_priority;
324 * Remove the mutex from the list
326 virtual void do_V(void *m, const char *f="*unknown*", int l=0) {
327 ASSERT_p(current >= 0, f, l);
330 if (lock_list[current].lock == m) {
331 lock_list[current].lock = NULL;
332 lock_list[current].state = LMGR_LOCK_EMPTY;
336 Pmsg3(0, "ERROR: wrong P/V order search lock=%p %s:%i\n", m, f, l);
337 Pmsg4(000, "ERROR: wrong P/V order pos=%i lock=%p %s:%i\n",
338 current, lock_list[current].lock, lock_list[current].file,
339 lock_list[current].line);
340 for (int i=current-1; i >= 0; i--) { /* already seen current */
341 Pmsg4(000, "ERROR: wrong P/V order pos=%i lock=%p %s:%i\n",
342 i, lock_list[i].lock, lock_list[i].file, lock_list[i].line);
343 if (lock_list[i].lock == m) {
344 Pmsg3(000, "ERROR: FOUND P pos=%i %s:%i\n", i, f, l);
351 /* reset max_priority to the last one */
353 max_priority = lock_list[current].max_priority;
361 virtual ~lmgr_thread_t() {destroy();}
364 pthread_mutex_destroy(&mutex);
368 class lmgr_dummy_thread_t: public lmgr_thread_t
370 void do_V(void *m, const char *file, int l) {}
372 void pre_P(void *m, int priority, const char *file, int l) {}
376 * LMGR - Lock Manager
382 pthread_once_t key_lmgr_once = PTHREAD_ONCE_INIT;
383 static pthread_key_t lmgr_key; /* used to get lgmr_thread_t object */
385 static dlist *global_mgr = NULL; /* used to store all lgmr_thread_t objects */
386 static pthread_mutex_t lmgr_global_mutex = PTHREAD_MUTEX_INITIALIZER;
387 static pthread_t undertaker;
388 static bool use_undertaker=true;
390 #define lmgr_is_active() (global_mgr != NULL)
393 * Add a new lmgr_thread_t object to the global list
395 void lmgr_register_thread(lmgr_thread_t *item)
397 lmgr_p(&lmgr_global_mutex);
399 global_mgr->prepend(item);
401 lmgr_v(&lmgr_global_mutex);
405 * Call this function to cleanup specific lock thread data
407 void lmgr_unregister_thread(lmgr_thread_t *item)
409 if (!lmgr_is_active()) {
412 lmgr_p(&lmgr_global_mutex);
414 global_mgr->remove(item);
416 lmgr_v(&lmgr_global_mutex);
420 * Search for a deadlock when it's secure to walk across
421 * locks list. (after lmgr_detect_deadlock or a fatal signal)
423 bool lmgr_detect_deadlock_unlocked()
426 lmgr_node_t *node=NULL;
429 dlist *g = New(dlist(node, &node->link));
431 /* First, get a list of all node */
432 foreach_dlist(item, global_mgr) {
433 for(int i=0; i<=item->current; i++) {
435 lock = &item->lock_list[i];
436 /* Depending if the lock is granted or not, it's a child or a root
437 * Granted: Mutex -> Thread
438 * Wanted: Thread -> Mutex
440 * Note: a Mutex can be locked only once, a thread can request only
444 if (lock->state == LMGR_LOCK_GRANTED) {
445 node = New(lmgr_node_t((void*)lock->lock, (void*)item->thread_id));
446 } else if (lock->state == LMGR_LOCK_WANTED) {
447 node = New(lmgr_node_t((void*)item->thread_id, (void*)lock->lock));
455 //foreach_dlist(node, g) {
456 // printf("g n=%p c=%p\n", node->node, node->child);
459 ret = contains_cycle(g);
461 printf("Found a deadlock !!!!\n");
469 * Search for a deadlock in during the runtime
470 * It will lock all thread specific lock manager, nothing
471 * can be locked during this check.
473 bool lmgr_detect_deadlock()
476 if (!lmgr_is_active()) {
480 lmgr_p(&lmgr_global_mutex);
483 foreach_dlist(item, global_mgr) {
484 lmgr_p(&item->mutex);
487 ret = lmgr_detect_deadlock_unlocked();
489 foreach_dlist(item, global_mgr) {
490 lmgr_v(&item->mutex);
493 lmgr_v(&lmgr_global_mutex);
500 * Use this function is used only after a fatal signal
501 * We don't use locking to display the information
503 void dbg_print_lock(FILE *fp)
505 fprintf(fp, "Attempt to dump locks\n");
506 if (!lmgr_is_active()) {
510 foreach_dlist(item, global_mgr) {
516 * Dump each lmgr_thread_t object
520 lmgr_p(&lmgr_global_mutex);
523 foreach_dlist(item, global_mgr) {
527 lmgr_v(&lmgr_global_mutex);
530 void cln_hdl(void *a)
532 lmgr_cleanup_thread();
535 void *check_deadlock(void *)
539 pthread_cleanup_push(cln_hdl, NULL);
541 while (!bmicrosleep(30, 0)) {
542 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old);
543 if (lmgr_detect_deadlock()) {
547 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old);
548 pthread_testcancel();
550 Pmsg0(000, "Undertaker is leaving...\n");
551 pthread_cleanup_pop(1);
555 /* This object is used when LMGR is not initialized */
556 static lmgr_dummy_thread_t dummy_lmgr;
559 * Retrieve the lmgr_thread_t object from the stack
561 inline lmgr_thread_t *lmgr_get_thread_info()
563 if (lmgr_is_active()) {
564 return (lmgr_thread_t *)pthread_getspecific(lmgr_key);
571 * launch once for all threads
573 void create_lmgr_key()
575 int status = pthread_key_create(&lmgr_key, NULL);
578 Pmsg1(000, _("pthread key create failed: ERR=%s\n"),
579 be.bstrerror(status));
583 lmgr_thread_t *n=NULL;
584 global_mgr = New(dlist(n, &n->link));
586 if (use_undertaker) {
587 status = pthread_create(&undertaker, NULL, check_deadlock, NULL);
590 Pmsg1(000, _("pthread_create failed: ERR=%s\n"),
591 be.bstrerror(status));
598 * Each thread have to call this function to put a lmgr_thread_t object
599 * in the stack and be able to call mutex_lock/unlock
601 void lmgr_init_thread()
603 int status = pthread_once(&key_lmgr_once, create_lmgr_key);
606 Pmsg1(000, _("pthread key create failed: ERR=%s\n"),
607 be.bstrerror(status));
610 lmgr_thread_t *l = New(lmgr_thread_t());
611 pthread_setspecific(lmgr_key, l);
612 lmgr_register_thread(l);
616 * Call this function at the end of the thread
618 void lmgr_cleanup_thread()
620 if (!lmgr_is_active()) {
623 lmgr_thread_t *self = lmgr_get_thread_info();
624 lmgr_unregister_thread(self);
629 * This function should be call at the end of the main thread
630 * Some thread like the watchdog are already present, so the global_mgr
631 * list is never empty. Should carefully clear the memory.
633 void lmgr_cleanup_main()
640 if (use_undertaker) {
641 pthread_cancel(undertaker);
643 lmgr_cleanup_thread();
644 lmgr_p(&lmgr_global_mutex);
650 lmgr_v(&lmgr_global_mutex);
654 * Set the priority of the lmgr mutex object
656 void bthread_mutex_set_priority(bthread_mutex_t *m, int prio)
662 * Replacement for pthread_mutex_init()
664 int bthread_mutex_init(bthread_mutex_t *m, const pthread_mutexattr_t *attr)
667 return pthread_mutex_init(&m->mutex, attr);
671 * Replacement for pthread_mutex_destroy()
673 int bthread_mutex_destroy(bthread_mutex_t *m)
675 return pthread_mutex_destroy(&m->mutex);
679 * Replacement for pthread_mutex_lock()
682 int bthread_mutex_lock_p(bthread_mutex_t *m, const char *file, int line)
684 lmgr_thread_t *self = lmgr_get_thread_info();
685 self->pre_P(m, m->priority, file, line);
692 * Replacement for pthread_mutex_unlock()
695 int bthread_mutex_unlock_p(bthread_mutex_t *m, const char *file, int line)
697 lmgr_thread_t *self = lmgr_get_thread_info();
698 self->do_V(m, file, line);
704 * Replacement for pthread_mutex_lock() but with real pthread_mutex_t
707 int bthread_mutex_lock_p(pthread_mutex_t *m, const char *file, int line)
709 lmgr_thread_t *self = lmgr_get_thread_info();
710 self->pre_P(m, 0, file, line);
717 * Replacement for pthread_mutex_unlock() but with real pthread_mutex_t
720 int bthread_mutex_unlock_p(pthread_mutex_t *m, const char *file, int line)
722 lmgr_thread_t *self = lmgr_get_thread_info();
723 self->do_V(m, file, line);
731 int bthread_cond_wait_p(pthread_cond_t *cond,
733 const char *file, int line)
736 lmgr_thread_t *self = lmgr_get_thread_info();
737 self->do_V(m, file, line);
738 ret = pthread_cond_wait(cond, m);
739 self->pre_P(m, 0, file, line);
746 int bthread_cond_timedwait_p(pthread_cond_t *cond,
748 const struct timespec * abstime,
749 const char *file, int line)
752 lmgr_thread_t *self = lmgr_get_thread_info();
753 self->do_V(m, file, line);
754 ret = pthread_cond_timedwait(cond, m, abstime);
755 self->pre_P(m, 0, file, line);
762 int bthread_cond_wait_p(pthread_cond_t *cond,
764 const char *file, int line)
767 lmgr_thread_t *self = lmgr_get_thread_info();
768 self->do_V(m, file, line);
769 ret = pthread_cond_wait(cond, &m->mutex);
770 self->pre_P(m, m->priority, file, line);
777 int bthread_cond_timedwait_p(pthread_cond_t *cond,
779 const struct timespec * abstime,
780 const char *file, int line)
783 lmgr_thread_t *self = lmgr_get_thread_info();
784 self->do_V(m, file, line);
785 ret = pthread_cond_timedwait(cond, &m->mutex, abstime);
786 self->pre_P(m, m->priority, file, line);
792 * Use this function when the caller handle the mutex directly
794 * lmgr_pre_lock(m, 10);
795 * pthread_mutex_lock(m);
798 void lmgr_pre_lock(void *m, int prio, const char *file, int line)
800 lmgr_thread_t *self = lmgr_get_thread_info();
801 self->pre_P(m, prio, file, line);
805 * Use this function when the caller handle the mutex directly
807 void lmgr_post_lock()
809 lmgr_thread_t *self = lmgr_get_thread_info();
814 * Do directly pre_P and post_P (used by trylock)
816 void lmgr_do_lock(void *m, int prio, const char *file, int line)
818 lmgr_thread_t *self = lmgr_get_thread_info();
819 self->pre_P(m, prio, file, line);
824 * Use this function when the caller handle the mutex directly
826 void lmgr_do_unlock(void *m)
828 lmgr_thread_t *self = lmgr_get_thread_info();
833 void *(*start_routine)(void*);
838 void *lmgr_thread_launcher(void *x)
842 pthread_cleanup_push(cln_hdl, NULL);
844 lmgr_thread_arg_t arg;
845 lmgr_thread_arg_t *a = (lmgr_thread_arg_t *)x;
846 arg.start_routine = a->start_routine;
850 ret = arg.start_routine(arg.arg);
851 pthread_cleanup_pop(1);
855 int lmgr_thread_create(pthread_t *thread,
856 const pthread_attr_t *attr,
857 void *(*start_routine)(void*), void *arg)
859 /* lmgr should be active (lmgr_init_thread() call in main()) */
860 ASSERT(lmgr_is_active());
861 /* Will be freed by the child */
862 lmgr_thread_arg_t *a = (lmgr_thread_arg_t*) malloc(sizeof(lmgr_thread_arg_t));
863 a->start_routine = start_routine;
865 return pthread_create(thread, attr, lmgr_thread_launcher, a);
868 #else /* _USE_LOCKMGR */
872 * Use this function is used only after a fatal signal
873 * We don't use locking to display information
875 void dbg_print_lock(FILE *fp)
877 Pmsg0(000, "lockmgr disabled\n");
880 #endif /* _USE_LOCKMGR */
885 #define BTHREAD_MUTEX_NO_PRIORITY {PTHREAD_MUTEX_INITIALIZER, 0}
886 #define BTHREAD_MUTEX_PRIORITY_1 {PTHREAD_MUTEX_INITIALIZER, 1}
887 #define BTHREAD_MUTEX_PRIORITY_2 {PTHREAD_MUTEX_INITIALIZER, 2}
888 #define BTHREAD_MUTEX_PRIORITY_3 {PTHREAD_MUTEX_INITIALIZER, 3}
889 #define BTHREAD_MUTEX_PRIORITY_4 {PTHREAD_MUTEX_INITIALIZER, 4}
892 #define P(x) bthread_mutex_lock_p(&(x), __FILE__, __LINE__)
893 #define V(x) bthread_mutex_unlock_p(&(x), __FILE__, __LINE__)
894 #define pthread_create(a, b, c, d) lmgr_thread_create(a,b,c,d)
896 bthread_mutex_t mutex1 = BTHREAD_MUTEX_NO_PRIORITY;
897 bthread_mutex_t mutex2 = BTHREAD_MUTEX_NO_PRIORITY;
898 bthread_mutex_t mutex3 = BTHREAD_MUTEX_NO_PRIORITY;
899 bthread_mutex_t mutex4 = BTHREAD_MUTEX_NO_PRIORITY;
900 bthread_mutex_t mutex5 = BTHREAD_MUTEX_NO_PRIORITY;
901 bthread_mutex_t mutex6 = BTHREAD_MUTEX_NO_PRIORITY;
902 bthread_mutex_t mutex_p1 = BTHREAD_MUTEX_PRIORITY_1;
903 bthread_mutex_t mutex_p2 = BTHREAD_MUTEX_PRIORITY_2;
904 bthread_mutex_t mutex_p3 = BTHREAD_MUTEX_PRIORITY_3;
905 static const char *my_prog;
907 void *self_lock(void *temp)
916 void *nolock(void *temp)
924 void *locker(void *temp)
926 bthread_mutex_t *m = (bthread_mutex_t*) temp;
932 void *rwlocker(void *temp)
934 brwlock_t *m = (brwlock_t*) temp;
943 void *mix_rwl_mutex(void *temp)
945 brwlock_t *m = (brwlock_t*) temp;
954 void *th2(void *temp)
969 void *th1(void *temp)
986 void *thx(void *temp)
988 int s= 1 + (int) (500.0 * (rand() / (RAND_MAX + 1.0))) + 200;
1001 fprintf(stderr, "undertaker sleep()\n");
1004 if (lmgr_detect_deadlock()) {
1012 void *th_prio(void *a) {
1014 bstrncpy(buf, my_prog, sizeof(buf));
1015 bstrncat(buf, " priority", sizeof(buf));
1016 int ret = system(buf);
1022 void _ok(const char *file, int l, const char *op, int value, const char *label)
1027 printf("ERR %.30s %s:%i on %s\n", label, file, l, op);
1029 printf("OK %.30s\n", label);
1033 #define ok(x, label) _ok(__FILE__, __LINE__, #x, (x), label)
1035 void _nok(const char *file, int l, const char *op, int value, const char *label)
1040 printf("ERR %.30s %s:%i on !%s\n", label, file, l, op);
1042 printf("OK %.30s\n", label);
1046 #define nok(x, label) _nok(__FILE__, __LINE__, #x, (x), label)
1050 printf("Result %i/%i OK\n", nb - err, nb);
1056 * - Must detect multiple lock
1057 * - lock/unlock in wrong order
1058 * - deadlock with 2 or 3 threads
1060 int main(int argc, char **argv)
1063 lmgr_thread_t *self;
1064 pthread_t id1, id2, id3, tab[200];
1067 use_undertaker = false;
1070 if (argc == 2) { /* do priority check */
1071 P(mutex_p2); /* not permited */
1073 V(mutex_p1); /* never goes here */
1078 pthread_create(&id1, NULL, self_lock, NULL);
1080 ok(lmgr_detect_deadlock(), "Check self deadlock");
1081 lmgr_v(&mutex1.mutex); /* a bit dirty */
1082 pthread_join(id1, NULL);
1085 pthread_create(&id1, NULL, nolock, NULL);
1087 nok(lmgr_detect_deadlock(), "Check for nolock");
1088 pthread_join(id1, NULL);
1091 pthread_create(&id1, NULL, locker, &mutex1);
1092 pthread_create(&id2, NULL, locker, &mutex1);
1093 pthread_create(&id3, NULL, locker, &mutex1);
1095 nok(lmgr_detect_deadlock(), "Check for multiple lock");
1097 pthread_join(id1, NULL);
1098 pthread_join(id2, NULL);
1099 pthread_join(id3, NULL);
1106 pthread_create(&id1, NULL, rwlocker, &wr);
1107 pthread_create(&id2, NULL, rwlocker, &wr);
1108 pthread_create(&id3, NULL, rwlocker, &wr);
1109 nok(lmgr_detect_deadlock(), "Check for multiple rwlock");
1110 rwl_writeunlock(&wr);
1111 nok(lmgr_detect_deadlock(), "Check for simple rwlock");
1112 rwl_writeunlock(&wr);
1113 nok(lmgr_detect_deadlock(), "Check for multiple rwlock");
1115 pthread_join(id1, NULL);
1116 pthread_join(id2, NULL);
1117 pthread_join(id3, NULL);
1121 pthread_create(&id1, NULL, mix_rwl_mutex, &wr);
1122 nok(lmgr_detect_deadlock(), "Check for mix rwlock/mutex");
1124 nok(lmgr_detect_deadlock(), "Check for mix rwlock/mutex");
1125 rwl_writeunlock(&wr);
1126 nok(lmgr_detect_deadlock(), "Check for mix rwlock/mutex");
1127 pthread_join(id1, NULL);
1134 nok(lmgr_detect_deadlock(), "Check for wrong order");
1136 for(int j=0; j<200; j++) {
1137 pthread_create(&tab[j], NULL, thx, NULL);
1139 for(int j=0; j<200; j++) {
1140 pthread_join(tab[j], NULL);
1141 if (j%3) { lmgr_detect_deadlock();}
1143 nok(lmgr_detect_deadlock(), "Check 200 lockers");
1152 pthread_create(&id1, NULL, th1, NULL);
1154 pthread_create(&id2, NULL, th2, NULL);
1156 ok(lmgr_detect_deadlock(), "Check for deadlock");
1158 pthread_create(&id3, NULL, th_prio, NULL);
1159 pthread_join(id3, &ret);
1160 ok(ret != 0, "Check for priority segfault");
1162 self = lmgr_get_thread_info();
1164 ok(self->max_priority == 1, "Check max_priority 1/4");
1166 ok(self->max_priority == 2, "Check max_priority 2/4");
1168 ok(self->max_priority == 3, "Check max_priority 3/4");
1170 ok(self->max_priority == 3, "Check max_priority 4/4");
1172 ok(self->max_priority == 3, "Check max_priority 1/5");
1174 ok(self->max_priority == 2, "Check max_priority 4/5");
1176 ok(self->max_priority == 1, "Check max_priority 4/5");
1178 ok(self->max_priority == 0, "Check max_priority 5/5");
1185 ok(self->max_priority == 3, "Check max_priority mixed");
1187 ok(self->max_priority == 3, "Check max_priority mixed");
1189 ok(self->max_priority == 3, "Check max_priority mixed");
1191 ok(self->max_priority == 0, "Check max_priority mixed");
1193 ok(self->max_priority == 0, "Check max_priority mixed");
1202 // pthread_create(&id3, NULL, th3, NULL);
1204 // pthread_join(id1, NULL);
1205 // pthread_join(id2, NULL);
1206 lmgr_cleanup_main();
1207 sm_check(__FILE__, __LINE__, false);