Refine ContextManager

- Add isManagingContext API
- Remove global lock and global variable (use Singleton instead)
- Encapsulate getSlotIndexFromAddress API
- Extract configurable define to Config.h
diff --git a/lib/bcc/ContextManager.cpp b/lib/bcc/ContextManager.cpp
index e480480..16fbcf1 100644
--- a/lib/bcc/ContextManager.cpp
+++ b/lib/bcc/ContextManager.cpp
@@ -19,6 +19,9 @@
 
 #include "ContextManager.h"
 
+#include <llvm/System/Mutex.h>
+#include <llvm/Support/MutexGuard.h>
+
 #include <errno.h>
 #include <sys/mman.h>
 #include <utils/threads.h>
@@ -27,63 +30,56 @@
 #include <string.h>
 
 
-namespace {
-  static bool ContextSlotTaken[BCC_CONTEXT_SLOT_COUNT];
-} // namespace anonymous
-
-
 namespace bcc {
 
-static android::Mutex gContextLock;
+// Starting address for context slots
+char * const ContextManager::ContextFixedAddr = BCC_CONTEXT_FIXED_ADDR_;
+
+// ContextManager singleton object
+ContextManager ContextManager::TheContextManager;
 
 
-ssize_t getSlotIndexFromAddress(char *addr) {
-  if (addr >= BCC_CONTEXT_FIXED_ADDR) {
-    size_t offset = (size_t)(addr - BCC_CONTEXT_FIXED_ADDR);
-    if (offset % BCC_CONTEXT_SIZE == 0) {
-      size_t slot = offset / BCC_CONTEXT_SIZE;
-      if (slot < BCC_CONTEXT_SLOT_COUNT) {
-        return slot;
-      }
-    }
+ContextManager::ContextManager() {
+  // Initialize context slot occupation table to false
+  for (size_t i = 0; i < ContextSlotCount; ++i) {
+    mContextSlotOccupied[i] = false;
   }
-  return -1;
 }
 
+char *ContextManager::allocateContext() {
+  {
+    // Acquire mContextSlotOccupiedLock
+    llvm::MutexGuard Locked(mContextSlotOccupiedLock);
 
-char *allocateContext() {
-  android::AutoMutex _l(gContextLock);
+    // Try to allocate context on the managed context slot.
+    for (size_t i = 0; i < ContextSlotCount; ++i) {
+      if (mContextSlotOccupied[i]) {
+        continue;
+      }
 
-  // Try to allocate context on the managed context slot.
-  for (size_t i = 0; i < BCC_CONTEXT_SLOT_COUNT; ++i) {
-    if (ContextSlotTaken[i]) {
-      continue;
+      void *addr = ContextFixedAddr + ContextSize * i;
+      void *result = mmap(addr, ContextSize,
+                          PROT_READ | PROT_WRITE | PROT_EXEC,
+                          MAP_PRIVATE | MAP_ANON, -1, 0);
+
+      if (result == addr) {
+        LOGI("Allocate bcc context. addr=%p\n", result);
+        mContextSlotOccupied[i] = true;
+        return static_cast<char *>(result);
+      }
+
+      if (result && result != MAP_FAILED) {
+        LOGE("Unable to allocate. suggested=%p, result=%p\n", addr, result);
+        munmap(result, ContextSize);
+      }
+
+      LOGE("Unable to allocate. addr=%p.  Retry ...\n", addr);
     }
-
-    // Try to mmap
-    void *addr = BCC_CONTEXT_FIXED_ADDR + BCC_CONTEXT_SIZE * i;
-    void *result = mmap(addr, BCC_CONTEXT_SIZE,
-                        PROT_READ | PROT_WRITE | PROT_EXEC,
-                        MAP_PRIVATE | MAP_ANON, -1, 0);
-
-    if (result == addr) {
-      LOGI("Allocate bcc context. addr=%p\n", result);
-      ContextSlotTaken[i] = true;
-      return static_cast<char *>(result);
-    }
-
-    if (result && result != MAP_FAILED) {
-      LOGE("Unable to allocate. suggested=%p, result=%p\n", addr, result);
-      munmap(result, BCC_CONTEXT_SIZE);
-    }
-
-    LOGE("Unable to allocate. addr=%p.  Retry ...\n", addr);
+    // Release mContextSlotOccupiedLock
   }
 
   // No slot available, allocate at arbitary address.
-
-  void *result = mmap(0, BCC_CONTEXT_SIZE,
-                      PROT_READ | PROT_WRITE | PROT_EXEC,
+  void *result = mmap(0, ContextSize, PROT_READ | PROT_WRITE | PROT_EXEC,
                       MAP_PRIVATE | MAP_ANON, -1, 0);
 
   if (!result || result == MAP_FAILED) {
@@ -92,18 +88,16 @@
   }
 
   LOGI("Allocate bcc context. addr=%p\n", result);
-  return (char *)result;
+  return static_cast<char *>(result);
 }
 
 
-char *allocateContext(char *addr, int imageFd, off_t imageOffset) {
-  android::AutoMutex _l(gContextLock);
-
+char *ContextManager::allocateContext(char *addr,
+                                      int imageFd, off_t imageOffset) {
   // This function should only allocate context when address is an context
   // slot address.  And the image offset is aligned to the pagesize.
 
   if (imageFd < 0) {
-    // Invalid file descriptor.
     LOGE("Invalid file descriptor for bcc context image\n");
     return NULL;
   }
@@ -121,13 +115,14 @@
     return NULL;
   }
 
-  if (ContextSlotTaken[slot]) {
+  llvm::MutexGuard Locked(mContextSlotOccupiedLock);
+  if (mContextSlotOccupied[slot]) {
     LOGW("Suggested bcc context slot has been occupied.\n");
     return NULL;
   }
 
   // LOGI("addr=%x, imageFd=%d, imageOffset=%x", addr, imageFd, imageOffset);
-  void *result = mmap(addr, BCC_CONTEXT_SIZE,
+  void *result = mmap(addr, ContextSize,
                       PROT_READ | PROT_WRITE | PROT_EXEC,
                       MAP_PRIVATE, imageFd, imageOffset);
 
@@ -138,27 +133,27 @@
 
   if (result != addr) {
     LOGE("Unable to allocate at suggested=%p, result=%p\n", addr, result);
-    munmap(result, BCC_CONTEXT_SIZE);
+    munmap(result, ContextSize);
     return NULL;
   }
 
   LOGI("Allocate bcc context. addr=%p\n", addr);
-  ContextSlotTaken[slot] = true;
+  mContextSlotOccupied[slot] = true;
   return static_cast<char *>(result);
 }
 
 
-void deallocateContext(char *addr) {
+void ContextManager::deallocateContext(char *addr) {
   if (!addr) {
     return;
   }
 
-  android::AutoMutex _l(gContextLock);
+  llvm::MutexGuard Locked(mContextSlotOccupiedLock);
 
   LOGI("Deallocate bcc context. addr=%p\n", addr);
 
   // Unmap
-  if (munmap(addr, BCC_CONTEXT_SIZE) < 0) {
+  if (munmap(addr, ContextSize) < 0) {
     LOGE("Unable to unmap. addr=%p (reason: %s)\n", addr, strerror(errno));
     return;
   }
@@ -168,8 +163,36 @@
   ssize_t slot = getSlotIndexFromAddress(addr);
   if (slot >= 0) {
     // Give the context slot back.
-    ContextSlotTaken[slot] = false;
+    mContextSlotOccupied[slot] = false;
   }
 }
 
+
+bool ContextManager::isManagingContext(char *addr) {
+  ssize_t slot = getSlotIndexFromAddress(addr);
+
+  if (slot < 0) {
+    return false;
+  }
+
+  llvm::MutexGuard Locked(mContextSlotOccupiedLock);
+  return mContextSlotOccupied[slot];
+}
+
+
+ssize_t ContextManager::getSlotIndexFromAddress(char *addr) {
+  if (addr >= ContextFixedAddr) {
+    size_t offset = (size_t)(addr - ContextFixedAddr);
+    if (offset % ContextSize == 0) {
+      size_t slot = offset / ContextSize;
+      if (slot < ContextSlotCount) {
+        return slot;
+      }
+    }
+  }
+  return -1;
+}
+
+
+
 } // namespace bcc