blob: 917d7f1178c6f8b32231d77af602351885f92dff [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>
24
25#include <stddef.h>
26#include <string.h>
27
28
29namespace {
30 static bool ContextSlotTaken[BCC_CONTEXT_SLOT_COUNT];
31} // namespace anonymous
32
33
34namespace bcc {
35
36char *allocateContext() {
37 // Try to allocate context on the managed context slot.
38 for (size_t i = 0; i < BCC_CONTEXT_SLOT_COUNT; ++i) {
39 if (ContextSlotTaken[i]) {
40 continue;
41 }
42
43 // Take the context slot. (No matter we can mmap or not)
44 ContextSlotTaken[i] = true;
45
46 void *addr = BCC_CONTEXT_FIXED_ADDR + BCC_CONTEXT_SIZE * i;
47
48 // Try to mmap
49 void *result = mmap(addr, BCC_CONTEXT_SIZE,
50 PROT_READ | PROT_WRITE | PROT_EXEC,
Loganf15ede32011-01-01 01:37:22 +080051 MAP_PRIVATE | MAP_ANON, -1, 0);
Loganeb3d12b2010-12-16 06:20:18 +080052
Loganb1feb382010-12-29 20:37:11 +080053 if (result == addr) {
54 LOGI("Allocate bcc context. addr=%p\n", result);
55 return static_cast<char *>(result);
Loganeb3d12b2010-12-16 06:20:18 +080056 }
57
Loganf15ede32011-01-01 01:37:22 +080058 if (result && result != MAP_FAILED) {
Loganb1feb382010-12-29 20:37:11 +080059 LOGE("Unable to allocate. suggested=%p, result=%p\n", addr, result);
Loganf15ede32011-01-01 01:37:22 +080060 munmap(result, BCC_CONTEXT_SIZE);
61 }
62
Loganb1feb382010-12-29 20:37:11 +080063 LOGE("Unable to allocate. addr=%p. Retry ...\n", addr);
Loganeb3d12b2010-12-16 06:20:18 +080064 }
65
66 // No slot available, allocate at arbitary address.
67
68 void *result = mmap(0, BCC_CONTEXT_SIZE,
69 PROT_READ | PROT_WRITE | PROT_EXEC,
70 MAP_PRIVATE | MAP_ANON, -1, 0);
71
72 if (!result || result == MAP_FAILED) {
Loganb1feb382010-12-29 20:37:11 +080073 LOGE("Unable to mmap. (reason: %s)\n", strerror(errno));
Loganeb3d12b2010-12-16 06:20:18 +080074 return NULL;
75 }
76
Loganb1feb382010-12-29 20:37:11 +080077 LOGI("Allocate bcc context. addr=%p\n", result);
Loganeb3d12b2010-12-16 06:20:18 +080078 return (char *)result;
79}
80
81
82char *allocateContext(char *addr, int imageFd, off_t imageOffset) {
83 // This function should only allocate context when address is an context
84 // slot address. And the image offset is aligned to the pagesize.
85
86 if (imageFd < 0) {
87 // Invalid file descriptor.
Loganb1feb382010-12-29 20:37:11 +080088 LOGE("Invalid file descriptor for bcc context image\n");
Loganeb3d12b2010-12-16 06:20:18 +080089 return NULL;
90 }
91
92 unsigned long pagesize = (unsigned long)sysconf(_SC_PAGESIZE);
93
94 if (imageOffset % pagesize > 0) {
Loganb1feb382010-12-29 20:37:11 +080095 LOGE("BCC context image offset is not aligned to page size\n");
Loganeb3d12b2010-12-16 06:20:18 +080096 return NULL;
97 }
98
99 if (addr < BCC_CONTEXT_FIXED_ADDR) {
Loganb1feb382010-12-29 20:37:11 +0800100 LOGE("Suggested address is not a bcc context slot address\n");
Loganeb3d12b2010-12-16 06:20:18 +0800101 return NULL;
102 }
103
104 size_t offset = (size_t)(addr - BCC_CONTEXT_FIXED_ADDR);
105 size_t slot = offset / BCC_CONTEXT_SIZE;
106
107 if (offset % BCC_CONTEXT_SIZE != 0 || slot >= BCC_CONTEXT_SLOT_COUNT) {
Loganb1feb382010-12-29 20:37:11 +0800108 LOGE("Suggested address is not a bcc context slot address\n");
Loganeb3d12b2010-12-16 06:20:18 +0800109 return NULL;
110 }
Loganb1feb382010-12-29 20:37:11 +0800111
Loganeb3d12b2010-12-16 06:20:18 +0800112 if (ContextSlotTaken[slot]) {
Loganb1feb382010-12-29 20:37:11 +0800113 LOGE("Suggested bcc context slot has been occupied.\n");
Loganeb3d12b2010-12-16 06:20:18 +0800114 return NULL;
115 }
116
117 ContextSlotTaken[slot] = true;
118
Shih-wei Liao931501a2010-12-16 04:43:04 -0800119 // LOGI("addr=%x, imageFd=%d, imageOffset=%x", addr, imageFd, imageOffset);
Loganeb3d12b2010-12-16 06:20:18 +0800120 void *result = mmap(addr, BCC_CONTEXT_SIZE,
121 PROT_READ | PROT_WRITE | PROT_EXEC,
122 MAP_PRIVATE, imageFd, imageOffset);
123
Loganb1feb382010-12-29 20:37:11 +0800124 if (!result || result == MAP_FAILED) {
125 LOGE("Unable to allocate. addr=%p\n", addr);
126 return NULL;
127 }
128
Loganf15ede32011-01-01 01:37:22 +0800129 if (result != addr) {
130 LOGE("Unable to allocate at suggested=%p, result=%p\n", addr, result);
131 munmap(result, BCC_CONTEXT_SIZE);
132 return NULL;
133 }
134
Loganb1feb382010-12-29 20:37:11 +0800135 LOGI("Allocate bcc context. addr=%p\n", addr);
136 return static_cast<char *>(result);
Loganeb3d12b2010-12-16 06:20:18 +0800137}
138
139
140void deallocateContext(char *addr) {
141 if (!addr) {
142 return;
143 }
144
Loganb1feb382010-12-29 20:37:11 +0800145 LOGI("Deallocate bcc context. addr=%p\n", addr);
Logan069b3312010-12-31 18:31:15 +0800146
Loganeb3d12b2010-12-16 06:20:18 +0800147 // Unmap
148 if (munmap(addr, BCC_CONTEXT_SIZE) < 0) {
Loganb1feb382010-12-29 20:37:11 +0800149 LOGE("Unable to unmap. addr=%p (reason: %s)\n", addr, strerror(errno));
Loganeb3d12b2010-12-16 06:20:18 +0800150 return;
151 }
152
153 // If the address is one of the context slot, then mark such slot
154 // freely available as well.
155 if (addr >= BCC_CONTEXT_FIXED_ADDR) {
156 size_t offset = (size_t)(addr - BCC_CONTEXT_FIXED_ADDR);
157 size_t slot = offset / BCC_CONTEXT_SIZE;
158
159 if (offset % BCC_CONTEXT_SIZE == 0 && slot < BCC_CONTEXT_SLOT_COUNT) {
160 // Give the context slot back.
161 ContextSlotTaken[slot] = false;
162 }
163 }
164}
165
166} // namespace bcc