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