[PATCH] D26340: [analyzer] Add SpinLockChecker for the Magenta kernel

2016-11-09 Thread Devin Coughlin via cfe-commits
dcoughlin added a comment.

In https://reviews.llvm.org/D26340#590882, @khazem wrote:

> Devin, based on Artem's review of the other checker that I have posted [1] I 
> am wondering about merging both this SpinLockChecker and the MutexChecker 
> into PthreadLockChecker. Do you think it is still worth landing this 
> SpinLockChecker, or do you suppose that abandoning this patch and working on 
> merging all the checkers would be a good idea? I've noted how the checkers 
> might be merged in my reply to Artem: [2].


Merging seems reasonable to me. It is also a good way to make it less likely 
that the Magenta checkers accidentally regress since the main logic of the 
checker will be exercised when checking a much more common API.


https://reviews.llvm.org/D26340



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26340: [analyzer] Add SpinLockChecker for the Magenta kernel

2016-11-09 Thread Devin Coughlin via cfe-commits
dcoughlin added a comment.

Thanks for adding the path notes and adopting CallDescription. I've added some 
additional comments inline, which are mostly minor nits.

Two additional important changes -- and I should have noted these in the 
initial review -- is that it would be good to remove a MemRegion mapping from 
the program state when a MemRegion escapes and also when it becomes dead. These 
should both be small changes.

**Escaping**
Removing the mapping when the lock escapes will avoid false positives when the 
lock is passed to a function that the analyzer doesn't inline (for example, if 
it is in another translation unit) that unlocks it:

  void foo(lock_t *l) {
spin_lock(l);
...
do_stuff_and_unlock(l);
..
spin_lock();
  }

If `do_stuff_and_unlock()` is in another translation unit the analyzer won't 
see the unlock and so will report a false positive if you don't remove the 
mapping when the lock escapes.

If you remove the mapping when the lock escapes, the analyzer will 
optimistically assume the best-case scenario the next time it sees a lock or 
unlock operation. There is an example of how to do this in 
`ObjCContainersChecker::checkPointerEscape()`

**Removing Dead Symbols**
It is also important for performance to remove mappings that are no longer 
relevant. There is a cost to keep around mappings in the program state: both 
memory (because the analyzer keeps some states around for use in the bug 
reporter visitor) and time (because the analyzer has to iterate over the map 
when determining whether two states are the same).  There is an example of how 
to do this in `ObjCLoopChecker::checkDeadSymbols`.




Comment at: include/clang/StaticAnalyzer/Checkers/Checkers.td:728
+//===--===//
+// Magenta checkers.
+//===--===//

Nit: I think it would good to add a little bit more context to disambiguate so 
that future maintainers will be able to do a web search to learn about what 
these checkers are for. For example, maybe something like "Checkers for the 
Magenta kernel"?



Comment at: lib/StaticAnalyzer/Checkers/SpinLockChecker.cpp:208
+  *DoubleUnlockBugType,
+  "Execution path found where spinlock is unlocked twice in a row", Node);
+  Report->markInteresting(SpinLockLocation);

Nit: it is enough to have the message be "Spinlock is unlocked twice in a row". 
I don't think it is necessary to explicitly mention the execution path 
(especially now that you have a path note for the first unlock).



Comment at: lib/StaticAnalyzer/Checkers/SpinLockChecker.cpp:224
+  *DoubleLockBugType,
+  "Execution path found where spinlock is locked twice in a row", Node);
+  Report->addRange(Call.getSourceRange());

Nit: Same here.



Comment at: test/Analysis/spinlock_correct.c:1
+// RUN: %clang_cc1 -analyze -analyzer-checker=magenta.SpinLock -verify %s
+// expected-no-diagnostics

Nit: Typically in the analyzer codebase we try to keep the number of test files 
to a minimum. Can these three test files all be combined into one?



Comment at: test/Analysis/spinlock_correct.c:1
+// RUN: %clang_cc1 -analyze -analyzer-checker=magenta.SpinLock -verify %s
+// expected-no-diagnostics

dcoughlin wrote:
> Nit: Typically in the analyzer codebase we try to keep the number of test 
> files to a minimum. Can these three test files all be combined into one?
Another nit: The analyzer relies on always having core checkers enabled because 
they model important aspects of the language. You should change this to `... 
-analyzer-checker=core,magenta.SpinLock ...`


https://reviews.llvm.org/D26340



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26340: [analyzer] Add SpinLockChecker for the Magenta kernel

