]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
lockdep: include Mutex.cc
authorSage Weil <sage@newdream.net>
Sat, 1 Nov 2008 00:10:06 +0000 (17:10 -0700)
committerSage Weil <sage@newdream.net>
Sat, 1 Nov 2008 00:10:06 +0000 (17:10 -0700)
src/common/Mutex.cc [new file with mode: 0644]

diff --git a/src/common/Mutex.cc b/src/common/Mutex.cc
new file mode 100644 (file)
index 0000000..7cd254a
--- /dev/null
@@ -0,0 +1,123 @@
+
+#include "Mutex.h"
+
+int g_lockdep = 0;
+
+#ifdef LOCKDEP
+
+#include "include/types.h"
+#include "Clock.h"
+#include "BackTrace.h"
+
+#include <hash_map>
+
+#include "config.h"
+
+#define  dout(l)    if (l<=g_conf.debug_lockdep) *_dout << g_clock.now() << " " << pthread_self() << " lockdep: "
+#define  derr(l)    if (l<=g_conf.debug_lockdep) *_derr << g_clock.now() << " " << pthread_self() << " lockdep: "
+
+
+pthread_mutex_t lockdep_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+hash_map<pthread_t, map<const char *, BackTrace *> > held;
+hash_map<const char *, map<const char *, BackTrace *> > follows;       // <left item> follows <right items>
+hash_map<const char *, map<const char *, BackTrace *> > follows_ever;
+
+#define BACKTRACE_SKIP 3
+
+// does a follow b?
+bool does_follow(const char *a, const char *b)
+{
+  if (!follows.count(a))
+    return false;
+  
+  map<const char *, BackTrace *> &s = follows[a];
+  if (s.count(b)) {
+    dout(0) << "------------------------------------" << std::endl;
+    dout(0) << a << " <- " << b << " at: " << std::endl;
+    s[b]->print(*_dout);
+    *_dout << std::endl;
+    return true;
+  }
+
+  for (map<const char *, BackTrace *>::iterator p = s.begin(); p != s.end(); p++)
+    if (does_follow(p->first, b)) {
+      dout(0) << a << " <- " << p->first << " at: " << std::endl;
+      p->second->print(*_dout);
+      *_dout << std::endl;
+      return true;
+    }
+
+  return false;
+}
+
+void Mutex::_will_lock()
+{
+  pthread_t p = pthread_self();
+
+  dout(20) << name << " _will_lock" << std::endl;
+
+  pthread_mutex_lock(&lockdep_mutex);
+
+  // check dependency graph
+  map<const char *, BackTrace *> &m = held[p];
+  for (map<const char *, BackTrace *>::iterator p = m.begin();
+       p != m.end();
+       p++) {
+    if (!follows[name].count(p->first)) {
+      // new dependency 
+      
+      // did we just create a cycle?
+      BackTrace *bt = new BackTrace(BACKTRACE_SKIP);
+      if (does_follow(p->first, name)) {
+       dout(0) << "new dependency " << name << " <- " << p->first
+               << " creates a cycle at"
+               << std::endl;
+       bt->print(*_dout);
+       *_dout << std::endl;
+       *_dout << std::endl;
+       *_dout << std::endl;
+
+       // don't add this dependency, or we'll get aMutex. cycle in the graph, and
+       // does_follow() won't terminate.
+      } else {
+       follows[name][p->first] = bt;
+       dout(10) << name << " <- " << p->first << " at" << std::endl;
+       //bt->print(*_dout);
+      }
+    }
+  }
+
+  pthread_mutex_unlock(&lockdep_mutex);
+}
+
+void Mutex::_locked()
+{
+  BackTrace *bt = new BackTrace(BACKTRACE_SKIP);
+  pthread_t p = pthread_self();
+
+  dout(20) << name << " _locked" << std::endl;
+
+  pthread_mutex_lock(&lockdep_mutex);
+  held[p][name] = bt;
+  pthread_mutex_unlock(&lockdep_mutex);
+}
+
+void Mutex::_unlocked()
+{
+  pthread_t p = pthread_self();
+  
+  dout(20) << name << " _unlocked" << std::endl;
+  pthread_mutex_lock(&lockdep_mutex);
+  assert(held.count(p));
+  assert(held[p].count(name));
+  delete held[p][name];
+  held[p].erase(name);
+  pthread_mutex_unlock(&lockdep_mutex);
+}
+
+
+
+
+
+#endif