blob: 723db3c5ea8d806a4dffc7114e26422ad0a8e96c [file] [log] [blame]
Nicolas Capens68a82382018-10-02 13:16:55 -04001// 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
Nicolas Capens68a82382018-10-02 13:16:55 -040017#include "Debug.hpp"
Ben Clayton595d9112019-12-17 20:37:57 +000018#include "Types.hpp"
Nicolas Capens68a82382018-10-02 13:16:55 -040019
20#if defined(_WIN32)
Ben Clayton595d9112019-12-17 20:37:57 +000021# ifndef WIN32_LEAN_AND_MEAN
22# define WIN32_LEAN_AND_MEAN
23# endif
24# include <windows.h>
25# include <intrin.h>
Nicolas Capens68a82382018-10-02 13:16:55 -040026#else
Ben Clayton595d9112019-12-17 20:37:57 +000027# include <errno.h>
28# include <sys/mman.h>
29# include <stdlib.h>
30# include <unistd.h>
Nicolas Capens68a82382018-10-02 13:16:55 -040031#endif
32
Nicolas Capens4cd9767e62019-07-11 01:13:55 -040033#include <cstdlib>
Ben Clayton595d9112019-12-17 20:37:57 +000034#include <cstring>
Nicolas Capens68a82382018-10-02 13:16:55 -040035
36#undef allocate
37#undef deallocate
38
Ben Clayton595d9112019-12-17 20:37:57 +000039#if(defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)) && !defined(__x86__)
40# define __x86__
Nicolas Capens68a82382018-10-02 13:16:55 -040041#endif
42
Nicolas Capens157ba262019-12-10 17:49:14 -050043namespace sw {
44
45namespace {
46
Nicolas Capens68a82382018-10-02 13:16:55 -040047struct Allocation
48{
Ben Clayton595d9112019-12-17 20:37:57 +000049 // size_t bytes;
Nicolas Capens68a82382018-10-02 13:16:55 -040050 unsigned char *block;
51};
52
53void *allocateRaw(size_t bytes, size_t alignment)
54{
Ben Clayton595d9112019-12-17 20:37:57 +000055 ASSERT((alignment & (alignment - 1)) == 0); // Power of 2 alignment.
Nicolas Capens68a82382018-10-02 13:16:55 -040056
Ben Clayton595d9112019-12-17 20:37:57 +000057#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)
Nicolas Capens68a82382018-10-02 13:16:55 -040067 {
Ben Clayton595d9112019-12-17 20:37:57 +000068 errno = result;
69 allocation = nullptr;
Nicolas Capens68a82382018-10-02 13:16:55 -040070 }
Ben Clayton595d9112019-12-17 20:37:57 +000071 return allocation;
72 }
73#else
74 unsigned char *block = (unsigned char *)malloc(bytes + sizeof(Allocation) + alignment);
75 unsigned char *aligned = nullptr;
Nicolas Capens68a82382018-10-02 13:16:55 -040076
Ben Clayton595d9112019-12-17 20:37:57 +000077 if(block)
78 {
79 aligned = (unsigned char *)((uintptr_t)(block + sizeof(Allocation) + alignment - 1) & -(intptr_t)alignment);
80 Allocation *allocation = (Allocation *)(aligned - sizeof(Allocation));
Nicolas Capens68a82382018-10-02 13:16:55 -040081
82 // allocation->bytes = bytes;
Ben Clayton595d9112019-12-17 20:37:57 +000083 allocation->block = block;
84 }
Nicolas Capens68a82382018-10-02 13:16:55 -040085
Ben Clayton595d9112019-12-17 20:37:57 +000086 return aligned;
87#endif
Nicolas Capens68a82382018-10-02 13:16:55 -040088}
Nicolas Capens157ba262019-12-10 17:49:14 -050089
Nicolas Capens68a82382018-10-02 13:16:55 -040090} // anonymous namespace
91
92size_t memoryPageSize()
93{
94 static int pageSize = 0;
95
96 if(pageSize == 0)
97 {
Ben Clayton595d9112019-12-17 20:37:57 +000098#if defined(_WIN32)
99 SYSTEM_INFO systemInfo;
100 GetSystemInfo(&systemInfo);
101 pageSize = systemInfo.dwPageSize;
102#else
103 pageSize = sysconf(_SC_PAGESIZE);
104#endif
Nicolas Capens68a82382018-10-02 13:16:55 -0400105 }
106
107 return pageSize;
108}
109
110void *allocate(size_t bytes, size_t alignment)
111{
112 void *memory = allocateRaw(bytes, alignment);
113
114 if(memory)
115 {
116 memset(memory, 0, bytes);
117 }
118
119 return memory;
120}
121
122void deallocate(void *memory)
123{
Ben Clayton595d9112019-12-17 20:37:57 +0000124#if defined(LINUX_ENABLE_NAMED_MMAP)
125 free(memory);
126#else
127 if(memory)
128 {
129 unsigned char *aligned = (unsigned char *)memory;
130 Allocation *allocation = (Allocation *)(aligned - sizeof(Allocation));
Nicolas Capens68a82382018-10-02 13:16:55 -0400131
Ben Clayton595d9112019-12-17 20:37:57 +0000132 free(allocation->block);
133 }
134#endif
Nicolas Capens68a82382018-10-02 13:16:55 -0400135}
136
Nicolas Capens68a82382018-10-02 13:16:55 -0400137void clear(uint16_t *memory, uint16_t element, size_t count)
138{
Ben Clayton595d9112019-12-17 20:37:57 +0000139#if defined(_MSC_VER) && defined(__x86__) && !defined(MEMORY_SANITIZER)
140 __stosw(memory, element, count);
141#elif defined(__GNUC__) && defined(__x86__) && !defined(MEMORY_SANITIZER)
142 __asm__ __volatile__("rep stosw"
143 : "+D"(memory), "+c"(count)
144 : "a"(element)
145 : "memory");
146#else
147 for(size_t i = 0; i < count; i++)
148 {
149 memory[i] = element;
150 }
151#endif
Nicolas Capens68a82382018-10-02 13:16:55 -0400152}
153
154void clear(uint32_t *memory, uint32_t element, size_t count)
155{
Ben Clayton595d9112019-12-17 20:37:57 +0000156#if defined(_MSC_VER) && defined(__x86__) && !defined(MEMORY_SANITIZER)
157 __stosd((unsigned long *)memory, element, count);
158#elif defined(__GNUC__) && defined(__x86__) && !defined(MEMORY_SANITIZER)
159 __asm__ __volatile__("rep stosl"
160 : "+D"(memory), "+c"(count)
161 : "a"(element)
162 : "memory");
163#else
164 for(size_t i = 0; i < count; i++)
165 {
166 memory[i] = element;
167 }
168#endif
Nicolas Capens68a82382018-10-02 13:16:55 -0400169}
Nicolas Capens157ba262019-12-10 17:49:14 -0500170
171} // namespace sw