xref: /aosp_15_r20/external/swiftshader/src/System/Memory.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*03ce13f7SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*03ce13f7SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*03ce13f7SAndroid Build Coastguard Worker //
7*03ce13f7SAndroid Build Coastguard Worker //    http://www.apache.org/licenses/LICENSE-2.0
8*03ce13f7SAndroid Build Coastguard Worker //
9*03ce13f7SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*03ce13f7SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*03ce13f7SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*03ce13f7SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*03ce13f7SAndroid Build Coastguard Worker // limitations under the License.
14*03ce13f7SAndroid Build Coastguard Worker 
15*03ce13f7SAndroid Build Coastguard Worker #include "Memory.hpp"
16*03ce13f7SAndroid Build Coastguard Worker 
17*03ce13f7SAndroid Build Coastguard Worker #include "Debug.hpp"
18*03ce13f7SAndroid Build Coastguard Worker #include "Types.hpp"
19*03ce13f7SAndroid Build Coastguard Worker 
20*03ce13f7SAndroid Build Coastguard Worker #if defined(_WIN32)
21*03ce13f7SAndroid Build Coastguard Worker #	ifndef WIN32_LEAN_AND_MEAN
22*03ce13f7SAndroid Build Coastguard Worker #		define WIN32_LEAN_AND_MEAN
23*03ce13f7SAndroid Build Coastguard Worker #	endif
24*03ce13f7SAndroid Build Coastguard Worker #	include <windows.h>
25*03ce13f7SAndroid Build Coastguard Worker #	include <intrin.h>
26*03ce13f7SAndroid Build Coastguard Worker #else
27*03ce13f7SAndroid Build Coastguard Worker #	include <errno.h>
28*03ce13f7SAndroid Build Coastguard Worker #	include <sys/mman.h>
29*03ce13f7SAndroid Build Coastguard Worker #	include <stdlib.h>
30*03ce13f7SAndroid Build Coastguard Worker #	include <unistd.h>
31*03ce13f7SAndroid Build Coastguard Worker #endif
32*03ce13f7SAndroid Build Coastguard Worker 
33*03ce13f7SAndroid Build Coastguard Worker #include <cstdlib>
34*03ce13f7SAndroid Build Coastguard Worker #include <cstring>
35*03ce13f7SAndroid Build Coastguard Worker 
36*03ce13f7SAndroid Build Coastguard Worker #undef allocate
37*03ce13f7SAndroid Build Coastguard Worker #undef deallocate
38*03ce13f7SAndroid Build Coastguard Worker 
39*03ce13f7SAndroid Build Coastguard Worker #if(defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)) && !defined(__x86__)
40*03ce13f7SAndroid Build Coastguard Worker #	define __x86__
41*03ce13f7SAndroid Build Coastguard Worker #endif
42*03ce13f7SAndroid Build Coastguard Worker 
43*03ce13f7SAndroid Build Coastguard Worker // A Clang extension to determine compiler features.
44*03ce13f7SAndroid Build Coastguard Worker // We use it to detect Sanitizer builds (e.g. -fsanitize=memory).
45*03ce13f7SAndroid Build Coastguard Worker #ifndef __has_feature
46*03ce13f7SAndroid Build Coastguard Worker #	define __has_feature(x) 0
47*03ce13f7SAndroid Build Coastguard Worker #endif
48*03ce13f7SAndroid Build Coastguard Worker 
49*03ce13f7SAndroid Build Coastguard Worker namespace sw {
50*03ce13f7SAndroid Build Coastguard Worker 
51*03ce13f7SAndroid Build Coastguard Worker namespace {
52*03ce13f7SAndroid Build Coastguard Worker 
53*03ce13f7SAndroid Build Coastguard Worker struct Allocation
54*03ce13f7SAndroid Build Coastguard Worker {
55*03ce13f7SAndroid Build Coastguard Worker 	// size_t bytes;
56*03ce13f7SAndroid Build Coastguard Worker 	unsigned char *block;
57*03ce13f7SAndroid Build Coastguard Worker };
58*03ce13f7SAndroid Build Coastguard Worker 
59*03ce13f7SAndroid Build Coastguard Worker }  // anonymous namespace
60*03ce13f7SAndroid Build Coastguard Worker 
memoryPageSize()61*03ce13f7SAndroid Build Coastguard Worker size_t memoryPageSize()
62*03ce13f7SAndroid Build Coastguard Worker {
63*03ce13f7SAndroid Build Coastguard Worker 	static int pageSize = [] {
64*03ce13f7SAndroid Build Coastguard Worker #if defined(_WIN32)
65*03ce13f7SAndroid Build Coastguard Worker 		SYSTEM_INFO systemInfo;
66*03ce13f7SAndroid Build Coastguard Worker 		GetSystemInfo(&systemInfo);
67*03ce13f7SAndroid Build Coastguard Worker 		return systemInfo.dwPageSize;
68*03ce13f7SAndroid Build Coastguard Worker #else
69*03ce13f7SAndroid Build Coastguard Worker 		return sysconf(_SC_PAGESIZE);
70*03ce13f7SAndroid Build Coastguard Worker #endif
71*03ce13f7SAndroid Build Coastguard Worker 	}();
72*03ce13f7SAndroid Build Coastguard Worker 
73*03ce13f7SAndroid Build Coastguard Worker 	return pageSize;
74*03ce13f7SAndroid Build Coastguard Worker }
75*03ce13f7SAndroid Build Coastguard Worker 
allocate(size_t bytes,size_t alignment,bool clearToZero)76*03ce13f7SAndroid Build Coastguard Worker static void *allocate(size_t bytes, size_t alignment, bool clearToZero)
77*03ce13f7SAndroid Build Coastguard Worker {
78*03ce13f7SAndroid Build Coastguard Worker 	ASSERT((alignment & (alignment - 1)) == 0);  // Power of 2 alignment.
79*03ce13f7SAndroid Build Coastguard Worker 
80*03ce13f7SAndroid Build Coastguard Worker 	size_t size = bytes + sizeof(Allocation) + alignment;
81*03ce13f7SAndroid Build Coastguard Worker 	unsigned char *block = (unsigned char *)malloc(size);
82*03ce13f7SAndroid Build Coastguard Worker 	unsigned char *aligned = nullptr;
83*03ce13f7SAndroid Build Coastguard Worker 
84*03ce13f7SAndroid Build Coastguard Worker 	if(block)
85*03ce13f7SAndroid Build Coastguard Worker 	{
86*03ce13f7SAndroid Build Coastguard Worker 		if(clearToZero)
87*03ce13f7SAndroid Build Coastguard Worker 		{
88*03ce13f7SAndroid Build Coastguard Worker 			memset(block, 0, size);
89*03ce13f7SAndroid Build Coastguard Worker 		}
90*03ce13f7SAndroid Build Coastguard Worker 
91*03ce13f7SAndroid Build Coastguard Worker 		aligned = (unsigned char *)((uintptr_t)(block + sizeof(Allocation) + alignment - 1) & -(intptr_t)alignment);
92*03ce13f7SAndroid Build Coastguard Worker 		Allocation *allocation = (Allocation *)(aligned - sizeof(Allocation));
93*03ce13f7SAndroid Build Coastguard Worker 
94*03ce13f7SAndroid Build Coastguard Worker 		// allocation->bytes = bytes;
95*03ce13f7SAndroid Build Coastguard Worker 		allocation->block = block;
96*03ce13f7SAndroid Build Coastguard Worker 	}
97*03ce13f7SAndroid Build Coastguard Worker 
98*03ce13f7SAndroid Build Coastguard Worker 	return aligned;
99*03ce13f7SAndroid Build Coastguard Worker }
100*03ce13f7SAndroid Build Coastguard Worker 
allocate(size_t bytes,size_t alignment)101*03ce13f7SAndroid Build Coastguard Worker void *allocate(size_t bytes, size_t alignment)
102*03ce13f7SAndroid Build Coastguard Worker {
103*03ce13f7SAndroid Build Coastguard Worker 	return allocate(bytes, alignment, false);
104*03ce13f7SAndroid Build Coastguard Worker }
105*03ce13f7SAndroid Build Coastguard Worker 
106*03ce13f7SAndroid Build Coastguard Worker // This funtion allocates memory that is zero-initialized for security reasons
107*03ce13f7SAndroid Build Coastguard Worker // only. In MemorySanitizer enabled builds it is left uninitialized.
allocateZeroOrPoison(size_t bytes,size_t alignment)108*03ce13f7SAndroid Build Coastguard Worker void *allocateZeroOrPoison(size_t bytes, size_t alignment)
109*03ce13f7SAndroid Build Coastguard Worker {
110*03ce13f7SAndroid Build Coastguard Worker 	return allocate(bytes, alignment, !__has_feature(memory_sanitizer));
111*03ce13f7SAndroid Build Coastguard Worker }
112*03ce13f7SAndroid Build Coastguard Worker 
freeMemory(void * memory)113*03ce13f7SAndroid Build Coastguard Worker void freeMemory(void *memory)
114*03ce13f7SAndroid Build Coastguard Worker {
115*03ce13f7SAndroid Build Coastguard Worker 	if(memory)
116*03ce13f7SAndroid Build Coastguard Worker 	{
117*03ce13f7SAndroid Build Coastguard Worker 		unsigned char *aligned = (unsigned char *)memory;
118*03ce13f7SAndroid Build Coastguard Worker 		Allocation *allocation = (Allocation *)(aligned - sizeof(Allocation));
119*03ce13f7SAndroid Build Coastguard Worker 
120*03ce13f7SAndroid Build Coastguard Worker 		free(allocation->block);
121*03ce13f7SAndroid Build Coastguard Worker 	}
122*03ce13f7SAndroid Build Coastguard Worker }
123*03ce13f7SAndroid Build Coastguard Worker 
clear(uint16_t * memory,uint16_t element,size_t count)124*03ce13f7SAndroid Build Coastguard Worker void clear(uint16_t *memory, uint16_t element, size_t count)
125*03ce13f7SAndroid Build Coastguard Worker {
126*03ce13f7SAndroid Build Coastguard Worker #if defined(_MSC_VER) && defined(__x86__) && !defined(MEMORY_SANITIZER)
127*03ce13f7SAndroid Build Coastguard Worker 	__stosw(memory, element, count);
128*03ce13f7SAndroid Build Coastguard Worker #elif defined(__GNUC__) && defined(__x86__) && !defined(MEMORY_SANITIZER)
129*03ce13f7SAndroid Build Coastguard Worker 	__asm__ __volatile__("rep stosw"
130*03ce13f7SAndroid Build Coastguard Worker 	                     : "+D"(memory), "+c"(count)
131*03ce13f7SAndroid Build Coastguard Worker 	                     : "a"(element)
132*03ce13f7SAndroid Build Coastguard Worker 	                     : "memory");
133*03ce13f7SAndroid Build Coastguard Worker #else
134*03ce13f7SAndroid Build Coastguard Worker 	for(size_t i = 0; i < count; i++)
135*03ce13f7SAndroid Build Coastguard Worker 	{
136*03ce13f7SAndroid Build Coastguard Worker 		memory[i] = element;
137*03ce13f7SAndroid Build Coastguard Worker 	}
138*03ce13f7SAndroid Build Coastguard Worker #endif
139*03ce13f7SAndroid Build Coastguard Worker }
140*03ce13f7SAndroid Build Coastguard Worker 
clear(uint32_t * memory,uint32_t element,size_t count)141*03ce13f7SAndroid Build Coastguard Worker void clear(uint32_t *memory, uint32_t element, size_t count)
142*03ce13f7SAndroid Build Coastguard Worker {
143*03ce13f7SAndroid Build Coastguard Worker #if defined(_MSC_VER) && defined(__x86__) && !defined(MEMORY_SANITIZER)
144*03ce13f7SAndroid Build Coastguard Worker 	__stosd((unsigned long *)memory, element, count);
145*03ce13f7SAndroid Build Coastguard Worker #elif defined(__GNUC__) && defined(__x86__) && !defined(MEMORY_SANITIZER)
146*03ce13f7SAndroid Build Coastguard Worker 	__asm__ __volatile__("rep stosl"
147*03ce13f7SAndroid Build Coastguard Worker 	                     : "+D"(memory), "+c"(count)
148*03ce13f7SAndroid Build Coastguard Worker 	                     : "a"(element)
149*03ce13f7SAndroid Build Coastguard Worker 	                     : "memory");
150*03ce13f7SAndroid Build Coastguard Worker #else
151*03ce13f7SAndroid Build Coastguard Worker 	for(size_t i = 0; i < count; i++)
152*03ce13f7SAndroid Build Coastguard Worker 	{
153*03ce13f7SAndroid Build Coastguard Worker 		memory[i] = element;
154*03ce13f7SAndroid Build Coastguard Worker 	}
155*03ce13f7SAndroid Build Coastguard Worker #endif
156*03ce13f7SAndroid Build Coastguard Worker }
157*03ce13f7SAndroid Build Coastguard Worker 
158*03ce13f7SAndroid Build Coastguard Worker }  // namespace sw
159