diff options
Diffstat (limited to 'src/lj_alloc.c')
-rw-r--r-- | src/lj_alloc.c | 52 |
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. */ |
99 | static LJ_AINLINE void *CALL_MMAP(size_t size) | 99 | static 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 */ |
108 | static LJ_AINLINE void *DIRECT_MMAP(size_t size) | 110 | static 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 */ |
121 | static LJ_AINLINE void *CALL_MMAP(size_t size) | 125 | static 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 */ |
128 | static LJ_AINLINE void *DIRECT_MMAP(size_t size) | 134 | static 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 */ |
138 | static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size) | 146 | static 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) | 183 | static 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 | ||
189 | static LJ_AINLINE void *CALL_MMAP(size_t size) | 206 | static 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) | 247 | static 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 | |
260 | static 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)) | 270 | static 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 |