2016-11-09 Thread Kareem Khazem via cfe-commits
khazem marked 4 inline comments as done.
khazem added a comment.

Devin, based on Artem's review of the other checker that I have posted [1] I am 
wondering about merging both this SpinLockChecker and the MutexChecker into 
PthreadLockChecker. Do you think it is still worth landing this 
SpinLockChecker, or do you suppose that abandoning this patch and working on 
merging all the checkers would be a good idea? I've noted how the checkers 
might be merged in my reply to Artem: [2].

[1] https://reviews.llvm.org/D26342
[2] https://reviews.llvm.org/D26342#590881


https://reviews.llvm.org/D26340



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26340: [analyzer] Add SpinLockChecker for the Magenta kernel

2016-11-08 Thread Kareem Khazem via cfe-commits
khazem updated this revision to Diff 77277.
khazem added a comment.

If a double-lock or double-release is detected, path notes are now emitted on 
the _first_ lock or release event. Also updated the tests to check for these 
notes.


https://reviews.llvm.org/D26340

Files:
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/CMakeLists.txt
  lib/StaticAnalyzer/Checkers/SpinLockChecker.cpp
  test/Analysis/spinlock_correct.c
  test/Analysis/spinlock_double_lock.c
  test/Analysis/spinlock_double_release.c

Index: test/Analysis/spinlock_double_release.c
===
--- /dev/null
+++ test/Analysis/spinlock_double_release.c
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -analyze -analyzer-output=text -analyzer-checker=magenta.SpinLock -verify %s
+
+typedef unsigned int lock_t;
+
+typedef struct S {
+  int a;
+  lock_t l;
+} S_t;
+
+static S_t st;
+
+void spin_lock(lock_t *lock);
+void spin_unlock(lock_t *lock);
+int bar();
+
+void bar1(lock_t *y) {
+  spin_unlock(y); // expected-note {{First unlocked here}}
+}
+
+void bar2(lock_t *x) {
+  spin_unlock(x); // expected-warning{{Execution path found where spinlock is unlocked twice in a row}}
+  // expected-note@-1 0+ {{Execution path found where spinlock is unlocked twice in a row}}
+}
+
+int foo() {
+  int a = bar();
+  if (a > 0) {  // expected-note {{Assuming 'a' is > 0}} \
+// expected-note {{Taking true branch}}
+spin_lock();
+bar1(); // expected-note {{Calling 'bar1'}} \
+expected-note {{Returning from 'bar1'}}
+  }
+
+  lock_t *c = 
+  bar2(c);  // expected-note {{Calling 'bar2'}}
+  return 0;
+}
+
Index: test/Analysis/spinlock_double_lock.c
===
--- /dev/null
+++ test/Analysis/spinlock_double_lock.c
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=magenta.SpinLock -analyzer-output=text -verify %s
+
+typedef unsigned int lock_t;
+
+static lock_t l;
+
+void spin_lock(lock_t *lock);
+void spin_unlock(lock_t *lock);
+int bar();
+
+int foo() {
+  int a = bar();
+  if (a > 0) // expected-note{{Assuming 'a' is > 0}} \
+expected-note{{Taking true branch}}
+
+spin_lock(); // expected-note{{First locked here}}
+  if (a > 10) // expected-note{{Assuming 'a' is > 10}} \
+ expected-note{{Taking true branch}}
+
+spin_lock(); // expected-warning{{Execution path found where spinlock is locked twice in a row}}
+// expected-note@-1 0+ {{Execution path found where spinlock is locked twice in a row}}
+
+
+  return 0;
+}
+
Index: test/Analysis/spinlock_correct.c
===
--- /dev/null
+++ test/Analysis/spinlock_correct.c
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=magenta.SpinLock -verify %s
+// expected-no-diagnostics
+
+typedef unsigned int lock_t;
+
+static lock_t l;
+
+void spin_lock(lock_t *lock);
+void spin_unlock(lock_t *lock);
+int bar();
+
+int foo() {
+  int a = bar();
+  if (a > 0) {
+spin_lock();
+  }
+
+  if (a < -10) {
+spin_lock();
+  }
+
+  if (a > 0)
+spin_unlock();
+
+  if (a < -10)
+spin_unlock();
+
+  return 0;
+}
+
Index: lib/StaticAnalyzer/Checkers/SpinLockChecker.cpp
===
--- /dev/null
+++ lib/StaticAnalyzer/Checkers/SpinLockChecker.cpp
@@ -0,0 +1,262 @@
+//== SpinLockChecker.cpp - SpinLock checker -*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+//
+// This defines SpinLockChecker, a check for the Magenta kernel. It
+// checks that there are no execution paths where spinlocks are locked
+// twice in a row, or unlocked twice in a row.
+//
+//===--===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+struct LockInfo {
+
+  enum Kind { Locked, Released } K;
+
+  LockInfo(Kind kind) : K(kind) {}
+
+  bool operator==(const LockInfo ) const { return K == LI.K; }
+
+  void Profile(llvm::FoldingSetNodeID ) const { ID.AddInteger(K); }
+
+  bool isLocked() const { return K == Locked; }
+
+  bool isReleased() const { return K == Released; }
+
+  static LockInfo getLocked() { return LockInfo(Locked); }
+
+  static LockInfo getReleased() { return LockInfo(Released); }
+
+};
+
+// When we detect a double-lock or double-release, we 

