blob: 8d173c1966d8e4c0caad2f20238725ee191ab534 [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
Loganeb3d12b2010-12-16 06:20:18 +080039char *allocateContext() {
Jeff Brown937a0bc2011-01-26 23:20:14 -080040 android::AutoMutex _l(gContextLock);
41
Loganeb3d12b2010-12-16 06:20:18 +080042 // Try to allocate context on the managed context slot.
43 for (size_t i = 0; i < BCC_CONTEXT_SLOT_COUNT; ++i) {
44 if (ContextSlotTaken[i]) {
45 continue;
46 }
47
Loganeb3d12b2010-12-16 06:20:18 +080048 // Try to mmap
Jeff Brown937a0bc2011-01-26 23:20:14 -080049 void *addr = BCC_CONTEXT_FIXED_ADDR + BCC_CONTEXT_SIZE * i;
Loganeb3d12b2010-12-16 06:20:18 +080050 void *result = mmap(addr, BCC_CONTEXT_SIZE,
51 PROT_READ | PROT_WRITE | PROT_EXEC,
Loganf15ede32011-01-01 01:37:22 +080052 MAP_PRIVATE | MAP_ANON, -1, 0);
Loganeb3d12b2010-12-16 06:20:18 +080053
Loganb1feb382010-12-29 20:37:11 +080054 if (result == addr) {
55 LOGI("Allocate bcc context. addr=%p\n", result);
Jeff Brown937a0bc2011-01-26 23:20:14 -080056 ContextSlotTaken[i] = true;
Loganb1feb382010-12-29 20:37:11 +080057 return static_cast<char *>(result);
Loganeb3d12b2010-12-16 06:20:18 +080058 }
59
Loganf15ede32011-01-01 01:37:22 +080060 if (result && result != MAP_FAILED) {
Loganb1feb382010-12-29 20:37:11 +080061 LOGE("Unable to allocate. suggested=%p, result=%p\n", addr, result);
Loganf15ede32011-01-01 01:37:22 +080062 munmap(result, BCC_CONTEXT_SIZE);
63 }
64
Loganb1feb382010-12-29 20:37:11 +080065 LOGE("Unable to allocate. addr=%p. Retry ...\n", addr);
Loganeb3d12b2010-12-16 06:20:18 +080066 }
67
68 // No slot available, allocate at arbitary address.
69
70 void *result = mmap(0, BCC_CONTEXT_SIZE,
71 PROT_READ | PROT_WRITE | PROT_EXEC,
72 MAP_PRIVATE | MAP_ANON, -1, 0);
73
74 if (!result || result == MAP_FAILED) {
Loganb1feb382010-12-29 20:37:11 +080075 LOGE("Unable to mmap. (reason: %s)\n", strerror(errno));
Loganeb3d12b2010-12-16 06:20:18 +080076 return NULL;
77 }
78
Loganb1feb382010-12-29 20:37:11 +080079 LOGI("Allocate bcc context. addr=%p\n", result);
Loganeb3d12b2010-12-16 06:20:18 +080080 return (char *)result;
81}
82
Jeff Brown937a0bc2011-01-26 23:20:14 -080083static ssize_t getSlotIndexFromAddress(char* addr) {
84 if (addr >= BCC_CONTEXT_FIXED_ADDR) {
85 size_t offset = (size_t)(addr - BCC_CONTEXT_FIXED_ADDR);
86 if (offset % BCC_CONTEXT_SIZE == 0) {
87 size_t slot = offset / BCC_CONTEXT_SIZE;
88 if (slot < BCC_CONTEXT_SLOT_COUNT) {
89 return slot;
90 }
91 }
92 }
93 return -1;
94}
Loganeb3d12b2010-12-16 06:20:18 +080095
96char *allocateContext(char *addr, int imageFd, off_t imageOffset) {
Jeff Brown937a0bc2011-01-26 23:20:14 -080097 android::AutoMutex _l(gContextLock);
98
Loganeb3d12b2010-12-16 06:20:18 +080099 // This function should only allocate context when address is an context
100 // slot address. And the image offset is aligned to the pagesize.
101
102 if (imageFd < 0) {
103 // Invalid file descriptor.
Loganb1feb382010-12-29 20:37:11 +0800104 LOGE("Invalid file descriptor for bcc context image\n");
Loganeb3d12b2010-12-16 06:20:18 +0800105 return NULL;
106 }
107
108 unsigned long pagesize = (unsigned long)sysconf(_SC_PAGESIZE);
109
110 if (imageOffset % pagesize > 0) {
Loganb1feb382010-12-29 20:37:11 +0800111 LOGE("BCC context image offset is not aligned to page size\n");
Loganeb3d12b2010-12-16 06:20:18 +0800112 return NULL;
113 }
114
Jeff Brown937a0bc2011-01-26 23:20:14 -0800115 ssize_t slot = getSlotIndexFromAddress(addr);
116 if (slot < 0) {
Loganb1feb382010-12-29 20:37:11 +0800117 LOGE("Suggested address is not a bcc context slot address\n");
Loganeb3d12b2010-12-16 06:20:18 +0800118 return NULL;
119 }
Loganb1feb382010-12-29 20:37:11 +0800120
Loganeb3d12b2010-12-16 06:20:18 +0800121 if (ContextSlotTaken[slot]) {
Shih-wei Liao39ebe2c2011-01-28 11:22:32 -0800122 LOGW("Suggested bcc context slot has been occupied.\n");
Loganeb3d12b2010-12-16 06:20:18 +0800123 return NULL;
124 }
125
Shih-wei Liao931501a2010-12-16 04:43:04 -0800126 // LOGI("addr=%x, imageFd=%d, imageOffset=%x", addr, imageFd, imageOffset);
Loganeb3d12b2010-12-16 06:20:18 +0800127 void *result = mmap(addr, BCC_CONTEXT_SIZE,
128 PROT_READ | PROT_WRITE | PROT_EXEC,
129 MAP_PRIVATE, imageFd, imageOffset);
130
Loganb1feb382010-12-29 20:37:11 +0800131 if (!result || result == MAP_FAILED) {
132 LOGE("Unable to allocate. addr=%p\n", addr);
133 return NULL;
134 }
135
Loganf15ede32011-01-01 01:37:22 +0800136 if (result != addr) {
137 LOGE("Unable to allocate at suggested=%p, result=%p\n", addr, result);
138 munmap(result, BCC_CONTEXT_SIZE);
139 return NULL;
140 }
141
Loganb1feb382010-12-29 20:37:11 +0800142 LOGI("Allocate bcc context. addr=%p\n", addr);
Jeff Brown937a0bc2011-01-26 23:20:14 -0800143 ContextSlotTaken[slot] = true;
Loganb1feb382010-12-29 20:37:11 +0800144 return static_cast<char *>(result);
Loganeb3d12b2010-12-16 06:20:18 +0800145}
146
147
148void deallocateContext(char *addr) {
149 if (!addr) {
150 return;
151 }
152
Jeff Brown937a0bc2011-01-26 23:20:14 -0800153 android::AutoMutex _l(gContextLock);
154
Loganb1feb382010-12-29 20:37:11 +0800155 LOGI("Deallocate bcc context. addr=%p\n", addr);
Logan069b3312010-12-31 18:31:15 +0800156
Loganeb3d12b2010-12-16 06:20:18 +0800157 // Unmap
158 if (munmap(addr, BCC_CONTEXT_SIZE) < 0) {
Loganb1feb382010-12-29 20:37:11 +0800159 LOGE("Unable to unmap. addr=%p (reason: %s)\n", addr, strerror(errno));
Loganeb3d12b2010-12-16 06:20:18 +0800160 return;
161 }
162
163 // If the address is one of the context slot, then mark such slot
164 // freely available as well.
Jeff Brown937a0bc2011-01-26 23:20:14 -0800165 ssize_t slot = getSlotIndexFromAddress(addr);
166 if (slot >= 0) {
167 // Give the context slot back.
168 ContextSlotTaken[slot] = false;
Loganeb3d12b2010-12-16 06:20:18 +0800169 }
170}
171
172} // namespace bcc