summaryrefslogtreecommitdiff
path: root/src/lj_alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_alloc.c')
-rw-r--r--src/lj_alloc.c52
1 files changed, 47 insertions, 5 deletions
diff --git a/src/lj_alloc.c b/src/lj_alloc.c
index 2f3fb473..8d4edb5e 100644
--- a/src/lj_alloc.c
+++ b/src/lj_alloc.c
@@ -23,7 +23,7 @@
23#define lj_alloc_c 23#define lj_alloc_c
24#define LUA_CORE 24#define LUA_CORE
25 25
26/* To get the mremap prototype. Must be defind before any system includes. */ 26/* To get the mremap prototype. Must be defined before any system includes. */
27#if defined(__linux__) && !defined(_GNU_SOURCE) 27#if defined(__linux__) && !defined(_GNU_SOURCE)
28#define _GNU_SOURCE 28#define _GNU_SOURCE
29#endif 29#endif
@@ -98,18 +98,22 @@ static void INIT_MMAP(void)
98/* Win64 32 bit MMAP via NtAllocateVirtualMemory. */ 98/* Win64 32 bit MMAP via NtAllocateVirtualMemory. */
99static LJ_AINLINE void *CALL_MMAP(size_t size) 99static LJ_AINLINE void *CALL_MMAP(size_t size)
100{ 100{
101 DWORD olderr = GetLastError();
101 void *ptr = NULL; 102 void *ptr = NULL;
102 long st = ntavm(INVALID_HANDLE_VALUE, &ptr, NTAVM_ZEROBITS, &size, 103 long st = ntavm(INVALID_HANDLE_VALUE, &ptr, NTAVM_ZEROBITS, &size,
103 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); 104 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
105 SetLastError(olderr);
104 return st == 0 ? ptr : MFAIL; 106 return st == 0 ? ptr : MFAIL;
105} 107}
106 108
107/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */ 109/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
108static LJ_AINLINE void *DIRECT_MMAP(size_t size) 110static LJ_AINLINE void *DIRECT_MMAP(size_t size)
109{ 111{
112 DWORD olderr = GetLastError();
110 void *ptr = NULL; 113 void *ptr = NULL;
111 long st = ntavm(INVALID_HANDLE_VALUE, &ptr, NTAVM_ZEROBITS, &size, 114 long st = ntavm(INVALID_HANDLE_VALUE, &ptr, NTAVM_ZEROBITS, &size,
112 MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, PAGE_READWRITE); 115 MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, PAGE_READWRITE);
116 SetLastError(olderr);
113 return st == 0 ? ptr : MFAIL; 117 return st == 0 ? ptr : MFAIL;
114} 118}
115 119
@@ -120,15 +124,19 @@ static LJ_AINLINE void *DIRECT_MMAP(size_t size)
120/* Win32 MMAP via VirtualAlloc */ 124/* Win32 MMAP via VirtualAlloc */
121static LJ_AINLINE void *CALL_MMAP(size_t size) 125static LJ_AINLINE void *CALL_MMAP(size_t size)
122{ 126{
127 DWORD olderr = GetLastError();
123 void *ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); 128 void *ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
129 SetLastError(olderr);
124 return ptr ? ptr : MFAIL; 130 return ptr ? ptr : MFAIL;
125} 131}
126 132
127/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */ 133/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
128static LJ_AINLINE void *DIRECT_MMAP(size_t size) 134static LJ_AINLINE void *DIRECT_MMAP(size_t size)
129{ 135{
136 DWORD olderr = GetLastError();
130 void *ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, 137 void *ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
131 PAGE_READWRITE); 138 PAGE_READWRITE);
139 SetLastError(olderr);
132 return ptr ? ptr : MFAIL; 140 return ptr ? ptr : MFAIL;
133} 141}
134 142
@@ -137,6 +145,7 @@ static LJ_AINLINE void *DIRECT_MMAP(size_t size)
137/* This function supports releasing coalesed segments */ 145/* This function supports releasing coalesed segments */
138static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size) 146static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size)
139{ 147{
148 DWORD olderr = GetLastError();
140 MEMORY_BASIC_INFORMATION minfo; 149 MEMORY_BASIC_INFORMATION minfo;
141 char *cptr = (char *)ptr; 150 char *cptr = (char *)ptr;
142 while (size) { 151 while (size) {
@@ -150,11 +159,13 @@ static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size)
150 cptr += minfo.RegionSize; 159 cptr += minfo.RegionSize;
151 size -= minfo.RegionSize; 160 size -= minfo.RegionSize;
152 } 161 }
162 SetLastError(olderr);
153 return 0; 163 return 0;
154} 164}
155 165
156#else 166#else
157 167
168#include <errno.h>
158#include <sys/mman.h> 169#include <sys/mman.h>
159 170
160#define MMAP_PROT (PROT_READ|PROT_WRITE) 171#define MMAP_PROT (PROT_READ|PROT_WRITE)
@@ -169,7 +180,13 @@ static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size)
169#if LJ_TARGET_LINUX 180#if LJ_TARGET_LINUX
170 181
171/* Actually this only gives us max. 1GB in current Linux kernels. */ 182/* Actually this only gives us max. 1GB in current Linux kernels. */
172#define CALL_MMAP(s) mmap(NULL, (s), MMAP_PROT, MAP_32BIT|MMAP_FLAGS, -1, 0) 183static LJ_AINLINE void *CALL_MMAP(size_t size)
184{
185 int olderr = errno;
186 void *ptr = mmap(NULL, size, MMAP_PROT, MAP_32BIT|MMAP_FLAGS, -1, 0);
187 errno = olderr;
188 return ptr;
189}
173 190
174#elif LJ_TARGET_OSX || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 191#elif LJ_TARGET_OSX || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
175 192
@@ -188,6 +205,7 @@ static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size)
188 205
189static LJ_AINLINE void *CALL_MMAP(size_t size) 206static LJ_AINLINE void *CALL_MMAP(size_t size)
190{ 207{
208 int olderr = errno;
191 /* Hint for next allocation. Doesn't need to be thread-safe. */ 209 /* Hint for next allocation. Doesn't need to be thread-safe. */
192 static uintptr_t alloc_hint = MMAP_REGION_START; 210 static uintptr_t alloc_hint = MMAP_REGION_START;
193 int retry = 0; 211 int retry = 0;
@@ -205,6 +223,7 @@ static LJ_AINLINE void *CALL_MMAP(size_t size)
205 if ((uintptr_t)p >= MMAP_REGION_START && 223 if ((uintptr_t)p >= MMAP_REGION_START &&
206 (uintptr_t)p + size < MMAP_REGION_END) { 224 (uintptr_t)p + size < MMAP_REGION_END) {
207 alloc_hint = (uintptr_t)p + size; 225 alloc_hint = (uintptr_t)p + size;
226 errno = olderr;
208 return p; 227 return p;
209 } 228 }
210 if (p != CMFAIL) munmap(p, size); 229 if (p != CMFAIL) munmap(p, size);
@@ -212,6 +231,7 @@ static LJ_AINLINE void *CALL_MMAP(size_t size)
212 retry = 1; 231 retry = 1;
213 alloc_hint = MMAP_REGION_START; 232 alloc_hint = MMAP_REGION_START;
214 } 233 }
234 errno = olderr;
215 return CMFAIL; 235 return CMFAIL;
216} 236}
217 237
@@ -224,17 +244,39 @@ static LJ_AINLINE void *CALL_MMAP(size_t size)
224#else 244#else
225 245
226/* 32 bit mode is easy. */ 246/* 32 bit mode is easy. */
227#define CALL_MMAP(s) mmap(NULL, (s), MMAP_PROT, MMAP_FLAGS, -1, 0) 247static LJ_AINLINE void *CALL_MMAP(size_t size)
248{
249 int olderr = errno;
250 void *ptr = mmap(NULL, size, MMAP_PROT, MMAP_FLAGS, -1, 0);
251 errno = olderr;
252 return ptr;
253}
228 254
229#endif 255#endif
230 256
231#define INIT_MMAP() ((void)0) 257#define INIT_MMAP() ((void)0)
232#define DIRECT_MMAP(s) CALL_MMAP(s) 258#define DIRECT_MMAP(s) CALL_MMAP(s)
233#define CALL_MUNMAP(a, s) munmap((a), (s)) 259
260static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size)
261{
262 int olderr = errno;
263 int ret = munmap(ptr, size);
264 errno = olderr;
265 return ret;
266}
234 267
235#if LJ_TARGET_LINUX 268#if LJ_TARGET_LINUX
236/* Need to define _GNU_SOURCE to get the mremap prototype. */ 269/* Need to define _GNU_SOURCE to get the mremap prototype. */
237#define CALL_MREMAP(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv)) 270static LJ_AINLINE void *CALL_MREMAP_(void *ptr, size_t osz, size_t nsz,
271 int flags)
272{
273 int olderr = errno;
274 ptr = mremap(ptr, osz, nsz, flags);
275 errno = olderr;
276 return ptr;
277}
278
279#define CALL_MREMAP(addr, osz, nsz, mv) CALL_MREMAP_((addr), (osz), (nsz), (mv))
238#define CALL_MREMAP_NOMOVE 0 280#define CALL_MREMAP_NOMOVE 0
239#define CALL_MREMAP_MAYMOVE 1 281#define CALL_MREMAP_MAYMOVE 1
240#if LJ_64 282#if LJ_64