#define BACKTRACE_SKIP 2
/******* Globals **********/
-int g_lockdep = 0;
+bool g_lockdep;
struct lockdep_stopper_t {
// disable lockdep when this module destructs.
~lockdep_stopper_t() {
static char follows[MAX_LOCKS][MAX_LOCKS/8]; // follows[a][b] means b taken after a
static BackTrace *follows_bt[MAX_LOCKS][MAX_LOCKS];
unsigned current_maxid;
-int last_freed_id;
+int last_freed_id = -1;
+static bool free_ids_inited;
static bool lockdep_force_backtrace()
{
g_lockdep = true;
g_lockdep_ceph_ctx = cct;
lockdep_dout(1) << "lockdep start" << dendl;
- current_maxid = 0;
- last_freed_id = -1;
-
- memset((void*) &free_ids[0], 255, sizeof(free_ids));
+ if (!free_ids_inited) {
+ free_ids_inited = true;
+ memset((void*) &free_ids[0], 255, sizeof(free_ids));
+ }
}
pthread_mutex_unlock(&lockdep_mutex);
}
held.clear();
lock_names.clear();
lock_ids.clear();
- lock_refs.clear();
- memset((void*)&free_ids[0], 0, sizeof(free_ids));
memset((void*)&follows[0][0], 0, current_maxid * MAX_LOCKS/8);
memset((void*)&follows_bt[0][0], 0, sizeof(BackTrace*) * current_maxid * MAX_LOCKS);
- current_maxid = 0;
- last_freed_id = -1;
}
pthread_mutex_unlock(&lockdep_mutex);
}
int lockdep_dump_locks()
{
pthread_mutex_lock(&lockdep_mutex);
+ if (!g_lockdep)
+ goto out;
for (ceph::unordered_map<pthread_t, map<int,BackTrace*> >::iterator p = held.begin();
p != held.end();
*_dout << dendl;
}
}
-
+out:
pthread_mutex_unlock(&lockdep_mutex);
return 0;
}
return -1;
}
-int lockdep_register(const char *name)
+static int _lockdep_register(const char *name)
{
- int id;
+ int id = -1;
- pthread_mutex_lock(&lockdep_mutex);
+ if (!g_lockdep)
+ return id;
ceph::unordered_map<std::string, int>::iterator p = lock_ids.find(name);
if (p == lock_ids.end()) {
id = lockdep_get_free_id();
}
++lock_refs[id];
- pthread_mutex_unlock(&lockdep_mutex);
return id;
}
+int lockdep_register(const char *name)
+{
+ int id;
+
+ pthread_mutex_lock(&lockdep_mutex);
+ id = _lockdep_register(name);
+ pthread_mutex_unlock(&lockdep_mutex);
+ return id;
+}
+
void lockdep_unregister(int id)
{
if (id < 0) {
pthread_mutex_lock(&lockdep_mutex);
+ std::string name;
map<int, std::string>::iterator p = lock_names.find(id);
- assert(p != lock_names.end());
+ if (p == lock_names.end())
+ name = { "unknown" };
+ else
+ name = p->second;
int &refs = lock_refs[id];
if (--refs == 0) {
- // reset dependency ordering
- memset((void*)&follows[id][0], 0, MAX_LOCKS/8);
- for (unsigned i=0; i<current_maxid; ++i) {
- delete follows_bt[id][i];
- follows_bt[id][i] = NULL;
-
- delete follows_bt[i][id];
- follows_bt[i][id] = NULL;
- follows[i][id / 8] &= 255 - (1 << (id % 8));
- }
+ if (p != lock_names.end()) {
+ // reset dependency ordering
+ memset((void*)&follows[id][0], 0, MAX_LOCKS/8);
+ for (unsigned i=0; i<current_maxid; ++i) {
+ delete follows_bt[id][i];
+ follows_bt[id][i] = NULL;
+
+ delete follows_bt[i][id];
+ follows_bt[i][id] = NULL;
+ follows[i][id / 8] &= 255 - (1 << (id % 8));
+ }
- lockdep_dout(10) << "unregistered '" << p->second << "' from " << id
- << dendl;
- lock_ids.erase(p->second);
- lock_names.erase(id);
+ lockdep_dout(10) << "unregistered '" << name << "' from " << id << dendl;
+ lock_ids.erase(p->second);
+ lock_names.erase(id);
+ }
lock_refs.erase(id);
free_ids[id/8] |= (1 << (id % 8));
- last_freed_id = id;
- } else {
- lockdep_dout(20) << "have " << refs << " of '" << p->second << "' "
- << "from " << id << dendl;
+ last_freed_id = id;
+ } else if (g_lockdep) {
+ lockdep_dout(20) << "have " << refs << " of '" << name << "' " <<
+ "from " << id << dendl;
}
pthread_mutex_unlock(&lockdep_mutex);
}
int lockdep_will_lock(const char *name, int id, bool force_backtrace)
{
pthread_t p = pthread_self();
- if (id < 0) id = lockdep_register(name);
pthread_mutex_lock(&lockdep_mutex);
+ if (!g_lockdep) {
+ pthread_mutex_unlock(&lockdep_mutex);
+ return id;
+ }
+
+ if (id < 0)
+ id = _lockdep_register(name);
+
lockdep_dout(20) << "_will_lock " << name << " (" << id << ")" << dendl;
// check dependency graph
}
}
}
-
pthread_mutex_unlock(&lockdep_mutex);
return id;
}
{
pthread_t p = pthread_self();
- if (id < 0) id = lockdep_register(name);
-
pthread_mutex_lock(&lockdep_mutex);
+ if (!g_lockdep)
+ goto out;
+ if (id < 0)
+ id = _lockdep_register(name);
+
lockdep_dout(20) << "_locked " << name << dendl;
if (force_backtrace || lockdep_force_backtrace())
held[p][id] = new BackTrace(BACKTRACE_SKIP);
else
held[p][id] = 0;
+out:
pthread_mutex_unlock(&lockdep_mutex);
return id;
}
}
pthread_mutex_lock(&lockdep_mutex);
+ if (!g_lockdep)
+ goto out;
lockdep_dout(20) << "_will_unlock " << name << dendl;
// don't assert.. lockdep may be enabled at any point in time
delete held[p][id];
held[p].erase(id);
+out:
pthread_mutex_unlock(&lockdep_mutex);
return id;
}