[PATCH] D26340: [analyzer] Add SpinLockChecker for the Magenta kernel

2016-11-08 Thread Kareem Khazem via cfe-commits
khazem updated this revision to Diff 77275.
khazem added a comment.

The strings for Spin{Unl,L}ockFuncName and LockErrorCategory are now 
initialized when constructing a SpinLockChecker object rather than being static 
globals, in order to avoid adverse effects on startup time.

Also, the Spin*FuncName variables are now of type CallDescription. This is to 
enable pointer rather than string comparisons of the function name.


https://reviews.llvm.org/D26340

Files:
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/CMakeLists.txt
  lib/StaticAnalyzer/Checkers/SpinLockChecker.cpp
  test/Analysis/spinlock_correct.c
  test/Analysis/spinlock_double_lock.c
  test/Analysis/spinlock_double_release.c

Index: test/Analysis/spinlock_double_release.c
===
--- /dev/null
+++ test/Analysis/spinlock_double_release.c
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=magenta.SpinLock -verify %s
+
+typedef unsigned int lock_t;
+
+typedef struct S {
+  int a;
+  lock_t l;
+} S_t;
+
+static S_t st;
+
+void spin_lock(lock_t *lock);
+void spin_unlock(lock_t *lock);
+int bar();
+
+void bar1(lock_t *y) {
+  spin_unlock(y);
+}
+
+void bar2(lock_t *x) {
+  spin_unlock(x); // expected-warning{{Execution path found where spinlock is unlocked twice in a row}}
+}
+
+int foo() {
+  int a = bar();
+  if (a > 0) {
+spin_lock();
+bar1();
+  }
+
+  lock_t *c = 
+  bar2(c);
+  return 0;
+}
+
Index: test/Analysis/spinlock_double_lock.c
===
--- /dev/null
+++ test/Analysis/spinlock_double_lock.c
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=magenta.SpinLock -verify %s
+
+typedef unsigned int lock_t;
+
+static lock_t l;
+
+void spin_lock(lock_t *lock);
+void spin_unlock(lock_t *lock);
+int bar();
+
+int foo() {
+  int a = bar();
+  if (a > 0)
+spin_lock();
+  if (a > 10)
+spin_lock(); // expected-warning{{Execution path found where spinlock is locked twice in a row}}
+
+  return 0;
+}
+
Index: test/Analysis/spinlock_correct.c
===
--- /dev/null
+++ test/Analysis/spinlock_correct.c
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=magenta.SpinLock -verify %s
+// expected-no-diagnostics
+
+typedef unsigned int lock_t;
+
+static lock_t l;
+
+void spin_lock(lock_t *lock);
+void spin_unlock(lock_t *lock);
+int bar();
+
+int foo() {
+  int a = bar();
+  if (a > 0) {
+spin_lock();
+  }
+
+  if (a < -10) {
+spin_lock();
+  }
+
+  if (a > 0)
+spin_unlock();
+
+  if (a < -10)
+spin_unlock();
+
+  return 0;
+}
+
Index: lib/StaticAnalyzer/Checkers/SpinLockChecker.cpp
===
--- /dev/null
+++ lib/StaticAnalyzer/Checkers/SpinLockChecker.cpp
@@ -0,0 +1,187 @@
+//== SpinLockChecker.cpp - SpinLock checker -*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+//
+// This defines SpinLockChecker, a check for the Magenta kernel. It
+// checks that there are no execution paths where spinlocks are locked
+// twice in a row, or unlocked twice in a row.
+//
+//===--===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+struct LockInfo {
+
+  enum Kind { Locked, Released } K;
+
+  LockInfo(Kind kind) : K(kind) {}
+
+  bool operator==(const LockInfo ) const { return K == LI.K; }
+
+  void Profile(llvm::FoldingSetNodeID ) const { ID.AddInteger(K); }
+
+  bool isLocked() const { return K == Locked; }
+
+  bool isReleased() const { return K == Released; }
+
+  static LockInfo getLocked() { return LockInfo(Locked); }
+
+  static LockInfo getReleased() { return LockInfo(Released); }
+
+};
+
+}
+
+/// We keep track of the locks in a map. SpinLockMap maps the
+/// memory region of a spinlock to its status (locked, released).
+/// The reason that we keep track of spinlocks as memory region is
+/// that the lock/unlock functions take lock arguments as pointers.
+REGISTER_MAP_WITH_PROGRAMSTATE(SpinLockMap, const MemRegion *, LockInfo)
+
+namespace {
+
+class SpinLockChecker : public Checker {
+
+  /// When facing a spin_unlock function call, check the record of the
+  /// corresponding lock in SpinLockMap and make sure that there are no
+  /// problems such as double unlocks.
+  void 

[PATCH] D26340: [analyzer] Add SpinLockChecker for the Magenta kernel

2016-11-08 Thread Kareem Khazem via cfe-commits
khazem added a comment.

Good to meet you too, thanks for the useful comments and pointers to helpful 
examples! I'm going to update the diff twice: the first one to address your 
first two comments, and the second one to address your last two.


https://reviews.llvm.org/D26340



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26340: [analyzer] Add SpinLockChecker for the Magenta kernel

2016-11-07 Thread Devin Coughlin via cfe-commits
dcoughlin added a comment.

Thanks for upstreaming this! (And it was great to meet you at the developer 
conference.)




Comment at: lib/StaticAnalyzer/Checkers/SpinLockChecker.cpp:61
+
+const ErrorCategoryStr LockInfo::LockErrCategory("Lock Error");
+const FunctionNameStr LockInfo::SpinLockFuncName("spin_lock");

In the LLVM/clang codebase we try very hard to avoid running constructors for 
globals, as this can have adverse effects on startup time. Typically we try to 
lazily initialize things like these or have them refer to constant data that 
the linker will handle automatically (such as a c string constant).

Can these be a C string constant instead? Or can they be instance members of 
the  SpinLockChecker class? (See the note about `CallDescription` below, which 
may be helpful.)



Comment at: lib/StaticAnalyzer/Checkers/SpinLockChecker.cpp:118
+
+  FunctionNameStr CalleeName = Call.getCalleeIdentifier()->getName();
+  if (CalleeName != LockInfo::getSpinLockFuncName() &&

In the analyzer codebase we try to use IdentifierInfo pointers to compare 
identifiers. Since these are interned it lets us perform pointer comparisons 
rather than expensive string comparisons.

There is a `CallDescription` class in `CallEvent.h` that encapsulates this 
logic. You can see an example of how it is used in SimpleStreamChecker.cpp.




Comment at: lib/StaticAnalyzer/Checkers/SpinLockChecker.cpp:182
+  Report->markInteresting(SpinLockLocation);
+  C.emitReport(std::move(Report));
+}

For these kinds of diagnostics it is often very helpful to emit a path note 
indicating where the first unlock was.

To do this, you can add a custom bug report visitor that will get called on 
each node in the path to a diagnostic and emit a note, if appropriate. In this 
case you would look for nodes with calls to unlock taking the same region as 
the one you are now reporting for.

There is an example of how to implement a bug report visitor in 
'SuperDeallocBRVisitor'.



Comment at: lib/StaticAnalyzer/Checkers/SpinLockChecker.cpp:192
+
+  auto Report = llvm::make_unique(
+  *DoubleLockBugType,

It would be good to emit a path note for the first lock, too.


https://reviews.llvm.org/D26340



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26340: [analyzer] Add SpinLockChecker for the Magenta kernel

2016-11-06 Thread Kareem Khazem via cfe-commits
khazem updated this revision to Diff 77005.
khazem added a comment.

Minor edit, the list of libraries in CMakeLists.txt is now in alphabetical 
order.


https://reviews.llvm.org/D26340

Files:
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/CMakeLists.txt
  lib/StaticAnalyzer/Checkers/SpinLockChecker.cpp
  test/Analysis/spinlock_correct.c
  test/Analysis/spinlock_double_lock.c
  test/Analysis/spinlock_double_release.c

Index: test/Analysis/spinlock_double_release.c
===
--- /dev/null
+++ test/Analysis/spinlock_double_release.c
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=magenta.SpinLock -verify %s
+
+typedef unsigned int lock_t;
+
+typedef struct S {
+  int a;
+  lock_t l;
+} S_t;
+
+static S_t st;
+
+void spin_lock(lock_t *lock);
+void spin_unlock(lock_t *lock);
+int bar();
+
+void bar1(lock_t *y) {
+  spin_unlock(y);
+}
+
+void bar2(lock_t *x) {
+  spin_unlock(x); // expected-warning{{Execution path found where spinlock is unlocked twice in a row}}
+}
+
+int foo() {
+  int a = bar();
+  if (a > 0) {
+spin_lock();
+bar1();
+  }
+
+  lock_t *c = 
+  bar2(c);
+  return 0;
+}
+
Index: test/Analysis/spinlock_double_lock.c
===
--- /dev/null
+++ test/Analysis/spinlock_double_lock.c
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=magenta.SpinLock -verify %s
+
+typedef unsigned int lock_t;
+
+static lock_t l;
+
+void spin_lock(lock_t *lock);
+void spin_unlock(lock_t *lock);
+int bar();
+
+int foo() {
+  int a = bar();
+  if (a > 0)
+spin_lock();
+  if (a > 10)
+spin_lock(); // expected-warning{{Execution path found where spinlock is locked twice in a row}}
+
+  return 0;
+}
+
Index: test/Analysis/spinlock_correct.c
===
--- /dev/null
+++ test/Analysis/spinlock_correct.c
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=magenta.SpinLock -verify %s
+// expected-no-diagnostics
+
+typedef unsigned int lock_t;
+
+static lock_t l;
+
+void spin_lock(lock_t *lock);
+void spin_unlock(lock_t *lock);
+int bar();
+
+int foo() {
+  int a = bar();
+  if (a > 0) {
+spin_lock();
+  }
+
+  if (a < -10) {
+spin_lock();
+  }
+
+  if (a > 0)
+spin_unlock();
+
+  if (a < -10)
+spin_unlock();
+
+  return 0;
+}
+
Index: lib/StaticAnalyzer/Checkers/SpinLockChecker.cpp
===
--- /dev/null
+++ lib/StaticAnalyzer/Checkers/SpinLockChecker.cpp
@@ -0,0 +1,198 @@
+//== SpinLockChecker.cpp - SpinLock checker -*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+//
+// This defines SpinLockChecker, a check for the Magenta kernel. It
+// checks that there are no execution paths where spinlocks are locked
+// twice in a row, or unlocked twice in a row.
+//
+//===--===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+typedef llvm::SmallString<16> ErrorCategoryStr;
+typedef llvm::SmallString<32> FunctionNameStr;
+
+struct LockInfo {
+
+  enum Kind { Locked, Released } K;
+
+  LockInfo(Kind kind) : K(kind) {}
+
+  bool operator==(const LockInfo ) const { return K == LI.K; }
+
+  void Profile(llvm::FoldingSetNodeID ) const { ID.AddInteger(K); }
+
+  bool isLocked() const { return K == Locked; }
+
+  bool isReleased() const { return K == Released; }
+
+  static LockInfo getLocked() { return LockInfo(Locked); }
+
+  static LockInfo getReleased() { return LockInfo(Released); }
+
+  static ErrorCategoryStr getLockErrorCategory() { return LockErrCategory; }
+
+  static FunctionNameStr getSpinLockFuncName() { return SpinLockFuncName; }
+
+  static FunctionNameStr getSpinUnlockFuncName() { return SpinUnlockFuncName; }
+
+private:
+  static const ErrorCategoryStr LockErrCategory;
+  static const FunctionNameStr SpinLockFuncName;
+  static const FunctionNameStr SpinUnlockFuncName;
+};
+
+const ErrorCategoryStr LockInfo::LockErrCategory("Lock Error");
+const FunctionNameStr LockInfo::SpinLockFuncName("spin_lock");
+const FunctionNameStr LockInfo::SpinUnlockFuncName("spin_unlock");
+}
+
+/// We keep track of the locks in a map. SpinLockMap maps the
+/// memory region of a spinlock to its status (locked, released).
+/// The reason that we keep track of