1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "Memory.hpp"
16
17 #include "Types.hpp"
18 #include "Debug.hpp"
19
20 #if defined(_WIN32)
21 #ifndef WIN32_LEAN_AND_MEAN
22 #define WIN32_LEAN_AND_MEAN
23 #endif
24 #include <windows.h>
25 #else
26 #include <sys/mman.h>
27 #include <unistd.h>
28 #endif
29
30 #if defined(__ANDROID__) && defined(TAG_JIT_CODE_MEMORY)
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <sys/prctl.h>
36
37 // Defined in bionic/libc/private/bionic_prctl.h, but that's not available outside of bionic.
38 #define ANDROID_PR_SET_VMA 0x53564d41 // 'SVMA'
39 #define ANDROID_PR_SET_VMA_ANON_NAME 0
40 #endif
41
42 #include <memory.h>
43
44 #undef allocate
45 #undef deallocate
46 #undef allocateZero
47 #undef deallocateZero
48
49 namespace sw
50 {
memoryPageSize()51 size_t memoryPageSize()
52 {
53 static int pageSize = 0;
54
55 if(pageSize == 0)
56 {
57 #if defined(_WIN32)
58 SYSTEM_INFO systemInfo;
59 GetSystemInfo(&systemInfo);
60 pageSize = systemInfo.dwPageSize;
61 #else
62 pageSize = sysconf(_SC_PAGESIZE);
63 #endif
64 }
65
66 return pageSize;
67 }
68
69 struct Allocation
70 {
71 // size_t bytes;
72 unsigned char *block;
73 };
74
allocate(size_t bytes,size_t alignment)75 void *allocate(size_t bytes, size_t alignment)
76 {
77 unsigned char *block = new unsigned char[bytes + sizeof(Allocation) + alignment];
78 unsigned char *aligned = 0;
79
80 if(block)
81 {
82 aligned = (unsigned char*)((uintptr_t)(block + sizeof(Allocation) + alignment - 1) & -(intptr_t)alignment);
83 Allocation *allocation = (Allocation*)(aligned - sizeof(Allocation));
84
85 // allocation->bytes = bytes;
86 allocation->block = block;
87 }
88
89 return aligned;
90 }
91
allocateZero(size_t bytes,size_t alignment)92 void *allocateZero(size_t bytes, size_t alignment)
93 {
94 void *memory = allocate(bytes, alignment);
95
96 if(memory)
97 {
98 memset(memory, 0, bytes);
99 }
100
101 return memory;
102 }
103
deallocate(void * memory)104 void deallocate(void *memory)
105 {
106 if(memory)
107 {
108 unsigned char *aligned = (unsigned char*)memory;
109 Allocation *allocation = (Allocation*)(aligned - sizeof(Allocation));
110
111 delete[] allocation->block;
112 }
113 }
114
allocateExecutable(size_t bytes)115 void *allocateExecutable(size_t bytes)
116 {
117 size_t pageSize = memoryPageSize();
118 size_t roundedSize = (bytes + pageSize - 1) & ~(pageSize - 1);
119 void *memory = allocate(roundedSize, pageSize);
120
121 #if defined(__ANDROID__) && defined(TAG_JIT_CODE_MEMORY)
122 if(memory)
123 {
124 char *name = nullptr;
125 asprintf(&name, "ss_x_%p", memory);
126
127 if(prctl(ANDROID_PR_SET_VMA, ANDROID_PR_SET_VMA_ANON_NAME, memory, roundedSize, name) == -1)
128 {
129 ALOGE("prctl failed %p 0x%zx (%s)", memory, roundedSize, strerror(errno));
130 free(name);
131 }
132 // The kernel retains a reference to name, so don't free it.
133 }
134 #endif
135
136 return memory;
137 }
138
markExecutable(void * memory,size_t bytes)139 void markExecutable(void *memory, size_t bytes)
140 {
141 #if defined(_WIN32)
142 unsigned long oldProtection;
143 VirtualProtect(memory, bytes, PAGE_EXECUTE_READ, &oldProtection);
144 #else
145 mprotect(memory, bytes, PROT_READ | PROT_EXEC);
146 #endif
147 }
148
deallocateExecutable(void * memory,size_t bytes)149 void deallocateExecutable(void *memory, size_t bytes)
150 {
151 #if defined(_WIN32)
152 unsigned long oldProtection;
153 VirtualProtect(memory, bytes, PAGE_READWRITE, &oldProtection);
154 #else
155 mprotect(memory, bytes, PROT_READ | PROT_WRITE);
156 #endif
157
158 deallocate(memory);
159 }
160 }
161