blob: e1be7946f0e6006e7fc8e6a18c1d1a9a9c559e68 [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
Loganf15ede32011-01-01 01:37:22 +080053 if (result == addr) { // Allocated successfully
Loganeb3d12b2010-12-16 06:20:18 +080054 return (char *)result;
55 }
56
Loganf15ede32011-01-01 01:37:22 +080057 if (result && result != MAP_FAILED) {
58 LOGE("Unable to allocate at suggested=%p, result=%p\n", addr, result);
59 munmap(result, BCC_CONTEXT_SIZE);
60 }
61
62 LOGE("Unable to allocate at %p. Retry ...\n", addr);
Loganeb3d12b2010-12-16 06:20:18 +080063 }
64
65 // No slot available, allocate at arbitary address.
66
67 void *result = mmap(0, BCC_CONTEXT_SIZE,
68 PROT_READ | PROT_WRITE | PROT_EXEC,
69 MAP_PRIVATE | MAP_ANON, -1, 0);
70
71 if (!result || result == MAP_FAILED) {
72 LOGE("Unable to mmap. (reason: %s)\n", strerror(errno));
73 return NULL;
74 }
75
76 return (char *)result;
77}
78
79
80char *allocateContext(char *addr, int imageFd, off_t imageOffset) {
81 // This function should only allocate context when address is an context
82 // slot address. And the image offset is aligned to the pagesize.
83
84 if (imageFd < 0) {
85 // Invalid file descriptor.
86 return NULL;
87 }
88
89 unsigned long pagesize = (unsigned long)sysconf(_SC_PAGESIZE);
90
91 if (imageOffset % pagesize > 0) {
92 // Image is not aligned in the cache file.
93 return NULL;
94 }
95
96 if (addr < BCC_CONTEXT_FIXED_ADDR) {
97 // If the suggest address is not at the context slot, then return
98 // NULL as error.
99 return NULL;
100 }
101
102 size_t offset = (size_t)(addr - BCC_CONTEXT_FIXED_ADDR);
103 size_t slot = offset / BCC_CONTEXT_SIZE;
104
105 if (offset % BCC_CONTEXT_SIZE != 0 || slot >= BCC_CONTEXT_SLOT_COUNT) {
106 // Invalid Slot Address (Not aligned or overflow)
107 return NULL;
108 }
Shih-wei Liao931501a2010-12-16 04:43:04 -0800109 // LOGI("BEFORE slot[%d] checking", slot);
Loganeb3d12b2010-12-16 06:20:18 +0800110 if (ContextSlotTaken[slot]) {
111 // Slot has been taken.
112 return NULL;
113 }
Shih-wei Liao931501a2010-12-16 04:43:04 -0800114 // LOGI("AFTER slot checking");
Loganeb3d12b2010-12-16 06:20:18 +0800115
116 ContextSlotTaken[slot] = true;
117
Shih-wei Liao931501a2010-12-16 04:43:04 -0800118 // LOGI("addr=%x, imageFd=%d, imageOffset=%x", addr, imageFd, imageOffset);
Loganeb3d12b2010-12-16 06:20:18 +0800119 void *result = mmap(addr, BCC_CONTEXT_SIZE,
120 PROT_READ | PROT_WRITE | PROT_EXEC,
121 MAP_PRIVATE, imageFd, imageOffset);
122
Loganf15ede32011-01-01 01:37:22 +0800123 if (result != addr) {
124 LOGE("Unable to allocate at suggested=%p, result=%p\n", addr, result);
125 munmap(result, BCC_CONTEXT_SIZE);
126 return NULL;
127 }
128
Loganeb3d12b2010-12-16 06:20:18 +0800129 return (result && result != MAP_FAILED) ? (char *)result : NULL;
130}
131
132
133void deallocateContext(char *addr) {
134 if (!addr) {
135 return;
136 }
137
Logan069b3312010-12-31 18:31:15 +0800138 LOGI("Deallocate bcc context %p\n", addr);
139
Loganeb3d12b2010-12-16 06:20:18 +0800140 // Unmap
141 if (munmap(addr, BCC_CONTEXT_SIZE) < 0) {
142 LOGE("Unable to unmap addr %p (reason: %s)\n", addr, strerror(errno));
143 return;
144 }
145
146 // If the address is one of the context slot, then mark such slot
147 // freely available as well.
148 if (addr >= BCC_CONTEXT_FIXED_ADDR) {
149 size_t offset = (size_t)(addr - BCC_CONTEXT_FIXED_ADDR);
150 size_t slot = offset / BCC_CONTEXT_SIZE;
151
152 if (offset % BCC_CONTEXT_SIZE == 0 && slot < BCC_CONTEXT_SLOT_COUNT) {
153 // Give the context slot back.
154 ContextSlotTaken[slot] = false;
155 }
156 }
157}
158
159} // namespace bcc