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 #include <intrin.h> 26 #else 27 #include <sys/mman.h> 28 #include <unistd.h> 29 #endif 30 31 #include <memory.h> 32 33 #undef allocate 34 #undef deallocate 35 36 #if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined (_M_X64)) && !defined(__x86__) 37 #define __x86__ 38 #endif 39 40 namespace sw 41 { 42 size_t memoryPageSize() 43 { 44 static int pageSize = 0; 45 46 if(pageSize == 0) 47 { 48 #if defined(_WIN32) 49 SYSTEM_INFO systemInfo; 50 GetSystemInfo(&systemInfo); 51 pageSize = systemInfo.dwPageSize; 52 #else 53 pageSize = sysconf(_SC_PAGESIZE); 54 #endif 55 } 56 57 return pageSize; 58 } 59 60 struct Allocation 61 { 62 // size_t bytes; 63 unsigned char *block; 64 }; 65 66 inline void *allocateRaw(size_t bytes, size_t alignment) 67 { 68 unsigned char *block = new unsigned char[bytes + sizeof(Allocation) + alignment]; 69 unsigned char *aligned = nullptr; 70 71 if(block) 72 { 73 aligned = (unsigned char*)((uintptr_t)(block + sizeof(Allocation) + alignment - 1) & -(intptr_t)alignment); 74 Allocation *allocation = (Allocation*)(aligned - sizeof(Allocation)); 75 76 // allocation->bytes = bytes; 77 allocation->block = block; 78 } 79 80 return aligned; 81 } 82 83 void *allocate(size_t bytes, size_t alignment) 84 { 85 void *memory = allocateRaw(bytes, alignment); 86 87 if(memory) 88 { 89 memset(memory, 0, bytes); 90 } 91 92 return memory; 93 } 94 95 void deallocate(void *memory) 96 { 97 if(memory) 98 { 99 unsigned char *aligned = (unsigned char*)memory; 100 Allocation *allocation = (Allocation*)(aligned - sizeof(Allocation)); 101 102 delete[] allocation->block; 103 } 104 } 105 106 void *allocateExecutable(size_t bytes) 107 { 108 size_t pageSize = memoryPageSize(); 109 110 return allocate((bytes + pageSize - 1) & ~(pageSize - 1), pageSize); 111 } 112 113 void markExecutable(void *memory, size_t bytes) 114 { 115 #if defined(_WIN32) 116 unsigned long oldProtection; 117 VirtualProtect(memory, bytes, PAGE_EXECUTE_READ, &oldProtection); 118 #else 119 mprotect(memory, bytes, PROT_READ | PROT_EXEC); 120 #endif 121 } 122 123 void deallocateExecutable(void *memory, size_t bytes) 124 { 125 #if defined(_WIN32) 126 unsigned long oldProtection; 127 VirtualProtect(memory, bytes, PAGE_READWRITE, &oldProtection); 128 #else 129 mprotect(memory, bytes, PROT_READ | PROT_WRITE); 130 #endif 131 132 deallocate(memory); 133 } 134 135 void clear(uint16_t *memory, uint16_t element, size_t count) 136 { 137 #if defined(_MSC_VER) && defined(__x86__) 138 __stosw(memory, element, count); 139 #elif defined(__GNUC__) && defined(__x86__) 140 __asm__("rep stosw" : : "D"(memory), "a"(element), "c"(count)); 141 #else 142 for(size_t i = 0; i < count; i++) 143 { 144 memory[i] = element; 145 } 146 #endif 147 } 148 149 void clear(uint32_t *memory, uint32_t element, size_t count) 150 { 151 #if defined(_MSC_VER) && defined(__x86__) 152 __stosd((unsigned long*)memory, element, count); 153 #elif defined(__GNUC__) && defined(__x86__) 154 __asm__("rep stosl" : : "D"(memory), "a"(element), "c"(count)); 155 #else 156 for(size_t i = 0; i < count; i++) 157 { 158 memory[i] = element; 159 } 160 #endif 161 } 162 } 163