assert(mutex.is_locked());
- --mutex.nlock;
+ mutex._pre_unlock();
int r = pthread_cond_wait(&_c, &mutex._m);
- ++mutex.nlock;
+ mutex._post_lock();
return r;
}
struct timespec ts;
when.to_timespec(&ts);
- --mutex.nlock;
+
+ mutex._pre_unlock();
int r = pthread_cond_timedwait(&_c, &mutex._m, &ts);
- ++mutex.nlock;
+ mutex._post_lock();
+
return r;
}
int WaitInterval(CephContext *cct, Mutex &mutex, utime_t interval) {
pthread_mutex_t _m;
int nlock;
+ pthread_t locked_by;
// don't allow copying.
void operator=(Mutex &M) {}
public:
Mutex(const char *n, bool r = false, bool ld=true, bool bt=false) :
- name(n), id(-1), recursive(r), lockdep(ld), backtrace(bt), nlock(0) {
+ name(n), id(-1), recursive(r), lockdep(ld), backtrace(bt), nlock(0), locked_by(0) {
if (recursive) {
// Mutexes of type PTHREAD_MUTEX_RECURSIVE do all the same checks as
// mutexes of type PTHREAD_MUTEX_ERRORCHECK.
int r = pthread_mutex_trylock(&_m);
if (r == 0) {
if (lockdep && g_lockdep) _locked();
- nlock++;
+ _post_lock();
}
return r == 0;
}
void Lock(bool no_lockdep=false) {
if (lockdep && g_lockdep && !no_lockdep) _will_lock();
int r = pthread_mutex_lock(&_m);
- if (lockdep && g_lockdep) _locked();
assert(r == 0);
- if (!recursive)
+ if (lockdep && g_lockdep) _locked();
+ _post_lock();
+ }
+ void _post_lock() {
+ if (!recursive) {
assert(nlock == 0);
+ locked_by = pthread_self();
+ };
nlock++;
}
- void Unlock() {
+ void _pre_unlock() {
assert(nlock > 0);
--nlock;
- if (!recursive)
+ if (!recursive) {
+ assert(locked_by == pthread_self());
+ locked_by = 0;
assert(nlock == 0);
+ }
+ }
+ void Unlock() {
+ _pre_unlock();
if (lockdep && g_lockdep) _will_unlock();
int r = pthread_mutex_unlock(&_m);
assert(r == 0);