Add context manager (which manages code and data block of each script.)
diff --git a/lib/bcc/CodeMemoryManager.cpp b/lib/bcc/CodeMemoryManager.cpp
index 774ddc3..87b99c1 100644
--- a/lib/bcc/CodeMemoryManager.cpp
+++ b/lib/bcc/CodeMemoryManager.cpp
@@ -18,15 +18,14 @@
#include <cutils/log.h>
#include "CodeMemoryManager.h"
+#include "ContextManager.h"
#include "llvm/Support/ErrorHandling.h"
-#include <errno.h>
#include <sys/mman.h>
#include <assert.h>
#include <stddef.h>
-#include <string.h>
#include <map>
#include <string>
@@ -36,9 +35,9 @@
namespace bcc {
-const unsigned int MaxCodeSize = BCC_MMAP_IMG_CODE_SIZE;
+const unsigned int MaxCodeSize = BCC_CONTEXT_CODE_SIZE;
const unsigned int MaxGOTSize = 1 * 1024;
-const unsigned int MaxGlobalVarSize = BCC_MMAP_IMG_DATA_SIZE;
+const unsigned int MaxGlobalVarSize = BCC_CONTEXT_DATA_SIZE;
CodeMemoryManager::CodeMemoryManager()
@@ -47,72 +46,26 @@
reset();
std::string ErrMsg;
- // Try to use fixed address
+ mpCodeMem = allocateContext();
- // Note: If we failed to allocate mpCodeMem at fixed address,
- // the caching mechanism has to either perform relocation or
- // give up. If the caching mechanism gives up, then we have to
- // recompile the bitcode and wasting a lot of time.
-
- for (size_t i = 0; i < BCC_MMAP_IMG_COUNT; ++i) {
- if (Compiler::BccMmapImgAddrTaken[i]) {
- // The address BCC_MMAP_IMG_BEGIN + i * BCC_MMAP_IMG_SIZE has
- // been taken.
- continue;
- }
-
- // Occupy the mmap image address first (No matter allocation
- // success or not. Keep occupying if succeed; otherwise,
- // keep occupying as a mark of failure.)
- Compiler::BccMmapImgAddrTaken[i] = true;
-
- void *currMmapImgAddr =
- reinterpret_cast<void *>(BCC_MMAP_IMG_BEGIN + i * BCC_MMAP_IMG_SIZE);
-
- mpCodeMem = mmap(currMmapImgAddr, BCC_MMAP_IMG_SIZE,
- PROT_READ | PROT_EXEC | PROT_WRITE,
- MAP_PRIVATE | MAP_ANON | MAP_FIXED,
- -1, 0);
-
- if (mpCodeMem == MAP_FAILED) {
- LOGE("Mmap mpCodeMem at %p failed with reason: %s. Retrying ..\n",
- currMmapImgAddr, strerror(errno));
- } else {
- // Good, we have got one mmap image address.
- break;
- }
+ if (!mpCodeMem) {
+ LOGE("Unable to allocate mpCodeMem\n");
+ llvm::report_fatal_error("Failed to allocate memory for emitting "
+ "codes\n" + ErrMsg);
}
- if (!mpCodeMem || mpCodeMem == MAP_FAILED) {
- LOGE("Try to allocate mpCodeMem at arbitary address.\n");
-
- mpCodeMem = mmap(NULL, BCC_MMAP_IMG_SIZE,
- PROT_READ | PROT_EXEC | PROT_WRITE,
- MAP_PRIVATE | MAP_ANON,
- -1, 0);
-
- if (mpCodeMem == MAP_FAILED) {
- LOGE("Unable to mmap mpCodeMem with reason: %s.\n", strerror(errno));
- llvm::report_fatal_error("Failed to allocate memory for emitting "
- "codes\n" + ErrMsg);
- }
- }
-
- LOGI("Mmap mpCodeMem at %p successfully.\n", mpCodeMem);
+ LOGI("Allocate mpCodeMem at %p successfully.\n", mpCodeMem);
// Set global variable pool
- mpGVMem = (void *) ((char *)mpCodeMem + MaxCodeSize);
+ mpGVMem = mpCodeMem + MaxCodeSize;
return;
}
CodeMemoryManager::~CodeMemoryManager() {
- if (mpCodeMem && mpCodeMem != MAP_FAILED) {
- munmap(mpCodeMem, BCC_MMAP_IMG_SIZE);
-
- // TODO(logan): Reset Compiler::BccMmapImgAddrTaken[i] to false, so
- // that the address can be reused.
+ if (mpCodeMem) {
+ deallocateContext(mpCodeMem);
}
mpCodeMem = 0;
diff --git a/lib/bcc/CodeMemoryManager.h b/lib/bcc/CodeMemoryManager.h
index 2c147df..a5e3915 100644
--- a/lib/bcc/CodeMemoryManager.h
+++ b/lib/bcc/CodeMemoryManager.h
@@ -103,8 +103,8 @@
uintptr_t mCurFuncMemIdx;
uintptr_t mCurSGMemIdx;
uintptr_t mCurGVMemIdx;
- void *mpCodeMem;
- void *mpGVMem;
+ char *mpCodeMem;
+ char *mpGVMem;
// GOT Base
uint8_t *mpGOTBase;
diff --git a/lib/bcc/Compiler.cpp b/lib/bcc/Compiler.cpp
index 695d1da..4a1a3ca 100644
--- a/lib/bcc/Compiler.cpp
+++ b/lib/bcc/Compiler.cpp
@@ -65,6 +65,8 @@
#include "Compiler.h"
+#include "ContextManager.h"
+
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/Passes.h"
@@ -98,7 +100,6 @@
#include <errno.h>
#include <sys/file.h>
-#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
@@ -160,8 +161,6 @@
bool Compiler::GlobalInitialized = false;
-bool Compiler::BccMmapImgAddrTaken[BCC_MMAP_IMG_COUNT];
-
// Code generation optimization level for the compiler
llvm::CodeGenOpt::Level Compiler::CodeGenOptLevel;
@@ -527,56 +526,38 @@
long pagesize = sysconf(_SC_PAGESIZE);
if (mCacheHdr->cachedCodeDataAddr % pagesize == 0) {
- void *addr = reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
+ char *addr = reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
- // Try to mmap at cached address directly.
- mCodeDataAddr = (char *) mmap(addr,
- BCC_MMAP_IMG_SIZE,
- PROT_READ | PROT_EXEC | PROT_WRITE,
- MAP_PRIVATE | MAP_FIXED,
- mCacheFd,
- mCacheHdr->codeOffset);
+ // Try to allocate context at cached address directly.
+ mCodeDataAddr = allocateContext(addr, mCacheFd, mCacheHdr->codeOffset);
- if (mCodeDataAddr && mCodeDataAddr != MAP_FAILED) {
- // Cheers! Mapped at the cached address successfully.
-
- // Update the BccMmapImgAddrTaken table (if required)
- if (mCacheHdr->cachedCodeDataAddr >= BCC_MMAP_IMG_BEGIN) {
- size_t offset = mCacheHdr->cachedCodeDataAddr - BCC_MMAP_IMG_BEGIN;
- size_t scriptId = offset / BCC_MMAP_IMG_SIZE;
-
- if ((offset % BCC_MMAP_IMG_SIZE) == 0 &&
- scriptId < BCC_MMAP_IMG_COUNT) {
- if (Compiler::BccMmapImgAddrTaken[scriptId] == true) {
- mCodeDataAddr = (char *) MAP_FAILED;
- } else {
- Compiler::BccMmapImgAddrTaken[scriptId] = true;
- }
- }
- }
+ if (!mCodeDataAddr) {
+ // Unable to allocate at cached address. Give up.
+ flock(mCacheFd, LOCK_UN);
+ goto bail;
+ }
#if 1
- // Check the checksum of code and data
- {
- uint32_t sum = mCacheHdr->checksum;
- uint32_t *ptr = (uint32_t *)mCodeDataAddr;
+ // Check the checksum of code and data
+ {
+ uint32_t sum = mCacheHdr->checksum;
+ uint32_t *ptr = (uint32_t *)mCodeDataAddr;
- for (size_t i = 0; i < BCC_MMAP_IMG_SIZE / sizeof(uint32_t); ++i) {
- sum ^= *ptr++;
- }
-
- if (sum != 0) {
- LOGE("Checksum check failed\n");
- goto bail;
- }
-
- LOGI("Passed checksum even parity verification.\n");
+ for (size_t i = 0; i < BCC_CONTEXT_SIZE / sizeof(uint32_t); ++i) {
+ sum ^= *ptr++;
}
+
+ if (sum != 0) {
+ LOGE("Checksum check failed\n");
+ goto bail;
+ }
+
+ LOGI("Passed checksum even parity verification.\n");
+ }
#endif
- flock(mCacheFd, LOCK_UN);
- return 0; // loadCacheFile succeed!
- }
+ flock(mCacheFd, LOCK_UN);
+ return 0; // loadCacheFile succeed!
}
}
@@ -699,10 +680,8 @@
free(mCacheMapAddr);
}
- if (mCodeDataAddr && mCodeDataAddr != MAP_FAILED) {
- if (munmap(mCodeDataAddr, BCC_MMAP_IMG_SIZE) != 0) {
- LOGE("munmap failed: %s\n", strerror(errno));
- }
+ if (mCodeDataAddr) {
+ deallocateContext(mCodeDataAddr);
}
mCacheMapAddr = NULL;
@@ -1210,10 +1189,8 @@
// mCodeDataAddr and mCacheMapAddr are from loadCacheFile and not
// managed by CodeMemoryManager.
- if (mCodeDataAddr != 0 && mCodeDataAddr != MAP_FAILED) {
- if (munmap(mCodeDataAddr, BCC_MMAP_IMG_SIZE) < 0) {
- LOGE("munmap failed while releasing mCodeDataAddr\n");
- }
+ if (mCodeDataAddr) {
+ deallocateContext(mCodeDataAddr);
}
if (mCacheMapAddr) {
@@ -1393,7 +1370,7 @@
uint32_t sum = 0;
uint32_t *ptr = (uint32_t *)mCodeDataAddr;
- for (size_t i = 0; i < BCC_MMAP_IMG_SIZE / sizeof(uint32_t); ++i) {
+ for (size_t i = 0; i < BCC_CONTEXT_SIZE / sizeof(uint32_t); ++i) {
sum ^= *ptr++;
}
diff --git a/lib/bcc/Compiler.h b/lib/bcc/Compiler.h
index 444d136..ff9f0d6 100644
--- a/lib/bcc/Compiler.h
+++ b/lib/bcc/Compiler.h
@@ -34,14 +34,6 @@
#include <utility>
-#define BCC_MMAP_IMG_BEGIN 0x7e000000
-#define BCC_MMAP_IMG_COUNT 5
-
-#define BCC_MMAP_IMG_CODE_SIZE (128 * 1024)
-#define BCC_MMAP_IMG_DATA_SIZE (128 * 1024)
-#define BCC_MMAP_IMG_SIZE (BCC_MMAP_IMG_CODE_SIZE + BCC_MMAP_IMG_DATA_SIZE)
-
-
namespace llvm {
class LLVMContext;
class Module;
@@ -67,8 +59,6 @@
//
static bool GlobalInitialized;
- static bool BccMmapImgAddrTaken[BCC_MMAP_IMG_COUNT];
-
// If given, this will be the name of the target triple to compile for.
// If not given, the initial values defined in this file will be used.
static std::string Triple;
diff --git a/lib/bcc/ContextManager.cpp b/lib/bcc/ContextManager.cpp
new file mode 100644
index 0000000..897314c
--- /dev/null
+++ b/lib/bcc/ContextManager.cpp
@@ -0,0 +1,144 @@
+/*
+ * copyright 2010, the android open source project
+ *
+ * licensed under the apache license, version 2.0 (the "license");
+ * you may not use this file except in compliance with the license.
+ * you may obtain a copy of the license at
+ *
+ * http://www.apache.org/licenses/license-2.0
+ *
+ * unless required by applicable law or agreed to in writing, software
+ * distributed under the license is distributed on an "as is" basis,
+ * without warranties or conditions of any kind, either express or implied.
+ * see the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+#define LOG_TAG "bcc"
+#include <cutils/log.h>
+
+#include "ContextManager.h"
+
+#include <errno.h>
+#include <sys/mman.h>
+
+#include <stddef.h>
+#include <string.h>
+
+
+namespace {
+ static bool ContextSlotTaken[BCC_CONTEXT_SLOT_COUNT];
+} // namespace anonymous
+
+
+namespace bcc {
+
+char *allocateContext() {
+ // Try to allocate context on the managed context slot.
+ for (size_t i = 0; i < BCC_CONTEXT_SLOT_COUNT; ++i) {
+ if (ContextSlotTaken[i]) {
+ continue;
+ }
+
+ // Take the context slot. (No matter we can mmap or not)
+ ContextSlotTaken[i] = true;
+
+ void *addr = BCC_CONTEXT_FIXED_ADDR + BCC_CONTEXT_SIZE * i;
+
+ // Try to mmap
+ void *result = mmap(addr, BCC_CONTEXT_SIZE,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
+
+ if (result && result != MAP_FAILED) { // Allocated successfully
+ return (char *)result;
+ }
+
+ LOGE("Unable to mmap at %p. Retry ...\n", addr);
+ }
+
+ // No slot available, allocate at arbitary address.
+
+ void *result = mmap(0, BCC_CONTEXT_SIZE,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANON, -1, 0);
+
+ if (!result || result == MAP_FAILED) {
+ LOGE("Unable to mmap. (reason: %s)\n", strerror(errno));
+ return NULL;
+ }
+
+ return (char *)result;
+}
+
+
+char *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.
+ return NULL;
+ }
+
+ unsigned long pagesize = (unsigned long)sysconf(_SC_PAGESIZE);
+
+ if (imageOffset % pagesize > 0) {
+ // Image is not aligned in the cache file.
+ return NULL;
+ }
+
+ if (addr < BCC_CONTEXT_FIXED_ADDR) {
+ // If the suggest address is not at the context slot, then return
+ // NULL as error.
+ return NULL;
+ }
+
+ size_t offset = (size_t)(addr - BCC_CONTEXT_FIXED_ADDR);
+ size_t slot = offset / BCC_CONTEXT_SIZE;
+
+ if (offset % BCC_CONTEXT_SIZE != 0 || slot >= BCC_CONTEXT_SLOT_COUNT) {
+ // Invalid Slot Address (Not aligned or overflow)
+ return NULL;
+ }
+
+ if (ContextSlotTaken[slot]) {
+ // Slot has been taken.
+ return NULL;
+ }
+
+ ContextSlotTaken[slot] = true;
+
+ void *result = mmap(addr, BCC_CONTEXT_SIZE,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE, imageFd, imageOffset);
+
+ return (result && result != MAP_FAILED) ? (char *)result : NULL;
+}
+
+
+void deallocateContext(char *addr) {
+ if (!addr) {
+ return;
+ }
+
+ // Unmap
+ if (munmap(addr, BCC_CONTEXT_SIZE) < 0) {
+ LOGE("Unable to unmap addr %p (reason: %s)\n", addr, strerror(errno));
+ return;
+ }
+
+ // If the address is one of the context slot, then mark such slot
+ // freely available as well.
+ if (addr >= BCC_CONTEXT_FIXED_ADDR) {
+ size_t offset = (size_t)(addr - BCC_CONTEXT_FIXED_ADDR);
+ size_t slot = offset / BCC_CONTEXT_SIZE;
+
+ if (offset % BCC_CONTEXT_SIZE == 0 && slot < BCC_CONTEXT_SLOT_COUNT) {
+ // Give the context slot back.
+ ContextSlotTaken[slot] = false;
+ }
+ }
+}
+
+} // namespace bcc
diff --git a/lib/bcc/ContextManager.h b/lib/bcc/ContextManager.h
new file mode 100644
index 0000000..b6d1a4c
--- /dev/null
+++ b/lib/bcc/ContextManager.h
@@ -0,0 +1,44 @@
+/*
+ * copyright 2010, the android open source project
+ *
+ * licensed under the apache license, version 2.0 (the "license");
+ * you may not use this file except in compliance with the license.
+ * you may obtain a copy of the license at
+ *
+ * http://www.apache.org/licenses/license-2.0
+ *
+ * unless required by applicable law or agreed to in writing, software
+ * distributed under the license is distributed on an "as is" basis,
+ * without warranties or conditions of any kind, either express or implied.
+ * see the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+#ifndef BCC_CONTEXTMANAGER_H
+#define BCC_CONTEXTMANAGER_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 char *allocateContext();
+
+ extern char *allocateContext(char *addr, int imageFd, off_t imageOffset);
+
+ extern void deallocateContext(char *addr);
+
+} // namespace bcc
+
+
+#endif // BCC_CONTEXTMANAGER_H