blob: 0fe9f78d4cfefb1b6098f13754aea3cf0fce6adf [file] [log] [blame]
Loganeb3d12b2010-12-16 06:20:18 +08001/*
2 * copyright 2010, the android open source project
3 *
4 * licensed under the apache license, version 2.0 (the "license");
5 * you may not use this file except in compliance with the license.
6 * you may obtain a copy of the license at
7 *
8 * http://www.apache.org/licenses/license-2.0
9 *
10 * unless required by applicable law or agreed to in writing, software
11 * distributed under the license is distributed on an "as is" basis,
12 * without warranties or conditions of any kind, either express or implied.
13 * see the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17#define LOG_TAG "bcc"
18#include <cutils/log.h>
19
20#include "ContextManager.h"
21
Logan1dc63142011-02-25 17:14:51 +080022#include <llvm/System/Mutex.h>
23#include <llvm/Support/MutexGuard.h>
24
Loganeb3d12b2010-12-16 06:20:18 +080025#include <errno.h>
26#include <sys/mman.h>
Jeff Brown937a0bc2011-01-26 23:20:14 -080027#include <utils/threads.h>
Loganeb3d12b2010-12-16 06:20:18 +080028
29#include <stddef.h>
30#include <string.h>
31
32
Loganeb3d12b2010-12-16 06:20:18 +080033namespace bcc {
34
Logan1dc63142011-02-25 17:14:51 +080035// Starting address for context slots
36char * const ContextManager::ContextFixedAddr = BCC_CONTEXT_FIXED_ADDR_;
37
38// ContextManager singleton object
39ContextManager ContextManager::TheContextManager;
Jeff Brown937a0bc2011-01-26 23:20:14 -080040
Logan42598052011-01-26 22:41:13 +080041
Logan1dc63142011-02-25 17:14:51 +080042ContextManager::ContextManager() {
43 // Initialize context slot occupation table to false
44 for (size_t i = 0; i < ContextSlotCount; ++i) {
45 mContextSlotOccupied[i] = false;
Logan42598052011-01-26 22:41:13 +080046 }
Logan42598052011-01-26 22:41:13 +080047}
48
Logan1dc63142011-02-25 17:14:51 +080049char *ContextManager::allocateContext() {
50 {
51 // Acquire mContextSlotOccupiedLock
52 llvm::MutexGuard Locked(mContextSlotOccupiedLock);
Logan42598052011-01-26 22:41:13 +080053
Logan1dc63142011-02-25 17:14:51 +080054 // Try to allocate context on the managed context slot.
55 for (size_t i = 0; i < ContextSlotCount; ++i) {
56 if (mContextSlotOccupied[i]) {
57 continue;
58 }
Jeff Brown937a0bc2011-01-26 23:20:14 -080059
Logan1dc63142011-02-25 17:14:51 +080060 void *addr = ContextFixedAddr + ContextSize * i;
61 void *result = mmap(addr, ContextSize,
62 PROT_READ | PROT_WRITE | PROT_EXEC,
63 MAP_PRIVATE | MAP_ANON, -1, 0);
64
65 if (result == addr) {
66 LOGI("Allocate bcc context. addr=%p\n", result);
67 mContextSlotOccupied[i] = true;
68 return static_cast<char *>(result);
69 }
70
71 if (result && result != MAP_FAILED) {
72 LOGE("Unable to allocate. suggested=%p, result=%p\n", addr, result);
73 munmap(result, ContextSize);
74 }
75
76 LOGE("Unable to allocate. addr=%p. Retry ...\n", addr);
Loganeb3d12b2010-12-16 06:20:18 +080077 }
Logan1dc63142011-02-25 17:14:51 +080078 // Release mContextSlotOccupiedLock
Loganeb3d12b2010-12-16 06:20:18 +080079 }
80
81 // No slot available, allocate at arbitary address.
Logan1dc63142011-02-25 17:14:51 +080082 void *result = mmap(0, ContextSize, PROT_READ | PROT_WRITE | PROT_EXEC,
Loganeb3d12b2010-12-16 06:20:18 +080083 MAP_PRIVATE | MAP_ANON, -1, 0);
84
85 if (!result || result == MAP_FAILED) {
Loganb1feb382010-12-29 20:37:11 +080086 LOGE("Unable to mmap. (reason: %s)\n", strerror(errno));
Loganeb3d12b2010-12-16 06:20:18 +080087 return NULL;
88 }
89
Loganb1feb382010-12-29 20:37:11 +080090 LOGI("Allocate bcc context. addr=%p\n", result);
Logan1dc63142011-02-25 17:14:51 +080091 return static_cast<char *>(result);
Loganeb3d12b2010-12-16 06:20:18 +080092}
93
94
Logan1dc63142011-02-25 17:14:51 +080095char *ContextManager::allocateContext(char *addr,
96 int imageFd, off_t imageOffset) {
Loganeb3d12b2010-12-16 06:20:18 +080097 // This function should only allocate context when address is an context
98 // slot address. And the image offset is aligned to the pagesize.
99
100 if (imageFd < 0) {
Loganb1feb382010-12-29 20:37:11 +0800101 LOGE("Invalid file descriptor for bcc context image\n");
Loganeb3d12b2010-12-16 06:20:18 +0800102 return NULL;
103 }
104
105 unsigned long pagesize = (unsigned long)sysconf(_SC_PAGESIZE);
106
107 if (imageOffset % pagesize > 0) {
Loganb1feb382010-12-29 20:37:11 +0800108 LOGE("BCC context image offset is not aligned to page size\n");
Loganeb3d12b2010-12-16 06:20:18 +0800109 return NULL;
110 }
111
Jeff Brown937a0bc2011-01-26 23:20:14 -0800112 ssize_t slot = getSlotIndexFromAddress(addr);
113 if (slot < 0) {
Loganb1feb382010-12-29 20:37:11 +0800114 LOGE("Suggested address is not a bcc context slot address\n");
Loganeb3d12b2010-12-16 06:20:18 +0800115 return NULL;
116 }
Loganb1feb382010-12-29 20:37:11 +0800117
Logan1dc63142011-02-25 17:14:51 +0800118 llvm::MutexGuard Locked(mContextSlotOccupiedLock);
119 if (mContextSlotOccupied[slot]) {
Shih-wei Liao39ebe2c2011-01-28 11:22:32 -0800120 LOGW("Suggested bcc context slot has been occupied.\n");
Loganeb3d12b2010-12-16 06:20:18 +0800121 return NULL;
122 }
123
Shih-wei Liao931501a2010-12-16 04:43:04 -0800124 // LOGI("addr=%x, imageFd=%d, imageOffset=%x", addr, imageFd, imageOffset);
Logan1dc63142011-02-25 17:14:51 +0800125 void *result = mmap(addr, ContextSize,
Loganeb3d12b2010-12-16 06:20:18 +0800126 PROT_READ | PROT_WRITE | PROT_EXEC,
127 MAP_PRIVATE, imageFd, imageOffset);
128
Loganb1feb382010-12-29 20:37:11 +0800129 if (!result || result == MAP_FAILED) {
130 LOGE("Unable to allocate. addr=%p\n", addr);
131 return NULL;
132 }
133
Loganf15ede32011-01-01 01:37:22 +0800134 if (result != addr) {
135 LOGE("Unable to allocate at suggested=%p, result=%p\n", addr, result);
Logan1dc63142011-02-25 17:14:51 +0800136 munmap(result, ContextSize);
Loganf15ede32011-01-01 01:37:22 +0800137 return NULL;
138 }
139
Loganb1feb382010-12-29 20:37:11 +0800140 LOGI("Allocate bcc context. addr=%p\n", addr);
Logan1dc63142011-02-25 17:14:51 +0800141 mContextSlotOccupied[slot] = true;
Loganb1feb382010-12-29 20:37:11 +0800142 return static_cast<char *>(result);
Loganeb3d12b2010-12-16 06:20:18 +0800143}
144
145
Logan1dc63142011-02-25 17:14:51 +0800146void ContextManager::deallocateContext(char *addr) {
Loganeb3d12b2010-12-16 06:20:18 +0800147 if (!addr) {
148 return;
149 }
150
Logan1dc63142011-02-25 17:14:51 +0800151 llvm::MutexGuard Locked(mContextSlotOccupiedLock);
Jeff Brown937a0bc2011-01-26 23:20:14 -0800152
Loganb1feb382010-12-29 20:37:11 +0800153 LOGI("Deallocate bcc context. addr=%p\n", addr);
Logan069b3312010-12-31 18:31:15 +0800154
Loganeb3d12b2010-12-16 06:20:18 +0800155 // Unmap
Logan1dc63142011-02-25 17:14:51 +0800156 if (munmap(addr, ContextSize) < 0) {
Loganb1feb382010-12-29 20:37:11 +0800157 LOGE("Unable to unmap. addr=%p (reason: %s)\n", addr, strerror(errno));
Loganeb3d12b2010-12-16 06:20:18 +0800158 return;
159 }
160
161 // If the address is one of the context slot, then mark such slot
162 // freely available as well.
Jeff Brown937a0bc2011-01-26 23:20:14 -0800163 ssize_t slot = getSlotIndexFromAddress(addr);
164 if (slot >= 0) {
165 // Give the context slot back.
Logan1dc63142011-02-25 17:14:51 +0800166 mContextSlotOccupied[slot] = false;
Loganeb3d12b2010-12-16 06:20:18 +0800167 }
168}
169
Logan1dc63142011-02-25 17:14:51 +0800170
Logan96d250e2011-02-28 01:25:26 +0800171bool ContextManager::isManagingContext(char *addr) const {
Logan1dc63142011-02-25 17:14:51 +0800172 ssize_t slot = getSlotIndexFromAddress(addr);
173
174 if (slot < 0) {
175 return false;
176 }
177
178 llvm::MutexGuard Locked(mContextSlotOccupiedLock);
179 return mContextSlotOccupied[slot];
180}
181
182
183ssize_t ContextManager::getSlotIndexFromAddress(char *addr) {
184 if (addr >= ContextFixedAddr) {
185 size_t offset = (size_t)(addr - ContextFixedAddr);
186 if (offset % ContextSize == 0) {
187 size_t slot = offset / ContextSize;
188 if (slot < ContextSlotCount) {
189 return slot;
190 }
191 }
192 }
193 return -1;
194}
195
196
197
Loganeb3d12b2010-12-16 06:20:18 +0800198} // namespace bcc