]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
spinlock: add support for pthread spinlocks
authorSage Weil <sage@newdream.net>
Mon, 20 Apr 2009 13:59:01 +0000 (06:59 -0700)
committerSage Weil <sage@newdream.net>
Mon, 20 Apr 2009 13:59:01 +0000 (06:59 -0700)
src/common/Spinlock.h [new file with mode: 0644]

diff --git a/src/common/Spinlock.h b/src/common/Spinlock.h
new file mode 100644 (file)
index 0000000..bf204b2
--- /dev/null
@@ -0,0 +1,113 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software 
+ * Foundation.  See file COPYING.
+ * 
+ */
+
+#ifndef __SPINLOCK_H
+#define __SPINLOCK_H
+
+#include <pthread.h>
+#include "include/assert.h"
+#include "lockdep.h"
+
+#define LOCKDEP
+
+class Spinlock {
+private:
+  const char *name;
+  int id;
+  bool lockdep;
+  bool backtrace;  // gather backtrace on lock acquisition
+
+  pthread_spinlock_t _s;
+  int nlock;
+
+  // don't allow copying.
+  void operator=(Spinlock &M) {}
+  Spinlock( const Spinlock &M ) {}
+
+#ifdef LOCKDEP
+  void _register() {
+    id = lockdep_register(name);
+  }
+  void _will_lock() { // about to lock
+    id = lockdep_will_lock(name, id);
+  }
+  void _locked() {    // just locked
+    id = lockdep_locked(name, id, backtrace);
+  }
+  void _unlocked() {  // just unlocked
+    id = lockdep_unlocked(name, id);
+  }
+#else
+  void _register() {}
+  void _will_lock() {} // about to lock
+  void _locked() {}    // just locked
+  void _unlocked() {}  // just unlocked
+#endif
+
+public:
+  Spinlock(const char *n, bool ld=true, bool bt=false) :
+    name(n), id(-1), lockdep(ld), backtrace(bt), nlock(0) {
+    pthread_spin_init(&_s, NULL);
+    if (lockdep && g_lockdep) _register();
+  }
+  ~Spinlock() {
+    assert(nlock == 0);
+    pthread_spin_destroy(&_s); 
+  }
+
+  bool is_locked() {
+    return (nlock > 0);
+  }
+
+  bool try_lock() {
+    int r = pthread_spin_trylock(&_s);
+    if (r == 0) {
+      if (lockdep && g_lockdep) _locked();
+      nlock++;
+    }
+    return r == 0;
+  }
+
+  void lock() {
+    if (lockdep && g_lockdep) _will_lock();
+    int r = pthread_spin_lock(&_s);
+    if (lockdep && g_lockdep) _locked();
+    assert(r == 0);
+    nlock++;
+  }
+
+  void unlock() {
+    assert(nlock > 0);
+    --nlock;
+    int r = pthread_spin_unlock(&_s);
+    assert(r == 0);
+    if (lockdep && g_lockdep) _unlocked();
+  }
+
+public:
+  class Locker {
+    Spinlock &spinlock;
+
+  public:
+    Locker(Spinlock& m) : spinlock(m) {
+      spinlock.lock();
+    }
+    ~Locker() {
+      spinlock.unlock();
+    }
+  };
+};
+
+
+#endif