Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / common / Mutex.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4  * Ceph - scalable distributed file system
5  *
6  * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
7  *
8  * This is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License version 2.1, as published by the Free Software
11  * Foundation.  See file COPYING.
12  *
13  */
14
15 #include "common/Mutex.h"
16 #include "common/perf_counters.h"
17 #include "common/config.h"
18 #include "common/Clock.h"
19 #include "common/valgrind.h"
20
21 Mutex::Mutex(const std::string &n, bool r, bool ld,
22              bool bt,
23              CephContext *cct) :
24   name(n), id(-1), recursive(r), lockdep(ld), backtrace(bt), nlock(0),
25   locked_by(0), cct(cct), logger(0)
26 {
27   ANNOTATE_BENIGN_RACE_SIZED(&id, sizeof(id), "Mutex lockdep id");
28   ANNOTATE_BENIGN_RACE_SIZED(&nlock, sizeof(nlock), "Mutex nlock");
29   ANNOTATE_BENIGN_RACE_SIZED(&locked_by, sizeof(locked_by), "Mutex locked_by");
30   if (cct) {
31     PerfCountersBuilder b(cct, string("mutex-") + name,
32                           l_mutex_first, l_mutex_last);
33     b.add_time_avg(l_mutex_wait, "wait", "Average time of mutex in locked state");
34     logger = b.create_perf_counters();
35     cct->get_perfcounters_collection()->add(logger);
36     logger->set(l_mutex_wait, 0);
37   }
38   if (recursive) {
39     // Mutexes of type PTHREAD_MUTEX_RECURSIVE do all the same checks as
40     // mutexes of type PTHREAD_MUTEX_ERRORCHECK.
41     pthread_mutexattr_t attr;
42     pthread_mutexattr_init(&attr);
43     pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
44     pthread_mutex_init(&_m,&attr);
45     pthread_mutexattr_destroy(&attr);
46     if (lockdep && g_lockdep)
47       _register();
48   }
49   else if (lockdep) {
50     // If the mutex type is PTHREAD_MUTEX_ERRORCHECK, then error checking
51     // shall be provided. If a thread attempts to relock a mutex that it
52     // has already locked, an error shall be returned. If a thread
53     // attempts to unlock a mutex that it has not locked or a mutex which
54     // is unlocked, an error shall be returned.
55     pthread_mutexattr_t attr;
56     pthread_mutexattr_init(&attr);
57     pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
58     pthread_mutex_init(&_m, &attr);
59     pthread_mutexattr_destroy(&attr);
60     if (g_lockdep)
61       _register();
62   }
63   else {
64     // If the mutex type is PTHREAD_MUTEX_DEFAULT, attempting to recursively
65     // lock the mutex results in undefined behavior. Attempting to unlock the
66     // mutex if it was not locked by the calling thread results in undefined
67     // behavior. Attempting to unlock the mutex if it is not locked results in
68     // undefined behavior.
69     pthread_mutex_init(&_m, NULL);
70   }
71 }
72
73 Mutex::~Mutex() {
74   assert(nlock == 0);
75
76   // helgrind gets confused by condition wakeups leading to mutex destruction
77   ANNOTATE_BENIGN_RACE_SIZED(&_m, sizeof(_m), "Mutex primitive");
78   pthread_mutex_destroy(&_m);
79
80   if (cct && logger) {
81     cct->get_perfcounters_collection()->remove(logger);
82     delete logger;
83   }
84   if (lockdep && g_lockdep) {
85     lockdep_unregister(id);
86   }
87 }
88
89 void Mutex::Lock(bool no_lockdep) {
90   int r;
91
92   if (lockdep && g_lockdep && !no_lockdep && !recursive) _will_lock();
93
94   if (logger && cct && cct->_conf->mutex_perf_counter) {
95     utime_t start;
96     // instrumented mutex enabled
97     start = ceph_clock_now();
98     if (TryLock()) {
99       goto out;
100     }
101
102     r = pthread_mutex_lock(&_m);
103
104     logger->tinc(l_mutex_wait,
105                  ceph_clock_now() - start);
106   } else {
107     r = pthread_mutex_lock(&_m);
108   }
109
110   assert(r == 0);
111   if (lockdep && g_lockdep) _locked();
112   _post_lock();
113
114 out:
115   ;
116 }
117
118 void Mutex::Unlock() {
119   _pre_unlock();
120   if (lockdep && g_lockdep) _will_unlock();
121   int r = pthread_mutex_unlock(&_m);
122   assert(r == 0);
123 }