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