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 #endif
31
32
33
34
35 #if MT_PLATFORM_WINDOWS
36
ThrowException()37 inline void ThrowException()
38 {
39 __debugbreak();
40 }
41
42 #elif MT_PLATFORM_POSIX
43
44 #include<signal.h>
ThrowException()45 inline void ThrowException()
46 {
47 raise(SIGTRAP);
48 // force access violation error
49 char* pBadAddr = (char*)0x0;
50 *pBadAddr = 0;
51 }
52
53 #elif MT_PLATFORM_OSX
54
ThrowException()55 inline void ThrowException()
56 {
57 __builtin_trap();
58 }
59
60 #else
61
62 #error Platform is not supported!
63
64 #endif
65
66
67
68 namespace MT
69 {
70
Alloc(size_t size,size_t align)71 void* Memory::Alloc(size_t size, size_t align)
72 {
73 void* p = nullptr;
74 #if MT_SSE_INTRINSICS_SUPPORTED
75 p = _mm_malloc(size, align);
76 #else
77 if (posix_memalign(&p, size, align) != 0)
78 {
79 p = nullptr;
80 }
81 #endif
82 MT_ASSERT(p, "Can't allocate memory");
83 return p;
84 }
85
Free(void * p)86 void Memory::Free(void* p)
87 {
88 #if MT_SSE_INTRINSICS_SUPPORTED
89 _mm_free(p);
90 #else
91 free(p);
92 #endif
93 }
94
AllocStack(size_t size)95 Memory::StackDesc Memory::AllocStack(size_t size)
96 {
97 StackDesc desc;
98
99 #if MT_PLATFORM_WINDOWS
100
101 MW_SYSTEM_INFO systemInfo;
102 GetSystemInfo(&systemInfo);
103
104 size_t pageSize = systemInfo.dwPageSize;
105 size_t pagesCount = size / pageSize;
106
107 //need additional page for stack guard
108 if ((size % pageSize) > 0)
109 {
110 pagesCount++;
111 }
112
113 //protected guard page
114 pagesCount++;
115
116 desc.stackMemoryBytesCount = pagesCount * pageSize;
117 desc.stackMemory = (char*)VirtualAlloc(NULL, desc.stackMemoryBytesCount, MW_MEM_COMMIT, MW_PAGE_READWRITE);
118 MT_ASSERT(desc.stackMemory != NULL, "Can't allocate memory");
119
120 desc.stackBottom = desc.stackMemory + pageSize;
121 desc.stackTop = desc.stackMemory + desc.stackMemoryBytesCount;
122
123 MW_DWORD oldProtect = 0;
124 MW_BOOL res = VirtualProtect(desc.stackMemory, pageSize, MW_PAGE_NOACCESS, &oldProtect);
125 MT_USED_IN_ASSERT(res);
126 MT_ASSERT(res != 0, "Can't protect memory");
127
128 #elif MT_PLATFORM_POSIX || MT_PLATFORM_OSX
129
130 int pageSize = (int)sysconf(_SC_PAGE_SIZE);
131 int pagesCount = (int)(size / pageSize);
132
133 //need additional page for stack tail
134 if ((size % pageSize) > 0)
135 {
136 pagesCount++;
137 }
138
139 //protected guard page
140 pagesCount++;
141
142 desc.stackMemoryBytesCount = pagesCount * pageSize;
143 desc.stackMemory = (char*)mmap(NULL, desc.stackMemoryBytesCount, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
144
145 MT_ASSERT((void *)desc.stackMemory != (void *)-1, "Can't allocate memory");
146
147 desc.stackBottom = desc.stackMemory + pageSize;
148 desc.stackTop = desc.stackMemory + desc.stackMemoryBytesCount;
149
150 int res = mprotect(desc.stackMemory, pageSize, PROT_NONE);
151 MT_USED_IN_ASSERT(res);
152 MT_ASSERT(res == 0, "Can't protect memory");
153 #else
154 #error Platform is not supported!
155 #endif
156
157 return desc;
158 }
159
FreeStack(const Memory::StackDesc & desc)160 void Memory::FreeStack(const Memory::StackDesc & desc)
161 {
162 #if MT_PLATFORM_WINDOWS
163
164 int res = VirtualFree(desc.stackMemory, 0, MW_MEM_RELEASE);
165 MT_USED_IN_ASSERT(res);
166 MT_ASSERT(res != 0, "Can't free memory");
167
168 #elif MT_PLATFORM_POSIX || MT_PLATFORM_OSX
169
170 int res = munmap(desc.stackMemory, desc.stackMemoryBytesCount);
171 MT_USED_IN_ASSERT(res);
172 MT_ASSERT(res == 0, "Can't free memory");
173 #else
174 #error Platform is not supported!
175 #endif
176 }
177
ReportAssert(const char * condition,const char * description,const char * sourceFile,int sourceLine)178 void Diagnostic::ReportAssert(const char* condition, const char* description, const char* sourceFile, int sourceLine)
179 {
180 printf("Assertion failed : %s. File %s, line %d. Condition %s\n", description, sourceFile, sourceLine, condition);
181 ThrowException();
182 }
183
184
185
186
187 }
188