From 2e7c543b7e4fa87b09e1139c164b7ca8e4e90cc7 Mon Sep 17 00:00:00 2001 From: Eric Bollengier Date: Tue, 8 Dec 2009 21:03:11 +0100 Subject: [PATCH] Add new bthread_mutex_t object that check mutex priority order --- bacula/src/lib/lockmgr.c | 296 ++++++++++++++++++++++++++++++++------- bacula/src/lib/lockmgr.h | 95 ++++++++++--- bacula/src/lib/rwlock.c | 7 +- bacula/src/lib/rwlock.h | 3 +- 4 files changed, 330 insertions(+), 71 deletions(-) diff --git a/bacula/src/lib/lockmgr.c b/bacula/src/lib/lockmgr.c index 3342be2b7d..d882da271e 100644 --- a/bacula/src/lib/lockmgr.c +++ b/bacula/src/lib/lockmgr.c @@ -27,12 +27,17 @@ */ #define _LOCKMGR_COMPLIANT -#include "lockmgr.h" +#include "bacula.h" #undef ASSERT #define ASSERT(x) if (!(x)) { \ char *jcr = NULL; \ - Pmsg3(000, _("%s:%i Failed ASSERT: %s\n"), __FILE__, __LINE__, #x); \ + Pmsg3(000, _("Failed ASSERT: %s\n"), __FILE__, __LINE__, #x); \ + jcr[0] = 0; } + +#define ASSERT_p(x,f,l) if (!(x)) { \ + char *jcr = NULL; \ + Pmsg3(000, _("from %s:%i Failed ASSERT: %s\n"), f, l, #x); \ jcr[0] = 0; } /* @@ -139,13 +144,16 @@ public: dlink link; void *lock; lmgr_state_t state; - + int max_priority; + int priority; + const char *file; int line; lmgr_lock_t() { lock = NULL; state = LMGR_LOCK_EMPTY; + priority = max_priority = 0; } lmgr_lock_t(void *l) { @@ -228,6 +236,7 @@ public: lmgr_lock_t lock_list[LMGR_MAX_LOCK]; int current; int max; + int max_priority; lmgr_thread_t() { int status; @@ -240,6 +249,7 @@ public: thread_id = pthread_self(); current = -1; max = 0; + max_priority = 0; } void _dump(FILE *fp) { @@ -264,9 +274,11 @@ public: /* * Call before a lock operation (mark mutex as WANTED) */ - virtual void pre_P(void *m, const char *f="*unknown*", int l=0) { - ASSERT(current < LMGR_MAX_LOCK); - ASSERT(current >= -1); + virtual void pre_P(void *m, int priority, + const char *f="*unknown*", int l=0) { + ASSERT_p(current < LMGR_MAX_LOCK, f, l); + ASSERT_p(current >= -1, f, l); + ASSERT_p(!priority || priority >= max_priority, f, l); lmgr_p(&mutex); { current++; @@ -274,7 +286,10 @@ public: lock_list[current].state = LMGR_LOCK_WANTED; lock_list[current].file = f; lock_list[current].line = l; + lock_list[current].priority = priority; + lock_list[current].max_priority = MAX(priority, max_priority); max = MAX(current, max); + max_priority = MAX(priority, max_priority); } lmgr_v(&mutex); } @@ -288,6 +303,7 @@ public: lock_list[current].state = LMGR_LOCK_GRANTED; } + /* Using this function is some sort of bug */ void shift_list(int i) { for(int j=i+1; j<=current; j++) { lock_list[i] = lock_list[j]; @@ -296,13 +312,19 @@ public: lock_list[current].lock = NULL; lock_list[current].state = LMGR_LOCK_EMPTY; } + /* rebuild the priority list */ + max_priority = 0; + for(int j=0; j< current; j++) { + max_priority = MAX(lock_list[j].priority, max_priority); + lock_list[j].max_priority = max_priority; + } } /* * Remove the mutex from the list */ virtual void do_V(void *m, const char *f="*unknown*", int l=0) { - ASSERT(current >= 0); + ASSERT_p(current >= 0, f, l); lmgr_p(&mutex); { if (lock_list[current].lock == m) { @@ -326,6 +348,12 @@ public: } } } + /* reset max_priority to the last one */ + if (current >= 0) { + max_priority = lock_list[current].max_priority; + } else { + max_priority = 0; + } } lmgr_v(&mutex); } @@ -341,7 +369,7 @@ class lmgr_dummy_thread_t: public lmgr_thread_t { void do_V(void *m, const char *file, int l) {} void post_P() {} - void pre_P(void *m, const char *file, int l) {} + void pre_P(void *m, int priority, const char *file, int l) {} }; /* @@ -357,6 +385,7 @@ static pthread_key_t lmgr_key; /* used to get lgmr_thread_t object */ static dlist *global_mgr = NULL; /* used to store all lgmr_thread_t objects */ static pthread_mutex_t lmgr_global_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_t undertaker; +static bool use_undertaker=true; #define lmgr_is_active() (global_mgr != NULL) @@ -554,12 +583,14 @@ void create_lmgr_key() lmgr_thread_t *n=NULL; global_mgr = New(dlist(n, &n->link)); - status = pthread_create(&undertaker, NULL, check_deadlock, NULL); - if (status != 0) { - berrno be; - Pmsg1(000, _("pthread_create failed: ERR=%s\n"), - be.bstrerror(status)); - ASSERT(0); + if (use_undertaker) { + status = pthread_create(&undertaker, NULL, check_deadlock, NULL); + if (status != 0) { + berrno be; + Pmsg1(000, _("pthread_create failed: ERR=%s\n"), + be.bstrerror(status)); + ASSERT(0); + } } } @@ -606,7 +637,9 @@ void lmgr_cleanup_main() if (!global_mgr) { return; } - pthread_cancel(undertaker); + if (use_undertaker) { + pthread_cancel(undertaker); + } lmgr_cleanup_thread(); lmgr_p(&lmgr_global_mutex); { @@ -617,15 +650,40 @@ void lmgr_cleanup_main() lmgr_v(&lmgr_global_mutex); } +/* + * Set the priority of the lmgr mutex object + */ +void bthread_mutex_set_priority(bthread_mutex_t *m, int prio) +{ + m->priority = prio; +} + +/* + * Replacement for pthread_mutex_init() + */ +int bthread_mutex_init(bthread_mutex_t *m, const pthread_mutexattr_t *attr) +{ + m->priority = 0; + return pthread_mutex_init(&m->mutex, attr); +} + +/* + * Replacement for pthread_mutex_destroy() + */ +int bthread_mutex_destroy(bthread_mutex_t *m) +{ + return pthread_mutex_destroy(&m->mutex); +} + /* * Replacement for pthread_mutex_lock() * Returns always ok */ -int lmgr_mutex_lock(pthread_mutex_t *m, const char *file, int line) +int bthread_mutex_lock_p(bthread_mutex_t *m, const char *file, int line) { lmgr_thread_t *self = lmgr_get_thread_info(); - self->pre_P(m, file, line); - lmgr_p(m); + self->pre_P(m, m->priority, file, line); + lmgr_p(&m->mutex); self->post_P(); return 0; } @@ -634,7 +692,32 @@ int lmgr_mutex_lock(pthread_mutex_t *m, const char *file, int line) * Replacement for pthread_mutex_unlock() * Returns always ok */ -int lmgr_mutex_unlock(pthread_mutex_t *m, const char *file, int line) +int bthread_mutex_unlock_p(bthread_mutex_t *m, const char *file, int line) +{ + lmgr_thread_t *self = lmgr_get_thread_info(); + self->do_V(m, file, line); + lmgr_v(&m->mutex); + return 0; +} + +/* + * Replacement for pthread_mutex_lock() but with real pthread_mutex_t + * Returns always ok + */ +int bthread_mutex_lock_p(pthread_mutex_t *m, const char *file, int line) +{ + lmgr_thread_t *self = lmgr_get_thread_info(); + self->pre_P(m, 0, file, line); + lmgr_p(m); + self->post_P(); + return 0; +} + +/* + * Replacement for pthread_mutex_unlock() but with real pthread_mutex_t + * Returns always ok + */ +int bthread_mutex_unlock_p(pthread_mutex_t *m, const char *file, int line) { lmgr_thread_t *self = lmgr_get_thread_info(); self->do_V(m, file, line); @@ -642,17 +725,65 @@ int lmgr_mutex_unlock(pthread_mutex_t *m, const char *file, int line) return 0; } + +/* TODO: check this + */ +int bthread_cond_wait_p(pthread_cond_t *cond, + pthread_mutex_t *m, + const char *file, int line) +{ + int ret; + lmgr_thread_t *self = lmgr_get_thread_info(); + self->do_V(m, file, line); + ret = pthread_cond_wait(cond, m); + self->pre_P(m, 0, file, line); + self->post_P(); + return ret; +} + +/* TODO: check this + */ +int bthread_cond_timedwait_p(pthread_cond_t *cond, + pthread_mutex_t *m, + const struct timespec * abstime, + const char *file, int line) +{ + int ret; + lmgr_thread_t *self = lmgr_get_thread_info(); + self->do_V(m, file, line); + ret = pthread_cond_timedwait(cond, m, abstime); + self->pre_P(m, 0, file, line); + self->post_P(); + return ret; +} + /* TODO: check this */ -int lmgr_cond_wait(pthread_cond_t *cond, - pthread_mutex_t *mutex, - const char *file, int line) +int bthread_cond_wait_p(pthread_cond_t *cond, + bthread_mutex_t *m, + const char *file, int line) { int ret; lmgr_thread_t *self = lmgr_get_thread_info(); - self->do_V(mutex, file, line); - ret = pthread_cond_wait(cond, mutex); - self->pre_P(mutex, file, line); + self->do_V(m, file, line); + ret = pthread_cond_wait(cond, &m->mutex); + self->pre_P(m, m->priority, file, line); + self->post_P(); + return ret; +} + +/* TODO: check this + */ +int bthread_cond_timedwait_p(pthread_cond_t *cond, + bthread_mutex_t *m, + const struct timespec * abstime, + const char *file, int line) +{ + int ret; + lmgr_thread_t *self = lmgr_get_thread_info(); + self->do_V(m, file, line); + ret = pthread_cond_timedwait(cond, &m->mutex, abstime); + self->pre_P(m, m->priority, file, line); self->post_P(); return ret; } @@ -660,14 +791,14 @@ int lmgr_cond_wait(pthread_cond_t *cond, /* * Use this function when the caller handle the mutex directly * - * lmgr_pre_lock(m); + * lmgr_pre_lock(m, 10); * pthread_mutex_lock(m); * lmgr_post_lock(m); */ -void lmgr_pre_lock(void *m, const char *file, int line) +void lmgr_pre_lock(void *m, int prio, const char *file, int line) { lmgr_thread_t *self = lmgr_get_thread_info(); - self->pre_P(m, file, line); + self->pre_P(m, prio, file, line); } /* @@ -682,10 +813,10 @@ void lmgr_post_lock() /* * Do directly pre_P and post_P (used by trylock) */ -void lmgr_do_lock(void *m, const char *file, int line) +void lmgr_do_lock(void *m, int prio, const char *file, int line) { lmgr_thread_t *self = lmgr_get_thread_info(); - self->pre_P(m, file, line); + self->pre_P(m, prio, file, line); self->post_P(); } @@ -751,21 +882,27 @@ void dbg_print_lock(FILE *fp) #ifdef _TEST_IT #include "lockmgr.h" -#define pthread_mutex_lock(x) lmgr_mutex_lock(x) -#define pthread_mutex_unlock(x) lmgr_mutex_unlock(x) -#define pthread_cond_wait(x,y) lmgr_cond_wait(x,y) -#define pthread_create(a, b, c, d) lmgr_thread_create(a,b,c,d) +#define BTHREAD_MUTEX_NO_PRIORITY {PTHREAD_MUTEX_INITIALIZER, 0} +#define BTHREAD_MUTEX_PRIORITY_1 {PTHREAD_MUTEX_INITIALIZER, 1} +#define BTHREAD_MUTEX_PRIORITY_2 {PTHREAD_MUTEX_INITIALIZER, 2} +#define BTHREAD_MUTEX_PRIORITY_3 {PTHREAD_MUTEX_INITIALIZER, 3} +#define BTHREAD_MUTEX_PRIORITY_4 {PTHREAD_MUTEX_INITIALIZER, 4} #undef P #undef V -#define P(x) lmgr_mutex_lock(&(x), __FILE__, __LINE__) -#define V(x) lmgr_mutex_unlock(&(x), __FILE__, __LINE__) - -pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; -pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER; -pthread_mutex_t mutex3 = PTHREAD_MUTEX_INITIALIZER; -pthread_mutex_t mutex4 = PTHREAD_MUTEX_INITIALIZER; -pthread_mutex_t mutex5 = PTHREAD_MUTEX_INITIALIZER; -pthread_mutex_t mutex6 = PTHREAD_MUTEX_INITIALIZER; +#define P(x) bthread_mutex_lock_p(&(x), __FILE__, __LINE__) +#define V(x) bthread_mutex_unlock_p(&(x), __FILE__, __LINE__) +#define pthread_create(a, b, c, d) lmgr_thread_create(a,b,c,d) + +bthread_mutex_t mutex1 = BTHREAD_MUTEX_NO_PRIORITY; +bthread_mutex_t mutex2 = BTHREAD_MUTEX_NO_PRIORITY; +bthread_mutex_t mutex3 = BTHREAD_MUTEX_NO_PRIORITY; +bthread_mutex_t mutex4 = BTHREAD_MUTEX_NO_PRIORITY; +bthread_mutex_t mutex5 = BTHREAD_MUTEX_NO_PRIORITY; +bthread_mutex_t mutex6 = BTHREAD_MUTEX_NO_PRIORITY; +bthread_mutex_t mutex_p1 = BTHREAD_MUTEX_PRIORITY_1; +bthread_mutex_t mutex_p2 = BTHREAD_MUTEX_PRIORITY_2; +bthread_mutex_t mutex_p3 = BTHREAD_MUTEX_PRIORITY_3; +static const char *my_prog; void *self_lock(void *temp) { @@ -786,9 +923,9 @@ void *nolock(void *temp) void *locker(void *temp) { - pthread_mutex_t *m = (pthread_mutex_t*) temp; - lmgr_p(m); - lmgr_v(m); + bthread_mutex_t *m = (bthread_mutex_t*) temp; + P(*m); + V(*m); return NULL; } @@ -872,6 +1009,14 @@ void *th3(void *a) { return NULL; } +void *th_prio(void *a) { + char buf[512]; + bstrncpy(buf, my_prog, sizeof(buf)); + bstrncat(buf, " priority", sizeof(buf)); + int ret = system(buf); + return (void*) ret; +} + int err=0; int nb=0; void _ok(const char *file, int l, const char *op, int value, const char *label) @@ -912,15 +1057,28 @@ int report() * - lock/unlock in wrong order * - deadlock with 2 or 3 threads */ -int main() +int main(int argc, char **argv) { + void *ret=NULL; + lmgr_thread_t *self; pthread_t id1, id2, id3, tab[200]; + my_prog = argv[0]; + + use_undertaker = false; lmgr_init_thread(); + if (argc == 2) { /* do priority check */ + P(mutex_p2); /* not permited */ + P(mutex_p1); + V(mutex_p1); /* never goes here */ + V(mutex_p2); + return 0; + } + pthread_create(&id1, NULL, self_lock, NULL); sleep(2); ok(lmgr_detect_deadlock(), "Check self deadlock"); - lmgr_v(&mutex1); /* a bit dirty */ + lmgr_v(&mutex1.mutex); /* a bit dirty */ pthread_join(id1, NULL); @@ -997,6 +1155,48 @@ int main() sleep(1); ok(lmgr_detect_deadlock(), "Check for deadlock"); + pthread_create(&id3, NULL, th_prio, NULL); + pthread_join(id3, &ret); + ok(ret != 0, "Check for priority segfault"); + + self = lmgr_get_thread_info(); + P(mutex_p1); + ok(self->max_priority == 1, "Check max_priority 1/4"); + P(mutex_p2); + ok(self->max_priority == 2, "Check max_priority 2/4"); + P(mutex_p3); + ok(self->max_priority == 3, "Check max_priority 3/4"); + P(mutex6); + ok(self->max_priority == 3, "Check max_priority 4/4"); + V(mutex6); + ok(self->max_priority == 3, "Check max_priority 1/5"); + V(mutex_p3); + ok(self->max_priority == 2, "Check max_priority 4/5"); + V(mutex_p2); + ok(self->max_priority == 1, "Check max_priority 4/5"); + V(mutex_p1); + ok(self->max_priority == 0, "Check max_priority 5/5"); + + + P(mutex_p1); + P(mutex_p2); + P(mutex_p3); + P(mutex6); + ok(self->max_priority == 3, "Check max_priority mixed"); + V(mutex_p2); + ok(self->max_priority == 3, "Check max_priority mixed"); + V(mutex_p1); + ok(self->max_priority == 3, "Check max_priority mixed"); + V(mutex_p3); + ok(self->max_priority == 0, "Check max_priority mixed"); + V(mutex6); + ok(self->max_priority == 0, "Check max_priority mixed"); + + P(mutex_p1); + P(mutex_p2); + V(mutex_p1); + V(mutex_p2); + // lmgr_dump(); // // pthread_create(&id3, NULL, th3, NULL); diff --git a/bacula/src/lib/lockmgr.h b/bacula/src/lib/lockmgr.h index 697b844838..fdde9c7a2a 100644 --- a/bacula/src/lib/lockmgr.h +++ b/bacula/src/lib/lockmgr.h @@ -29,8 +29,6 @@ #ifndef _LOCKMGR_H #define _LOCKMGR_H 1 -#include "bacula.h" - /* * P and V op that don't use the lock manager (for memory allocation or on * win32) @@ -40,40 +38,74 @@ void lmgr_v(pthread_mutex_t *m); #ifdef _USE_LOCKMGR +typedef struct bthread_mutex_t +{ + pthread_mutex_t mutex; + int priority; +} bthread_mutex_t; + /* * We decide that a thread won't lock more than LMGR_MAX_LOCK at the same time */ #define LMGR_MAX_LOCK 32 -/* Not yet working */ -int lmgr_cond_wait(pthread_cond_t *cond, - pthread_mutex_t *mutex, - const char *file="*unknown*", int line=0); +int bthread_cond_wait_p(pthread_cond_t *cond, + bthread_mutex_t *mutex, + const char *file="*unknown*", int line=0); + +int bthread_cond_timedwait_p(pthread_cond_t *cond, + bthread_mutex_t *mutex, + const struct timespec * abstime, + const char *file="*unknown*", int line=0); + +/* Same with real pthread_mutex_t */ +int bthread_cond_wait_p(pthread_cond_t *cond, + pthread_mutex_t *mutex, + const char *file="*unknown*", int line=0); + +int bthread_cond_timedwait_p(pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec * abstime, + const char *file="*unknown*", int line=0); + +/* Replacement of pthread_mutex_lock() but with real pthread_mutex_t */ +int bthread_mutex_lock_p(pthread_mutex_t *m, + const char *file="*unknown*", int line=0); + +/* Replacement for pthread_mutex_unlock() but with real pthread_mutex_t */ +int bthread_mutex_unlock_p(pthread_mutex_t *m, + const char *file="*unknown*", int line=0); /* Replacement of pthread_mutex_lock() */ -int lmgr_mutex_lock(pthread_mutex_t *m, - const char *file="*unknown*", int line=0); +int bthread_mutex_lock_p(bthread_mutex_t *m, + const char *file="*unknown*", int line=0); /* Replacement of pthread_mutex_unlock() */ -int lmgr_mutex_unlock(pthread_mutex_t *m, - const char *file="*unknown*", int line=0); +int bthread_mutex_unlock_p(bthread_mutex_t *m, + const char *file="*unknown*", int line=0); /* * Use them when you want use your lock yourself (ie rwlock) */ /* Call before requesting the lock */ -void lmgr_pre_lock(void *m, const char *file="*unknown*", int line=0); +void lmgr_pre_lock(void *m, int prio=0, + const char *file="*unknown*", int line=0); /* Call after getting it */ void lmgr_post_lock(); /* Same as pre+post lock */ -void lmgr_do_lock(void *m, const char *file="*unknown*", int line=0); +void lmgr_do_lock(void *m, int prio=0, + const char *file="*unknown*", int line=0); /* Call just before releasing the lock */ void lmgr_do_unlock(void *m); +int bthread_mutex_init(bthread_mutex_t *m, const pthread_mutexattr_t *attr); +int bthread_mutex_destroy(bthread_mutex_t *m); +void bthread_mutex_set_priority(bthread_mutex_t *m, int prio); + /* * Each thread have to call this function to put a lmgr_thread_t object * in the stack and be able to call mutex_lock/unlock @@ -120,16 +152,28 @@ int lmgr_thread_create(pthread_t *thread, * Define _LOCKMGR_COMPLIANT to use real pthread functions */ +#define BTHREAD_MUTEX_NO_PRIORITY {PTHREAD_MUTEX_INITIALIZER, 0} +#define BTHREAD_MUTEX_PRIORITY_1 {PTHREAD_MUTEX_INITIALIZER, 1} +#define BTHREAD_MUTEX_PRIORITY_2 {PTHREAD_MUTEX_INITIALIZER, 2} +#define BTHREAD_MUTEX_PRIORITY_3 {PTHREAD_MUTEX_INITIALIZER, 3} +#define BTHREAD_MUTEX_PRIORITY_4 {PTHREAD_MUTEX_INITIALIZER, 4} +#define BTHREAD_MUTEX_INITIALIZER BTHREAD_MUTEX_NO_PRIORITY +#define bthread_mutex_lock(x) bthread_mutex_lock_p(x, __FILE__, __LINE__) +#define bthread_mutex_unlock(x) bthread_mutex_unlock_p +#define bthread_cond_wait(x,y) bthread_cond_wait_p(x,y, __FILE__, __LINE__) +#define bthread_cond_timedwait(x,y,z) bthread_cond_timedwait_p(x,y,z, __FILE__, __LINE__) + #ifdef _LOCKMGR_COMPLIANT # define P(x) lmgr_p(&(x)) # define V(x) lmgr_v(&(x)) #else -# define P(x) lmgr_mutex_lock(&(x), __FILE__, __LINE__) -# define V(x) lmgr_mutex_unlock(&(x), __FILE__, __LINE__) -# define pthread_mutex_lock(x) lmgr_mutex_lock(x, __FILE__, __LINE__) -# define pthread_mutex_unlock(x) lmgr_mutex_unlock(x, __FILE__, __LINE__) -# define pthread_cond_wait(x,y) lmgr_cond_wait(x,y, __FILE__, __LINE__) -# define pthread_create(a, b, c, d) lmgr_thread_create(a,b,c,d) +# define P(x) bthread_mutex_lock_p(&(x), __FILE__, __LINE__) +# define V(x) bthread_mutex_unlock_p(&(x), __FILE__, __LINE__) +# define pthread_create(a, b, c, d) lmgr_thread_create(a,b,c,d) +# define pthread_mutex_lock(x) bthread_mutex_lock(x) +# define pthread_mutex_unlock(x) bthread_mutex_unlock(x) +# define pthread_cond_wait(x,y) bthread_cond_wait(x,y) +# define pthread_cond_timedwait(x,y,z) bthread_cond_timedwait(x,y,z) #endif #else /* _USE_LOCKMGR */ @@ -143,9 +187,22 @@ int lmgr_thread_create(pthread_t *thread, # define lmgr_do_lock(m, f, l) # define lmgr_do_unlock(m) # define lmgr_cleanup_main() +# define bthread_mutex_set_priority(a) +# define bthread_mutex_init(a,b) pthread_mutex_init(a,b) +# define bthread_mutex_destroy(a) pthread_mutex_destroy(a) +# define bthread_mutex_lock(a) pthread_mutex_lock(a) +# define bthread_mutex_unlock(a) pthread_mutex_unlock(a) +# define lmgr_cond_wait(a,b) pthread_cond_wait(a,b) +# define lmgr_cond_timedwait(a,b,c) pthread_cond_timedwait(a,b,c) +# define bthread_mutex_t pthread_mutex_t # define P(x) lmgr_p(&(x)) # define V(x) lmgr_v(&(x)) - +# define BTHREAD_MUTEX_NO_PRIORITY PTHREAD_MUTEX_INITIALIZER +# define BTHREAD_MUTEX_PRIORITY_1 PTHREAD_MUTEX_INITIALIZER +# define BTHREAD_MUTEX_PRIORITY_2 PTHREAD_MUTEX_INITIALIZER +# define BTHREAD_MUTEX_PRIORITY_3 PTHREAD_MUTEX_INITIALIZER +# define BTHREAD_MUTEX_PRIORITY_4 PTHREAD_MUTEX_INITIALIZER +# define BTHREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER #endif /* _USE_LOCKMGR */ #endif /* _LOCKMGR_H */ diff --git a/bacula/src/lib/rwlock.c b/bacula/src/lib/rwlock.c index e91b9eab37..0647343aa5 100644 --- a/bacula/src/lib/rwlock.c +++ b/bacula/src/lib/rwlock.c @@ -49,12 +49,13 @@ * Returns: 0 on success * errno on failure */ -int rwl_init(brwlock_t *rwl) +int rwl_init(brwlock_t *rwl, int prio) { int stat; rwl->r_active = rwl->w_active = 0; rwl->r_wait = rwl->w_wait = 0; + rwl->priority = prio; if ((stat = pthread_mutex_init(&rwl->mutex, NULL)) != 0) { return stat; } @@ -233,7 +234,7 @@ int rwl_writelock(brwlock_t *rwl) pthread_mutex_unlock(&rwl->mutex); return 0; } - lmgr_pre_lock(rwl, __FILE__, __LINE__); + lmgr_pre_lock(rwl, rwl->priority, __FILE__, __LINE__); if (rwl->w_active || rwl->r_active > 0) { rwl->w_wait++; /* indicate that we are waiting */ pthread_cleanup_push(rwl_write_release, (void *)rwl); @@ -278,7 +279,7 @@ int rwl_writetrylock(brwlock_t *rwl) } else { rwl->w_active = 1; /* we are running */ rwl->writer_id = pthread_self(); /* save writer thread's id */ - lmgr_do_lock(rwl, __FILE__, __LINE__); + lmgr_do_lock(rwl, rwl->priority, __FILE__, __LINE__); } stat2 = pthread_mutex_unlock(&rwl->mutex); return (stat == 0 ? stat2 : stat); diff --git a/bacula/src/lib/rwlock.h b/bacula/src/lib/rwlock.h index f03af8eb9f..7c5847636d 100644 --- a/bacula/src/lib/rwlock.h +++ b/bacula/src/lib/rwlock.h @@ -46,6 +46,7 @@ typedef struct s_rwlock_tag { pthread_cond_t read; /* wait for read */ pthread_cond_t write; /* wait for write */ pthread_t writer_id; /* writer's thread id */ + int priority; /* used in deadlock detection */ int valid; /* set when valid */ int r_active; /* readers active */ int w_active; /* writers active */ @@ -68,7 +69,7 @@ typedef struct s_rwsteal_tag { /* * read/write lock prototypes */ -extern int rwl_init(brwlock_t *wrlock); +extern int rwl_init(brwlock_t *wrlock, int priority=0); extern int rwl_destroy(brwlock_t *rwlock); extern int rwl_readlock(brwlock_t *rwlock); extern int rwl_readtrylock(brwlock_t *rwlock); -- 2.39.5