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_kill (only with USE_LOCKMGR_SAFEKILL)
716 int bthread_kill(pthread_t thread, int sig,
717 const char *file, int line)
719 bool thread_found_in_process=false;
721 /* We doesn't allow to send signal to ourself */
722 ASSERT(!pthread_equal(thread, pthread_self()));
724 /* This loop isn't very efficient with dozens of threads but we don't use
725 * signal very much, and this feature is for testing only
727 lmgr_p(&lmgr_global_mutex);
730 foreach_dlist(item, global_mgr) {
731 if (pthread_equal(thread, item->thread_id)) {
732 thread_found_in_process=true;
737 lmgr_v(&lmgr_global_mutex);
739 /* Sending a signal to non existing thread can create problem
740 * so, we can stop here.
742 ASSERT(thread_found_in_process == true);
744 return pthread_kill(thread, sig);
748 * Replacement for pthread_mutex_lock()
751 int bthread_mutex_lock_p(bthread_mutex_t *m, const char *file, int line)
753 lmgr_thread_t *self = lmgr_get_thread_info();
754 self->pre_P(m, m->priority, file, line);
761 * Replacement for pthread_mutex_unlock()
764 int bthread_mutex_unlock_p(bthread_mutex_t *m, const char *file, int line)
766 lmgr_thread_t *self = lmgr_get_thread_info();
767 self->do_V(m, file, line);
773 * Replacement for pthread_mutex_lock() but with real pthread_mutex_t
776 int bthread_mutex_lock_p(pthread_mutex_t *m, const char *file, int line)
778 lmgr_thread_t *self = lmgr_get_thread_info();
779 self->pre_P(m, 0, file, line);
786 * Replacement for pthread_mutex_unlock() but with real pthread_mutex_t
789 int bthread_mutex_unlock_p(pthread_mutex_t *m, const char *file, int line)
791 lmgr_thread_t *self = lmgr_get_thread_info();
792 self->do_V(m, file, line);
800 int bthread_cond_wait_p(pthread_cond_t *cond,
802 const char *file, int line)
805 lmgr_thread_t *self = lmgr_get_thread_info();
806 self->do_V(m, file, line);
807 ret = pthread_cond_wait(cond, m);
808 self->pre_P(m, 0, file, line);
815 int bthread_cond_timedwait_p(pthread_cond_t *cond,
817 const struct timespec * abstime,
818 const char *file, int line)
821 lmgr_thread_t *self = lmgr_get_thread_info();
822 self->do_V(m, file, line);
823 ret = pthread_cond_timedwait(cond, m, abstime);
824 self->pre_P(m, 0, file, line);
831 int bthread_cond_wait_p(pthread_cond_t *cond,
833 const char *file, int line)
836 lmgr_thread_t *self = lmgr_get_thread_info();
837 self->do_V(m, file, line);
838 ret = pthread_cond_wait(cond, &m->mutex);
839 self->pre_P(m, m->priority, file, line);
846 int bthread_cond_timedwait_p(pthread_cond_t *cond,
848 const struct timespec * abstime,
849 const char *file, int line)
852 lmgr_thread_t *self = lmgr_get_thread_info();
853 self->do_V(m, file, line);
854 ret = pthread_cond_timedwait(cond, &m->mutex, abstime);
855 self->pre_P(m, m->priority, file, line);
860 /* Test if this mutex is locked by the current thread
863 * 1 - locked by the current thread
864 * 2 - locked by an other thread
866 int lmgr_mutex_is_locked(void *m)
868 lmgr_thread_t *self = lmgr_get_thread_info();
870 for(int i=0; i <= self->current; i++) {
871 if (self->lock_list[i].lock == m) {
872 return 1; /* locked by us */
876 return 0; /* not locked by us */
880 * Use this function when the caller handle the mutex directly
882 * lmgr_pre_lock(m, 10);
883 * pthread_mutex_lock(m);
886 void lmgr_pre_lock(void *m, int prio, const char *file, int line)
888 lmgr_thread_t *self = lmgr_get_thread_info();
889 self->pre_P(m, prio, file, line);
893 * Use this function when the caller handle the mutex directly
895 void lmgr_post_lock()
897 lmgr_thread_t *self = lmgr_get_thread_info();
902 * Do directly pre_P and post_P (used by trylock)
904 void lmgr_do_lock(void *m, int prio, const char *file, int line)
906 lmgr_thread_t *self = lmgr_get_thread_info();
907 self->pre_P(m, prio, file, line);
912 * Use this function when the caller handle the mutex directly
914 void lmgr_do_unlock(void *m)
916 lmgr_thread_t *self = lmgr_get_thread_info();
921 void *(*start_routine)(void*);
926 void *lmgr_thread_launcher(void *x)
930 pthread_cleanup_push(cln_hdl, NULL);
932 lmgr_thread_arg_t arg;
933 lmgr_thread_arg_t *a = (lmgr_thread_arg_t *)x;
934 arg.start_routine = a->start_routine;
938 ret = arg.start_routine(arg.arg);
939 pthread_cleanup_pop(1);
943 int lmgr_thread_create(pthread_t *thread,
944 const pthread_attr_t *attr,
945 void *(*start_routine)(void*), void *arg)
947 /* lmgr should be active (lmgr_init_thread() call in main()) */
948 ASSERT(lmgr_is_active());
949 /* Will be freed by the child */
950 lmgr_thread_arg_t *a = (lmgr_thread_arg_t*) malloc(sizeof(lmgr_thread_arg_t));
951 a->start_routine = start_routine;
953 return pthread_create(thread, attr, lmgr_thread_launcher, a);
956 #else /* _USE_LOCKMGR */
960 * Use this function is used only after a fatal signal
961 * We don't use locking to display information
963 void dbg_print_lock(FILE *fp)
965 Pmsg0(000, "lockmgr disabled\n");
968 #endif /* _USE_LOCKMGR */
973 #define BTHREAD_MUTEX_NO_PRIORITY {PTHREAD_MUTEX_INITIALIZER, 0}
974 #define BTHREAD_MUTEX_PRIORITY(p) {PTHREAD_MUTEX_INITIALIZER, p}
977 #define P(x) bthread_mutex_lock_p(&(x), __FILE__, __LINE__)
978 #define V(x) bthread_mutex_unlock_p(&(x), __FILE__, __LINE__)
979 #define pthread_create(a, b, c, d) lmgr_thread_create(a,b,c,d)
981 bthread_mutex_t mutex1 = BTHREAD_MUTEX_NO_PRIORITY;
982 bthread_mutex_t mutex2 = BTHREAD_MUTEX_NO_PRIORITY;
983 bthread_mutex_t mutex3 = BTHREAD_MUTEX_NO_PRIORITY;
984 bthread_mutex_t mutex4 = BTHREAD_MUTEX_NO_PRIORITY;
985 bthread_mutex_t mutex5 = BTHREAD_MUTEX_NO_PRIORITY;
986 bthread_mutex_t mutex6 = BTHREAD_MUTEX_NO_PRIORITY;
987 bthread_mutex_t mutex_p1 = BTHREAD_MUTEX_PRIORITY(1);
988 bthread_mutex_t mutex_p2 = BTHREAD_MUTEX_PRIORITY(2);
989 bthread_mutex_t mutex_p3 = BTHREAD_MUTEX_PRIORITY(3);
990 static const char *my_prog;
992 void *self_lock(void *temp)
1001 void *nolock(void *temp)
1009 void *locker(void *temp)
1011 bthread_mutex_t *m = (bthread_mutex_t*) temp;
1017 void *rwlocker(void *temp)
1019 brwlock_t *m = (brwlock_t*) temp;
1028 void *mix_rwl_mutex(void *temp)
1030 brwlock_t *m = (brwlock_t*) temp;
1039 void *th2(void *temp)
1054 void *th1(void *temp)
1071 void *thx(void *temp)
1073 int s= 1 + (int) (500.0 * (rand() / (RAND_MAX + 1.0))) + 200;
1084 void *th3(void *a) {
1086 fprintf(stderr, "undertaker sleep()\n");
1089 if (lmgr_detect_deadlock()) {
1097 void *th_prio(void *a) {
1099 bstrncpy(buf, my_prog, sizeof(buf));
1100 bstrncat(buf, " priority", sizeof(buf));
1101 int ret = system(buf);
1107 void _ok(const char *file, int l, const char *op, int value, const char *label)
1112 printf("ERR %.30s %s:%i on %s\n", label, file, l, op);
1114 printf("OK %.30s\n", label);
1118 #define ok(x, label) _ok(__FILE__, __LINE__, #x, (x), label)
1120 void _nok(const char *file, int l, const char *op, int value, const char *label)
1125 printf("ERR %.30s %s:%i on !%s\n", label, file, l, op);
1127 printf("OK %.30s\n", label);
1131 #define nok(x, label) _nok(__FILE__, __LINE__, #x, (x), label)
1135 printf("Result %i/%i OK\n", nb - err, nb);
1141 * - Must detect multiple lock
1142 * - lock/unlock in wrong order
1143 * - deadlock with 2 or 3 threads
1145 int main(int argc, char **argv)
1148 lmgr_thread_t *self;
1149 pthread_t id1, id2, id3, tab[200];
1150 bthread_mutex_t bmutex1;
1151 pthread_mutex_t pmutex2;
1154 use_undertaker = false;
1156 self = lmgr_get_thread_info();
1158 if (argc == 2) { /* do priority check */
1159 P(mutex_p2); /* not permited */
1161 V(mutex_p1); /* never goes here */
1166 pthread_mutex_init(&bmutex1, NULL);
1167 bthread_mutex_set_priority(&bmutex1, 10);
1169 pthread_mutex_init(&pmutex2, NULL);
1171 ok(self->max_priority == 10, "Check self max_priority");
1173 ok(bmutex1.priority == 10, "Check bmutex_set_priority()");
1176 ok(self->max_priority == 0, "Check self max_priority");
1178 pthread_create(&id1, NULL, self_lock, NULL);
1180 ok(lmgr_detect_deadlock(), "Check self deadlock");
1181 lmgr_v(&mutex1.mutex); /* a bit dirty */
1182 pthread_join(id1, NULL);
1185 pthread_create(&id1, NULL, nolock, NULL);
1187 nok(lmgr_detect_deadlock(), "Check for nolock");
1188 pthread_join(id1, NULL);
1191 pthread_create(&id1, NULL, locker, &mutex1);
1192 pthread_create(&id2, NULL, locker, &mutex1);
1193 pthread_create(&id3, NULL, locker, &mutex1);
1195 nok(lmgr_detect_deadlock(), "Check for multiple lock");
1197 pthread_join(id1, NULL);
1198 pthread_join(id2, NULL);
1199 pthread_join(id3, NULL);
1206 pthread_create(&id1, NULL, rwlocker, &wr);
1207 pthread_create(&id2, NULL, rwlocker, &wr);
1208 pthread_create(&id3, NULL, rwlocker, &wr);
1209 nok(lmgr_detect_deadlock(), "Check for multiple rwlock");
1210 rwl_writeunlock(&wr);
1211 nok(lmgr_detect_deadlock(), "Check for simple rwlock");
1212 rwl_writeunlock(&wr);
1213 nok(lmgr_detect_deadlock(), "Check for multiple rwlock");
1215 pthread_join(id1, NULL);
1216 pthread_join(id2, NULL);
1217 pthread_join(id3, NULL);
1221 pthread_create(&id1, NULL, mix_rwl_mutex, &wr);
1222 nok(lmgr_detect_deadlock(), "Check for mix rwlock/mutex");
1224 nok(lmgr_detect_deadlock(), "Check for mix rwlock/mutex");
1225 rwl_writeunlock(&wr);
1226 nok(lmgr_detect_deadlock(), "Check for mix rwlock/mutex");
1227 pthread_join(id1, NULL);
1234 nok(lmgr_detect_deadlock(), "Check for wrong order");
1236 for(int j=0; j<200; j++) {
1237 pthread_create(&tab[j], NULL, thx, NULL);
1239 for(int j=0; j<200; j++) {
1240 pthread_join(tab[j], NULL);
1241 if (j%3) { lmgr_detect_deadlock();}
1243 nok(lmgr_detect_deadlock(), "Check 200 lockers");
1248 ok(lmgr_mutex_is_locked(&mutex6) == 1, "Check if mutex is locked");
1250 ok(lmgr_mutex_is_locked(&mutex6) == 0, "Check if mutex is locked");
1254 pthread_create(&id1, NULL, th1, NULL);
1256 pthread_create(&id2, NULL, th2, NULL);
1258 ok(lmgr_detect_deadlock(), "Check for deadlock");
1260 pthread_create(&id3, NULL, th_prio, NULL);
1261 pthread_join(id3, &ret);
1262 ok(ret != 0, "Check for priority segfault");
1265 ok(self->max_priority == 1, "Check max_priority 1/4");
1267 ok(self->max_priority == 2, "Check max_priority 2/4");
1269 ok(self->max_priority == 3, "Check max_priority 3/4");
1271 ok(self->max_priority == 3, "Check max_priority 4/4");
1273 ok(self->max_priority == 3, "Check max_priority 1/5");
1275 ok(self->max_priority == 2, "Check max_priority 4/5");
1277 ok(self->max_priority == 1, "Check max_priority 4/5");
1279 ok(self->max_priority == 0, "Check max_priority 5/5");
1286 ok(self->max_priority == 3, "Check max_priority mixed");
1288 ok(self->max_priority == 3, "Check max_priority mixed");
1290 ok(self->max_priority == 3, "Check max_priority mixed");
1292 ok(self->max_priority == 0, "Check max_priority mixed");
1294 ok(self->max_priority == 0, "Check max_priority mixed");
1303 // pthread_create(&id3, NULL, th3, NULL);
1305 // pthread_join(id1, NULL);
1306 // pthread_join(id2, NULL);
1307 lmgr_cleanup_main();
1308 sm_check(__FILE__, __LINE__, false);