blob: e48048077d25bf192ac50958465a630b2f086f3b [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
22#include <errno.h>
23#include <sys/mman.h>
Jeff Brown937a0bc2011-01-26 23:20:14 -080024#include <utils/threads.h>
Loganeb3d12b2010-12-16 06:20:18 +080025
26#include <stddef.h>
27#include <string.h>
28
29
30namespace {
31 static bool ContextSlotTaken[BCC_CONTEXT_SLOT_COUNT];
32} // namespace anonymous
33
34
35namespace bcc {
36
Jeff Brown937a0bc2011-01-26 23:20:14 -080037static android::Mutex gContextLock;
38
Logan42598052011-01-26 22:41:13 +080039
40ssize_t getSlotIndexFromAddress(char *addr) {
41 if (addr >= BCC_CONTEXT_FIXED_ADDR) {
42 size_t offset = (size_t)(addr - BCC_CONTEXT_FIXED_ADDR);
43 if (offset % BCC_CONTEXT_SIZE == 0) {
44 size_t slot = offset / BCC_CONTEXT_SIZE;
45 if (slot < BCC_CONTEXT_SLOT_COUNT) {
46 return slot;
47 }
48 }
49 }
50 return -1;
51}
52
53
Loganeb3d12b2010-12-16 06:20:18 +080054char *allocateContext() {
Jeff Brown937a0bc2011-01-26 23:20:14 -080055 android::AutoMutex _l(gContextLock);
56
Loganeb3d12b2010-12-16 06:20:18 +080057 // Try to allocate context on the managed context slot.
58 for (size_t i = 0; i < BCC_CONTEXT_SLOT_COUNT; ++i) {
59 if (ContextSlotTaken[i]) {
60 continue;
61 }
62
Loganeb3d12b2010-12-16 06:20:18 +080063 // Try to mmap
Jeff Brown937a0bc2011-01-26 23:20:14 -080064 void *addr = BCC_CONTEXT_FIXED_ADDR + BCC_CONTEXT_SIZE * i;
Loganeb3d12b2010-12-16 06:20:18 +080065 void *result = mmap(addr, BCC_CONTEXT_SIZE,
66 PROT_READ | PROT_WRITE | PROT_EXEC,
Loganf15ede32011-01-01 01:37:22 +080067 MAP_PRIVATE | MAP_ANON, -1, 0);
Loganeb3d12b2010-12-16 06:20:18 +080068
Loganb1feb382010-12-29 20:37:11 +080069 if (result == addr) {
70 LOGI("Allocate bcc context. addr=%p\n", result);
Jeff Brown937a0bc2011-01-26 23:20:14 -080071 ContextSlotTaken[i] = true;
Loganb1feb382010-12-29 20:37:11 +080072 return static_cast<char *>(result);
Loganeb3d12b2010-12-16 06:20:18 +080073 }
74
Loganf15ede32011-01-01 01:37:22 +080075 if (result && result != MAP_FAILED) {
Loganb1feb382010-12-29 20:37:11 +080076 LOGE("Unable to allocate. suggested=%p, result=%p\n", addr, result);
Loganf15ede32011-01-01 01:37:22 +080077 munmap(result, BCC_CONTEXT_SIZE);
78 }
79
Loganb1feb382010-12-29 20:37:11 +080080 LOGE("Unable to allocate. addr=%p. Retry ...\n", addr);
Loganeb3d12b2010-12-16 06:20:18 +080081 }
82
83 // No slot available, allocate at arbitary address.
84
85 void *result = mmap(0, BCC_CONTEXT_SIZE,
86 PROT_READ | PROT_WRITE | PROT_EXEC,
87 MAP_PRIVATE | MAP_ANON, -1, 0);
88
89 if (!result || result == MAP_FAILED) {
Loganb1feb382010-12-29 20:37:11 +080090 LOGE("Unable to mmap. (reason: %s)\n", strerror(errno));
Loganeb3d12b2010-12-16 06:20:18 +080091 return NULL;
92 }
93
Loganb1feb382010-12-29 20:37:11 +080094 LOGI("Allocate bcc context. addr=%p\n", result);
Loganeb3d12b2010-12-16 06:20:18 +080095 return (char *)result;
96}
97
98
99char *allocateContext(char *addr, int imageFd, off_t imageOffset) {
Jeff Brown937a0bc2011-01-26 23:20:14 -0800100 android::AutoMutex _l(gContextLock);
101
Loganeb3d12b2010-12-16 06:20:18 +0800102 // This function should only allocate context when address is an context
103 // slot address. And the image offset is aligned to the pagesize.
104
105 if (imageFd < 0) {
106 // Invalid file descriptor.
Loganb1feb382010-12-29 20:37:11 +0800107 LOGE("Invalid file descriptor for bcc context image\n");
Loganeb3d12b2010-12-16 06:20:18 +0800108 return NULL;
109 }
110
111 unsigned long pagesize = (unsigned long)sysconf(_SC_PAGESIZE);
112
113 if (imageOffset % pagesize > 0) {
Loganb1feb382010-12-29 20:37:11 +0800114 LOGE("BCC context image offset is not aligned to page size\n");
Loganeb3d12b2010-12-16 06:20:18 +0800115 return NULL;
116 }
117
Jeff Brown937a0bc2011-01-26 23:20:14 -0800118 ssize_t slot = getSlotIndexFromAddress(addr);
119 if (slot < 0) {
Loganb1feb382010-12-29 20:37:11 +0800120 LOGE("Suggested address is not a bcc context slot address\n");
Loganeb3d12b2010-12-16 06:20:18 +0800121 return NULL;
122 }
Loganb1feb382010-12-29 20:37:11 +0800123
Loganeb3d12b2010-12-16 06:20:18 +0800124 if (ContextSlotTaken[slot]) {
Shih-wei Liao39ebe2c2011-01-28 11:22:32 -0800125 LOGW("Suggested bcc context slot has been occupied.\n");
Loganeb3d12b2010-12-16 06:20:18 +0800126 return NULL;
127 }
128
Shih-wei Liao931501a2010-12-16 04:43:04 -0800129 // LOGI("addr=%x, imageFd=%d, imageOffset=%x", addr, imageFd, imageOffset);
Loganeb3d12b2010-12-16 06:20:18 +0800130 void *result = mmap(addr, BCC_CONTEXT_SIZE,
131 PROT_READ | PROT_WRITE | PROT_EXEC,
132 MAP_PRIVATE, imageFd, imageOffset);
133
Loganb1feb382010-12-29 20:37:11 +0800134 if (!result || result == MAP_FAILED) {
135 LOGE("Unable to allocate. addr=%p\n", addr);
136 return NULL;
137 }
138
Loganf15ede32011-01-01 01:37:22 +0800139 if (result != addr) {
140 LOGE("Unable to allocate at suggested=%p, result=%p\n", addr, result);
141 munmap(result, BCC_CONTEXT_SIZE);
142 return NULL;
143 }
144
Loganb1feb382010-12-29 20:37:11 +0800145 LOGI("Allocate bcc context. addr=%p\n", addr);
Jeff Brown937a0bc2011-01-26 23:20:14 -0800146 ContextSlotTaken[slot] = true;
Loganb1feb382010-12-29 20:37:11 +0800147 return static_cast<char *>(result);
Loganeb3d12b2010-12-16 06:20:18 +0800148}
149
150
151void deallocateContext(char *addr) {
152 if (!addr) {
153 return;
154 }
155
Jeff Brown937a0bc2011-01-26 23:20:14 -0800156 android::AutoMutex _l(gContextLock);
157
Loganb1feb382010-12-29 20:37:11 +0800158 LOGI("Deallocate bcc context. addr=%p\n", addr);
Logan069b3312010-12-31 18:31:15 +0800159
Loganeb3d12b2010-12-16 06:20:18 +0800160 // Unmap
161 if (munmap(addr, BCC_CONTEXT_SIZE) < 0) {
Loganb1feb382010-12-29 20:37:11 +0800162 LOGE("Unable to unmap. addr=%p (reason: %s)\n", addr, strerror(errno));
Loganeb3d12b2010-12-16 06:20:18 +0800163 return;
164 }
165
166 // If the address is one of the context slot, then mark such slot
167 // freely available as well.
Jeff Brown937a0bc2011-01-26 23:20:14 -0800168 ssize_t slot = getSlotIndexFromAddress(addr);
169 if (slot >= 0) {
170 // Give the context slot back.
171 ContextSlotTaken[slot] = false;
Loganeb3d12b2010-12-16 06:20:18 +0800172 }
173}
174
175} // namespace bcc