1 // The MIT License (MIT) 2 // 3 // Copyright (c) 2015 Sergey Makeev, Vadim Slyusarev 4 // 5 // Permission is hereby granted, free of charge, to any person obtaining a copy 6 // of this software and associated documentation files (the "Software"), to deal 7 // in the Software without restriction, including without limitation the rights 8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 // copies of the Software, and to permit persons to whom the Software is 10 // furnished to do so, subject to the following conditions: 11 // 12 // The above copyright notice and this permission notice shall be included in 13 // all copies or substantial portions of the Software. 14 // 15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 // THE SOFTWARE. 22 #include <MTConfig.h> 23 #include <MTAppInterop.h> 24 #include <MTTools.h> 25 26 #include <stdio.h> 27 28 #if MT_SSE_INTRINSICS_SUPPORTED 29 #include <xmmintrin.h> 30 #else 31 #include <malloc.h> 32 #endif 33 34 35 36 37 #if MT_PLATFORM_WINDOWS 38 39 inline void ThrowException() 40 { 41 __debugbreak(); 42 } 43 44 #elif MT_PLATFORM_POSIX 45 46 #include<signal.h> 47 inline void ThrowException() 48 { 49 raise(SIGTRAP); 50 // force access violation error 51 char* pBadAddr = (char*)0x0; 52 *pBadAddr = 0; 53 } 54 55 #elif MT_PLATFORM_OSX 56 57 inline void ThrowException() 58 { 59 __builtin_trap(); 60 } 61 62 #else 63 64 #error Platform is not supported! 65 66 #endif 67 68 69 70 namespace MT 71 { 72 73 void* Memory::Alloc(size_t size, size_t align) 74 { 75 void* p = nullptr; 76 #if MT_SSE_INTRINSICS_SUPPORTED 77 p = _mm_malloc(size, align); 78 #else 79 p = memalign(size, align); 80 #endif 81 MT_ASSERT(p, "Can't allocate memory"); 82 return p; 83 } 84 85 void Memory::Free(void* p) 86 { 87 #if MT_SSE_INTRINSICS_SUPPORTED 88 _mm_free(p); 89 #else 90 free(p); 91 #endif 92 } 93 94 Memory::StackDesc Memory::AllocStack(size_t size) 95 { 96 StackDesc desc; 97 98 #if MT_PLATFORM_WINDOWS 99 100 MW_SYSTEM_INFO systemInfo; 101 GetSystemInfo(&systemInfo); 102 103 int pageSize = (int)systemInfo.dwPageSize; 104 int pagesCount = (int)size / pageSize; 105 106 //need additional page for stack guard 107 if ((size % pageSize) > 0) 108 { 109 pagesCount++; 110 } 111 112 //protected guard page 113 pagesCount++; 114 115 desc.stackMemoryBytesCount = pagesCount * pageSize; 116 desc.stackMemory = (char*)VirtualAlloc(NULL, desc.stackMemoryBytesCount, MW_MEM_COMMIT, MW_PAGE_READWRITE); 117 MT_ASSERT(desc.stackMemory != NULL, "Can't allocate memory"); 118 119 desc.stackBottom = desc.stackMemory + pageSize; 120 desc.stackTop = desc.stackMemory + desc.stackMemoryBytesCount; 121 122 MW_DWORD oldProtect = 0; 123 MW_BOOL res = VirtualProtect(desc.stackMemory, pageSize, MW_PAGE_NOACCESS, &oldProtect); 124 MT_USED_IN_ASSERT(res); 125 MT_ASSERT(res != 0, "Can't protect memory"); 126 127 #elif MT_PLATFORM_POSIX || MT_PLATFORM_OSX 128 129 int pageSize = sysconf(_SC_PAGE_SIZE); 130 int pagesCount = size / pageSize; 131 132 //need additional page for stack tail 133 if ((size % pageSize) > 0) 134 { 135 pagesCount++; 136 } 137 138 //protected guard page 139 pagesCount++; 140 141 desc.stackMemoryBytesCount = pagesCount * pageSize; 142 desc.stackMemory = (char*)mmap(NULL, desc.stackMemoryBytesCount, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); 143 144 MT_ASSERT((void *)desc.stackMemory != (void *)-1, "Can't allocate memory"); 145 146 desc.stackBottom = desc.stackMemory + pageSize; 147 desc.stackTop = desc.stackMemory + desc.stackMemoryBytesCount; 148 149 int res = mprotect(desc.stackMemory, pageSize, PROT_NONE); 150 MT_USED_IN_ASSERT(res); 151 MT_ASSERT(res == 0, "Can't protect memory"); 152 #else 153 #error Platform is not supported! 154 #endif 155 156 return desc; 157 } 158 159 void Memory::FreeStack(const Memory::StackDesc & desc) 160 { 161 #if MT_PLATFORM_WINDOWS 162 163 int res = VirtualFree(desc.stackMemory, 0, MW_MEM_RELEASE); 164 MT_USED_IN_ASSERT(res); 165 MT_ASSERT(res != 0, "Can't free memory"); 166 167 #elif MT_PLATFORM_POSIX || MT_PLATFORM_OSX 168 169 int res = munmap(desc.stackMemory, desc.stackMemoryBytesCount); 170 MT_USED_IN_ASSERT(res); 171 MT_ASSERT(res == 0, "Can't free memory"); 172 #else 173 #error Platform is not supported! 174 #endif 175 } 176 177 void Diagnostic::ReportAssert(const char* condition, const char* description, const char* sourceFile, int sourceLine) 178 { 179 printf("Assertion failed : %s. File %s, line %d. Condition %s\n", description, sourceFile, sourceLine, condition); 180 ThrowException(); 181 } 182 183 184 185 186 } 187