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