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/CacheReader.cpp b/lib/bcc/CacheReader.cpp
index a820053..7288b19 100644
--- a/lib/bcc/CacheReader.cpp
+++ b/lib/bcc/CacheReader.cpp
@@ -101,7 +101,7 @@
mFileSize = stfile.st_size;
if (mFileSize < (off_t)sizeof(OBCC_Header) ||
- mFileSize < (off_t)BCC_CONTEXT_SIZE) {
+ mFileSize < (off_t)ContextManager::ContextSize) {
LOGE("Cache file is too small to be correct.\n");
return false;
}
@@ -215,7 +215,8 @@
#undef CHECK_SECTION_OFFSET
if (mFileSize < mpHeader->context_offset ||
- mFileSize < mpHeader->context_offset + BCC_CONTEXT_SIZE) {
+ mFileSize < (off_t)mpHeader->context_offset +
+ (off_t)ContextManager::ContextSize) {
LOGE("context section overflow.\n");
return false;
}
@@ -410,9 +411,10 @@
bool CacheReader::readContext() {
- mpResult->mContext = allocateContext(mpHeader->context_cached_addr,
- mFile->getFD(),
- mpHeader->context_offset);
+ mpResult->mContext =
+ ContextManager::get().allocateContext(mpHeader->context_cached_addr,
+ mFile->getFD(),
+ mpHeader->context_offset);
if (!mpResult->mContext) {
// Unable to allocate at cached address. Give up.
@@ -431,7 +433,7 @@
uint32_t sum = mpHeader->context_parity_checksum;
uint32_t *ptr = reinterpret_cast<uint32_t *>(mpResult->mContext);
- for (size_t i = 0; i < BCC_CONTEXT_SIZE / sizeof(uint32_t); ++i) {
+ for (size_t i = 0; i < ContextManager::ContextSize / sizeof(uint32_t); ++i) {
sum ^= *ptr++;
}
diff --git a/lib/bcc/CacheWriter.cpp b/lib/bcc/CacheWriter.cpp
index 27ffd6d..b0971ba 100644
--- a/lib/bcc/CacheWriter.cpp
+++ b/lib/bcc/CacheWriter.cpp
@@ -375,7 +375,7 @@
uint32_t sum = 0;
uint32_t *ptr = reinterpret_cast<uint32_t *>(mpOwner->getContext());
- for (size_t i = 0; i < BCC_CONTEXT_SIZE / sizeof(uint32_t); ++i) {
+ for (size_t i = 0; i < ContextManager::ContextSize / sizeof(uint32_t); ++i) {
sum ^= *ptr++;
}
@@ -416,7 +416,8 @@
WRITE_SECTION_SIMPLE(func_table, mpFuncTableSection);
WRITE_SECTION_SIMPLE(object_slot_list, mpObjectSlotSection);
- WRITE_SECTION(context, mpHeaderSection->context_offset, BCC_CONTEXT_SIZE,
+ WRITE_SECTION(context, mpHeaderSection->context_offset,
+ ContextManager::ContextSize,
mpOwner->getContext());
#undef WRITE_SECTION_SIMPLE
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
diff --git a/lib/bcc/ContextManager.h b/lib/bcc/ContextManager.h
index 461caff..0060012 100644
--- a/lib/bcc/ContextManager.h
+++ b/lib/bcc/ContextManager.h
@@ -17,30 +17,57 @@
#ifndef BCC_CONTEXTMANAGER_H
#define BCC_CONTEXTMANAGER_H
+#include <Config.h>
+
+#include <llvm/System/Mutex.h>
+
#include <stddef.h>
-#include <unistd.h>
-
-
-#define BCC_CONTEXT_FIXED_ADDR (reinterpret_cast<char *>(0x7e000000))
-#define BCC_CONTEXT_SLOT_COUNT 8
-
-#define BCC_CONTEXT_CODE_SIZE (128 * 1024)
-#define BCC_CONTEXT_DATA_SIZE (128 * 1024)
-#define BCC_CONTEXT_SIZE (BCC_CONTEXT_CODE_SIZE + BCC_CONTEXT_DATA_SIZE)
-
namespace bcc {
- extern ssize_t getSlotIndexFromAddress(char *addr);
+ class ContextManager {
+ public:
+ // Starting address of context slot address space
+ static char * const ContextFixedAddr;
- extern char *allocateContext();
+ // Number of the context slots
+ static size_t const ContextSlotCount = BCC_CONTEXT_SLOT_COUNT_;
- extern char *allocateContext(char *addr, int imageFd, off_t imageOffset);
+ // Context size
+ static size_t const ContextCodeSize = BCC_CONTEXT_CODE_SIZE_;
+ static size_t const ContextDataSize = BCC_CONTEXT_DATA_SIZE_;
+ static size_t const ContextSize = ContextCodeSize + ContextDataSize;
- extern void deallocateContext(char *addr);
+ private:
+ // Context manager singleton
+ static ContextManager TheContextManager;
+
+ private:
+ // Mutex lock for context slot occupation table
+ llvm::sys::Mutex mContextSlotOccupiedLock;
+
+ // Context slot occupation table
+ bool mContextSlotOccupied[ContextSlotCount];
+
+ ContextManager();
+
+ public:
+ static ContextManager &get() {
+ return TheContextManager;
+ }
+
+ char *allocateContext();
+ char *allocateContext(char *addr, int imageFd, off_t imageOffset);
+ void deallocateContext(char *addr);
+
+ bool isManagingContext(char *addr);
+
+ private:
+ static ssize_t getSlotIndexFromAddress(char *addr);
+
+ };
} // namespace bcc
-
#endif // BCC_CONTEXTMANAGER_H
diff --git a/lib/bcc/Script.cpp b/lib/bcc/Script.cpp
index e8dd4a3..34fe4f5 100644
--- a/lib/bcc/Script.cpp
+++ b/lib/bcc/Script.cpp
@@ -300,10 +300,9 @@
// Note: If the address of the context is not in the context slot, then
// we don't have to cache it.
- char *addr = getContext();
-
if (mCachePath &&
- !mIsContextSlotNotAvail && getSlotIndexFromAddress(addr) >= 0 &&
+ !mIsContextSlotNotAvail &&
+ ContextManager::get().isManagingContext(getContext()) &&
!getBooleanProp("debug.bcc.nocache")) {
FileHandle file;
diff --git a/lib/bcc/ScriptCached.cpp b/lib/bcc/ScriptCached.cpp
index 1003163..183e552 100644
--- a/lib/bcc/ScriptCached.cpp
+++ b/lib/bcc/ScriptCached.cpp
@@ -30,7 +30,7 @@
ScriptCached::~ScriptCached() {
// Deallocate the bcc script context
if (mContext) {
- deallocateContext(mContext);
+ ContextManager::get().deallocateContext(mContext);
}
// Deallocate string pool, exported var list, exported func list
diff --git a/lib/bcc/ScriptCompiled.cpp b/lib/bcc/ScriptCompiled.cpp
index 5fd45b6..7aa29f1 100644
--- a/lib/bcc/ScriptCompiled.cpp
+++ b/lib/bcc/ScriptCompiled.cpp
@@ -27,7 +27,7 @@
ScriptCompiled::~ScriptCompiled() {
// Deallocate the BCC context
if (mContext) {
- deallocateContext(mContext);
+ ContextManager::get().deallocateContext(mContext);
}
// Delete the emitted function information