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