• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 #include "ContextManager.h"
18 
19 #include "DebugHelper.h"
20 
21 #include <llvm/Support/Mutex.h>
22 #include <llvm/Support/MutexGuard.h>
23 
24 #include <errno.h>
25 #include <sys/mman.h>
26 #include <utils/threads.h>
27 
28 #include <stddef.h>
29 #include <string.h>
30 
31 
32 namespace bcc {
33 
34 // Starting address for context slots
35 char * const ContextManager::ContextFixedAddr = BCC_CONTEXT_FIXED_ADDR_;
36 
37 // ContextManager singleton object
38 ContextManager ContextManager::TheContextManager;
39 
40 
ContextManager()41 ContextManager::ContextManager() {
42   // Initialize context slot occupation table to false
43   for (size_t i = 0; i < ContextSlotCount; ++i) {
44     mContextSlotOccupied[i] = false;
45   }
46 }
47 
allocateContext()48 char *ContextManager::allocateContext() {
49   {
50     // Acquire mContextSlotOccupiedLock
51     llvm::MutexGuard Locked(mContextSlotOccupiedLock);
52 
53     // Try to allocate context on the managed context slot.
54     for (size_t i = 0; i < ContextSlotCount; ++i) {
55       if (mContextSlotOccupied[i]) {
56         continue;
57       }
58 
59       void *addr = ContextFixedAddr + ContextSize * i;
60       void *result = mmap(addr, ContextSize,
61                           PROT_READ | PROT_WRITE | PROT_EXEC,
62                           MAP_PRIVATE | MAP_ANON, -1, 0);
63 
64       if (result == addr) {
65         LOGI("Allocate bcc context. addr=%p\n", result);
66         mContextSlotOccupied[i] = true;
67         return static_cast<char *>(result);
68       }
69 
70       if (result && result != MAP_FAILED) {
71         LOGE("Unable to allocate. suggested=%p, result=%p\n", addr, result);
72         munmap(result, ContextSize);
73       }
74 
75       LOGE("Unable to allocate. addr=%p.  Retry ...\n", addr);
76     }
77     // Release mContextSlotOccupiedLock
78   }
79 
80   // No slot available, allocate at arbitary address.
81   void *result = mmap(0, ContextSize, PROT_READ | PROT_WRITE | PROT_EXEC,
82                       MAP_PRIVATE | MAP_ANON, -1, 0);
83 
84   if (!result || result == MAP_FAILED) {
85     LOGE("Unable to mmap. (reason: %s)\n", strerror(errno));
86     return NULL;
87   }
88 
89   LOGI("Allocate bcc context. addr=%p\n", result);
90   return static_cast<char *>(result);
91 }
92 
93 
allocateContext(char * addr,int imageFd,off_t imageOffset)94 char *ContextManager::allocateContext(char *addr,
95                                       int imageFd, off_t imageOffset) {
96   // This function should only allocate context when address is an context
97   // slot address.  And the image offset is aligned to the pagesize.
98 
99   if (imageFd < 0) {
100     LOGE("Invalid file descriptor for bcc context image\n");
101     return NULL;
102   }
103 
104   unsigned long pagesize = (unsigned long)sysconf(_SC_PAGESIZE);
105 
106   if (imageOffset % pagesize > 0) {
107     LOGE("BCC context image offset is not aligned to page size\n");
108     return NULL;
109   }
110 
111   ssize_t slot = getSlotIndexFromAddress(addr);
112   if (slot < 0) {
113     LOGE("Suggested address is not a bcc context slot address\n");
114     return NULL;
115   }
116 
117   llvm::MutexGuard Locked(mContextSlotOccupiedLock);
118   if (mContextSlotOccupied[slot]) {
119     LOGW("Suggested bcc context slot has been occupied.\n");
120     return NULL;
121   }
122 
123   // LOGI("addr=%x, imageFd=%d, imageOffset=%x", addr, imageFd, imageOffset);
124   void *result = mmap(addr, ContextSize,
125                       PROT_READ | PROT_WRITE | PROT_EXEC,
126                       MAP_PRIVATE, imageFd, imageOffset);
127 
128   if (!result || result == MAP_FAILED) {
129     LOGE("Unable to allocate. addr=%p\n", addr);
130     return NULL;
131   }
132 
133   if (result != addr) {
134     LOGE("Unable to allocate at suggested=%p, result=%p\n", addr, result);
135     munmap(result, ContextSize);
136     return NULL;
137   }
138 
139   LOGI("Allocate bcc context. addr=%p\n", addr);
140   mContextSlotOccupied[slot] = true;
141   return static_cast<char *>(result);
142 }
143 
144 
deallocateContext(char * addr)145 void ContextManager::deallocateContext(char *addr) {
146   if (!addr) {
147     return;
148   }
149 
150   llvm::MutexGuard Locked(mContextSlotOccupiedLock);
151 
152   LOGI("Deallocate bcc context. addr=%p\n", addr);
153 
154   // Unmap
155   if (munmap(addr, ContextSize) < 0) {
156     LOGE("Unable to unmap. addr=%p (reason: %s)\n", addr, strerror(errno));
157     return;
158   }
159 
160   // If the address is one of the context slot, then mark such slot
161   // freely available as well.
162   ssize_t slot = getSlotIndexFromAddress(addr);
163   if (slot >= 0) {
164     // Give the context slot back.
165     mContextSlotOccupied[slot] = false;
166   }
167 }
168 
169 
isManagingContext(char * addr) const170 bool ContextManager::isManagingContext(char *addr) const {
171   ssize_t slot = getSlotIndexFromAddress(addr);
172 
173   if (slot < 0) {
174     return false;
175   }
176 
177   llvm::MutexGuard Locked(mContextSlotOccupiedLock);
178   return mContextSlotOccupied[slot];
179 }
180 
181 
getSlotIndexFromAddress(char * addr)182 ssize_t ContextManager::getSlotIndexFromAddress(char *addr) {
183   if (addr >= ContextFixedAddr) {
184     size_t offset = (size_t)(addr - ContextFixedAddr);
185     if (offset % ContextSize == 0) {
186       size_t slot = offset / ContextSize;
187       if (slot < ContextSlotCount) {
188         return slot;
189       }
190     }
191   }
192   return -1;
193 }
194 
195 
196 
197 } // namespace bcc
198