2 Bacula® - The Network Backup Solution
4 Copyright (C) 2008-2011 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 three of the GNU Affero 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 Affero 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 Dmsg3(100, "%s:%d send kill to existing thread %p\n", file, line, thread);
745 return pthread_kill(thread, sig);
749 * Replacement for pthread_mutex_lock()
752 int bthread_mutex_lock_p(bthread_mutex_t *m, const char *file, int line)
754 lmgr_thread_t *self = lmgr_get_thread_info();
755 self->pre_P(m, m->priority, file, line);
762 * Replacement for pthread_mutex_unlock()
765 int bthread_mutex_unlock_p(bthread_mutex_t *m, const char *file, int line)
767 lmgr_thread_t *self = lmgr_get_thread_info();
768 self->do_V(m, file, line);
774 * Replacement for pthread_mutex_lock() but with real pthread_mutex_t
777 int bthread_mutex_lock_p(pthread_mutex_t *m, const char *file, int line)
779 lmgr_thread_t *self = lmgr_get_thread_info();
780 self->pre_P(m, 0, file, line);
787 * Replacement for pthread_mutex_unlock() but with real pthread_mutex_t
790 int bthread_mutex_unlock_p(pthread_mutex_t *m, const char *file, int line)
792 lmgr_thread_t *self = lmgr_get_thread_info();
793 self->do_V(m, file, line);
801 int bthread_cond_wait_p(pthread_cond_t *cond,
803 const char *file, int line)
806 lmgr_thread_t *self = lmgr_get_thread_info();
807 self->do_V(m, file, line);
808 ret = pthread_cond_wait(cond, m);
809 self->pre_P(m, 0, file, line);
816 int bthread_cond_timedwait_p(pthread_cond_t *cond,
818 const struct timespec * abstime,
819 const char *file, int line)
822 lmgr_thread_t *self = lmgr_get_thread_info();
823 self->do_V(m, file, line);
824 ret = pthread_cond_timedwait(cond, m, abstime);
825 self->pre_P(m, 0, file, line);
832 int bthread_cond_wait_p(pthread_cond_t *cond,
834 const char *file, int line)
837 lmgr_thread_t *self = lmgr_get_thread_info();
838 self->do_V(m, file, line);
839 ret = pthread_cond_wait(cond, &m->mutex);
840 self->pre_P(m, m->priority, file, line);
847 int bthread_cond_timedwait_p(pthread_cond_t *cond,
849 const struct timespec * abstime,
850 const char *file, int line)
853 lmgr_thread_t *self = lmgr_get_thread_info();
854 self->do_V(m, file, line);
855 ret = pthread_cond_timedwait(cond, &m->mutex, abstime);
856 self->pre_P(m, m->priority, file, line);
861 /* Test if this mutex is locked by the current thread
864 * 1 - locked by the current thread
865 * 2 - locked by an other thread
867 int lmgr_mutex_is_locked(void *m)
869 lmgr_thread_t *self = lmgr_get_thread_info();
871 for(int i=0; i <= self->current; i++) {
872 if (self->lock_list[i].lock == m) {
873 return 1; /* locked by us */
877 return 0; /* not locked by us */
881 * Use this function when the caller handle the mutex directly
883 * lmgr_pre_lock(m, 10);
884 * pthread_mutex_lock(m);
887 void lmgr_pre_lock(void *m, int prio, const char *file, int line)
889 lmgr_thread_t *self = lmgr_get_thread_info();
890 self->pre_P(m, prio, file, line);
894 * Use this function when the caller handle the mutex directly
896 void lmgr_post_lock()
898 lmgr_thread_t *self = lmgr_get_thread_info();
903 * Do directly pre_P and post_P (used by trylock)
905 void lmgr_do_lock(void *m, int prio, const char *file, int line)
907 lmgr_thread_t *self = lmgr_get_thread_info();
908 self->pre_P(m, prio, file, line);
913 * Use this function when the caller handle the mutex directly
915 void lmgr_do_unlock(void *m)
917 lmgr_thread_t *self = lmgr_get_thread_info();
922 void *(*start_routine)(void*);
927 void *lmgr_thread_launcher(void *x)
931 pthread_cleanup_push(cln_hdl, NULL);
933 lmgr_thread_arg_t arg;
934 lmgr_thread_arg_t *a = (lmgr_thread_arg_t *)x;
935 arg.start_routine = a->start_routine;
939 ret = arg.start_routine(arg.arg);
940 pthread_cleanup_pop(1);
944 int lmgr_thread_create(pthread_t *thread,
945 const pthread_attr_t *attr,
946 void *(*start_routine)(void*), void *arg)
948 /* lmgr should be active (lmgr_init_thread() call in main()) */
949 ASSERT(lmgr_is_active());
950 /* Will be freed by the child */
951 lmgr_thread_arg_t *a = (lmgr_thread_arg_t*) malloc(sizeof(lmgr_thread_arg_t));
952 a->start_routine = start_routine;
954 return pthread_create(thread, attr, lmgr_thread_launcher, a);
957 #else /* _USE_LOCKMGR */
961 * Use this function is used only after a fatal signal
962 * We don't use locking to display information
964 void dbg_print_lock(FILE *fp)
966 Pmsg0(000, "lockmgr disabled\n");
969 #endif /* _USE_LOCKMGR */
976 #define P(x) bthread_mutex_lock_p(&(x), __FILE__, __LINE__)
977 #define V(x) bthread_mutex_unlock_p(&(x), __FILE__, __LINE__)
978 #define pthread_create(a, b, c, d) lmgr_thread_create(a,b,c,d)
980 bthread_mutex_t mutex1 = BTHREAD_MUTEX_NO_PRIORITY;
981 bthread_mutex_t mutex2 = BTHREAD_MUTEX_NO_PRIORITY;
982 bthread_mutex_t mutex3 = BTHREAD_MUTEX_NO_PRIORITY;
983 bthread_mutex_t mutex4 = BTHREAD_MUTEX_NO_PRIORITY;
984 bthread_mutex_t mutex5 = BTHREAD_MUTEX_NO_PRIORITY;
985 bthread_mutex_t mutex6 = BTHREAD_MUTEX_NO_PRIORITY;
986 bthread_mutex_t mutex_p1 = BTHREAD_MUTEX_PRIORITY(1);
987 bthread_mutex_t mutex_p2 = BTHREAD_MUTEX_PRIORITY(2);
988 bthread_mutex_t mutex_p3 = BTHREAD_MUTEX_PRIORITY(3);
989 static const char *my_prog;
991 void *self_lock(void *temp)
1000 void *nolock(void *temp)
1008 void *locker(void *temp)
1010 bthread_mutex_t *m = (bthread_mutex_t*) temp;
1016 void *rwlocker(void *temp)
1018 brwlock_t *m = (brwlock_t*) temp;
1027 void *mix_rwl_mutex(void *temp)
1029 brwlock_t *m = (brwlock_t*) temp;
1038 void *th2(void *temp)
1053 void *th1(void *temp)
1070 void *thx(void *temp)
1072 int s= 1 + (int) (500.0 * (rand() / (RAND_MAX + 1.0))) + 200;
1083 void *th3(void *a) {
1085 fprintf(stderr, "undertaker sleep()\n");
1088 if (lmgr_detect_deadlock()) {
1096 void *th_prio(void *a) {
1098 bstrncpy(buf, my_prog, sizeof(buf));
1099 bstrncat(buf, " priority", sizeof(buf));
1100 int ret = system(buf);
1106 void _ok(const char *file, int l, const char *op, int value, const char *label)
1111 printf("ERR %.30s %s:%i on %s\n", label, file, l, op);
1113 printf("OK %.30s\n", label);
1117 #define ok(x, label) _ok(__FILE__, __LINE__, #x, (x), label)
1119 void _nok(const char *file, int l, const char *op, int value, const char *label)
1124 printf("ERR %.30s %s:%i on !%s\n", label, file, l, op);
1126 printf("OK %.30s\n", label);
1130 #define nok(x, label) _nok(__FILE__, __LINE__, #x, (x), label)
1134 printf("Result %i/%i OK\n", nb - err, nb);
1140 * - Must detect multiple lock
1141 * - lock/unlock in wrong order
1142 * - deadlock with 2 or 3 threads
1144 int main(int argc, char **argv)
1147 lmgr_thread_t *self;
1148 pthread_t id1, id2, id3, tab[200];
1149 bthread_mutex_t bmutex1;
1150 pthread_mutex_t pmutex2;
1153 use_undertaker = false;
1155 self = lmgr_get_thread_info();
1157 if (argc == 2) { /* do priority check */
1158 P(mutex_p2); /* not permited */
1160 V(mutex_p1); /* never goes here */
1165 pthread_mutex_init(&bmutex1, NULL);
1166 bthread_mutex_set_priority(&bmutex1, 10);
1168 pthread_mutex_init(&pmutex2, NULL);
1170 ok(self->max_priority == 10, "Check self max_priority");
1172 ok(bmutex1.priority == 10, "Check bmutex_set_priority()");
1175 ok(self->max_priority == 0, "Check self max_priority");
1177 pthread_create(&id1, NULL, self_lock, NULL);
1179 ok(lmgr_detect_deadlock(), "Check self deadlock");
1180 lmgr_v(&mutex1.mutex); /* a bit dirty */
1181 pthread_join(id1, NULL);
1184 pthread_create(&id1, NULL, nolock, NULL);
1186 nok(lmgr_detect_deadlock(), "Check for nolock");
1187 pthread_join(id1, NULL);
1190 pthread_create(&id1, NULL, locker, &mutex1);
1191 pthread_create(&id2, NULL, locker, &mutex1);
1192 pthread_create(&id3, NULL, locker, &mutex1);
1194 nok(lmgr_detect_deadlock(), "Check for multiple lock");
1196 pthread_join(id1, NULL);
1197 pthread_join(id2, NULL);
1198 pthread_join(id3, NULL);
1205 pthread_create(&id1, NULL, rwlocker, &wr);
1206 pthread_create(&id2, NULL, rwlocker, &wr);
1207 pthread_create(&id3, NULL, rwlocker, &wr);
1208 nok(lmgr_detect_deadlock(), "Check for multiple rwlock");
1209 rwl_writeunlock(&wr);
1210 nok(lmgr_detect_deadlock(), "Check for simple rwlock");
1211 rwl_writeunlock(&wr);
1212 nok(lmgr_detect_deadlock(), "Check for multiple rwlock");
1214 pthread_join(id1, NULL);
1215 pthread_join(id2, NULL);
1216 pthread_join(id3, NULL);
1220 pthread_create(&id1, NULL, mix_rwl_mutex, &wr);
1221 nok(lmgr_detect_deadlock(), "Check for mix rwlock/mutex");
1223 nok(lmgr_detect_deadlock(), "Check for mix rwlock/mutex");
1224 rwl_writeunlock(&wr);
1225 nok(lmgr_detect_deadlock(), "Check for mix rwlock/mutex");
1226 pthread_join(id1, NULL);
1233 nok(lmgr_detect_deadlock(), "Check for wrong order");
1235 for(int j=0; j<200; j++) {
1236 pthread_create(&tab[j], NULL, thx, NULL);
1238 for(int j=0; j<200; j++) {
1239 pthread_join(tab[j], NULL);
1240 if (j%3) { lmgr_detect_deadlock();}
1242 nok(lmgr_detect_deadlock(), "Check 200 lockers");
1247 ok(lmgr_mutex_is_locked(&mutex6) == 1, "Check if mutex is locked");
1249 ok(lmgr_mutex_is_locked(&mutex6) == 0, "Check if mutex is locked");
1253 pthread_create(&id1, NULL, th1, NULL);
1255 pthread_create(&id2, NULL, th2, NULL);
1257 ok(lmgr_detect_deadlock(), "Check for deadlock");
1259 pthread_create(&id3, NULL, th_prio, NULL);
1260 pthread_join(id3, &ret);
1261 ok(ret != 0, "Check for priority segfault");
1264 ok(self->max_priority == 1, "Check max_priority 1/4");
1266 ok(self->max_priority == 2, "Check max_priority 2/4");
1268 ok(self->max_priority == 3, "Check max_priority 3/4");
1270 ok(self->max_priority == 3, "Check max_priority 4/4");
1272 ok(self->max_priority == 3, "Check max_priority 1/5");
1274 ok(self->max_priority == 2, "Check max_priority 4/5");
1276 ok(self->max_priority == 1, "Check max_priority 4/5");
1278 ok(self->max_priority == 0, "Check max_priority 5/5");
1285 ok(self->max_priority == 3, "Check max_priority mixed");
1287 ok(self->max_priority == 3, "Check max_priority mixed");
1289 ok(self->max_priority == 3, "Check max_priority mixed");
1291 ok(self->max_priority == 0, "Check max_priority mixed");
1293 ok(self->max_priority == 0, "Check max_priority mixed");
1302 // pthread_create(&id3, NULL, th3, NULL);
1304 // pthread_join(id1, NULL);
1305 // pthread_join(id2, NULL);
1306 lmgr_cleanup_main();
1307 sm_check(__FILE__, __LINE__, false);