aboutsummaryrefslogtreecommitdiff
path: root/src/lj_alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_alloc.c')
-rw-r--r--src/lj_alloc.c275
1 files changed, 182 insertions, 93 deletions
diff --git a/src/lj_alloc.c b/src/lj_alloc.c
index 9adaa0e5..165203fa 100644
--- a/src/lj_alloc.c
+++ b/src/lj_alloc.c
@@ -31,6 +31,7 @@
31#include "lj_def.h" 31#include "lj_def.h"
32#include "lj_arch.h" 32#include "lj_arch.h"
33#include "lj_alloc.h" 33#include "lj_alloc.h"
34#include "lj_prng.h"
34 35
35#ifndef LUAJIT_USE_SYSMALLOC 36#ifndef LUAJIT_USE_SYSMALLOC
36 37
@@ -72,15 +73,58 @@
72 73
73#define IS_DIRECT_BIT (SIZE_T_ONE) 74#define IS_DIRECT_BIT (SIZE_T_ONE)
74 75
76
77/* Determine system-specific block allocation method. */
75#if LJ_TARGET_WINDOWS 78#if LJ_TARGET_WINDOWS
76 79
77#define WIN32_LEAN_AND_MEAN 80#define WIN32_LEAN_AND_MEAN
78#include <windows.h> 81#include <windows.h>
79 82
83#define LJ_ALLOC_VIRTUALALLOC 1
84
85#if LJ_64 && !LJ_GC64
86#define LJ_ALLOC_NTAVM 1
87#endif
88
89#else
90
91#include <errno.h>
92/* If this include fails, then rebuild with: -DLUAJIT_USE_SYSMALLOC */
93#include <sys/mman.h>
94
95#define LJ_ALLOC_MMAP 1
96
80#if LJ_64 97#if LJ_64
81 98
99#define LJ_ALLOC_MMAP_PROBE 1
100
101#if LJ_GC64
102#define LJ_ALLOC_MBITS 47 /* 128 TB in LJ_GC64 mode. */
103#elif LJ_TARGET_X64 && LJ_HASJIT
104/* Due to limitations in the x64 compiler backend. */
105#define LJ_ALLOC_MBITS 31 /* 2 GB on x64 with !LJ_GC64. */
106#else
107#define LJ_ALLOC_MBITS 32 /* 4 GB on other archs with !LJ_GC64. */
108#endif
109
110#endif
111
112#if LJ_64 && !LJ_GC64 && defined(MAP_32BIT)
113#define LJ_ALLOC_MMAP32 1
114#endif
115
116#if LJ_TARGET_LINUX
117#define LJ_ALLOC_MREMAP 1
118#endif
119
120#endif
121
122
123#if LJ_ALLOC_VIRTUALALLOC
124
125#if LJ_ALLOC_NTAVM
82/* Undocumented, but hey, that's what we all love so much about Windows. */ 126/* Undocumented, but hey, that's what we all love so much about Windows. */
83typedef long (*PNTAVM)(HANDLE handle, void **addr, ULONG zbits, 127typedef long (*PNTAVM)(HANDLE handle, void **addr, ULONG_PTR zbits,
84 size_t *size, ULONG alloctype, ULONG prot); 128 size_t *size, ULONG alloctype, ULONG prot);
85static PNTAVM ntavm; 129static PNTAVM ntavm;
86 130
@@ -89,14 +133,15 @@ static PNTAVM ntavm;
89*/ 133*/
90#define NTAVM_ZEROBITS 1 134#define NTAVM_ZEROBITS 1
91 135
92static void INIT_MMAP(void) 136static void init_mmap(void)
93{ 137{
94 ntavm = (PNTAVM)GetProcAddress(GetModuleHandleA("ntdll.dll"), 138 ntavm = (PNTAVM)GetProcAddress(GetModuleHandleA("ntdll.dll"),
95 "NtAllocateVirtualMemory"); 139 "NtAllocateVirtualMemory");
96} 140}
141#define INIT_MMAP() init_mmap()
97 142
98/* Win64 32 bit MMAP via NtAllocateVirtualMemory. */ 143/* Win64 32 bit MMAP via NtAllocateVirtualMemory. */
99static LJ_AINLINE void *CALL_MMAP(size_t size) 144static void *mmap_plain(size_t size)
100{ 145{
101 DWORD olderr = GetLastError(); 146 DWORD olderr = GetLastError();
102 void *ptr = NULL; 147 void *ptr = NULL;
@@ -107,7 +152,7 @@ static LJ_AINLINE void *CALL_MMAP(size_t size)
107} 152}
108 153
109/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */ 154/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
110static LJ_AINLINE void *DIRECT_MMAP(size_t size) 155static void *direct_mmap(size_t size)
111{ 156{
112 DWORD olderr = GetLastError(); 157 DWORD olderr = GetLastError();
113 void *ptr = NULL; 158 void *ptr = NULL;
@@ -119,31 +164,32 @@ static LJ_AINLINE void *DIRECT_MMAP(size_t size)
119 164
120#else 165#else
121 166
122#define INIT_MMAP() ((void)0)
123
124/* Win32 MMAP via VirtualAlloc */ 167/* Win32 MMAP via VirtualAlloc */
125static LJ_AINLINE void *CALL_MMAP(size_t size) 168static void *mmap_plain(size_t size)
126{ 169{
127 DWORD olderr = GetLastError(); 170 DWORD olderr = GetLastError();
128 void *ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); 171 void *ptr = LJ_WIN_VALLOC(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
129 SetLastError(olderr); 172 SetLastError(olderr);
130 return ptr ? ptr : MFAIL; 173 return ptr ? ptr : MFAIL;
131} 174}
132 175
133/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */ 176/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
134static LJ_AINLINE void *DIRECT_MMAP(size_t size) 177static void *direct_mmap(size_t size)
135{ 178{
136 DWORD olderr = GetLastError(); 179 DWORD olderr = GetLastError();
137 void *ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, 180 void *ptr = LJ_WIN_VALLOC(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
138 PAGE_READWRITE); 181 PAGE_READWRITE);
139 SetLastError(olderr); 182 SetLastError(olderr);
140 return ptr ? ptr : MFAIL; 183 return ptr ? ptr : MFAIL;
141} 184}
142 185
143#endif 186#endif
144 187
188#define CALL_MMAP(prng, size) mmap_plain(size)
189#define DIRECT_MMAP(prng, size) direct_mmap(size)
190
145/* This function supports releasing coalesed segments */ 191/* This function supports releasing coalesed segments */
146static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size) 192static int CALL_MUNMAP(void *ptr, size_t size)
147{ 193{
148 DWORD olderr = GetLastError(); 194 DWORD olderr = GetLastError();
149 MEMORY_BASIC_INFORMATION minfo; 195 MEMORY_BASIC_INFORMATION minfo;
@@ -163,10 +209,7 @@ static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size)
163 return 0; 209 return 0;
164} 210}
165 211
166#else 212#elif LJ_ALLOC_MMAP
167
168#include <errno.h>
169#include <sys/mman.h>
170 213
171#define MMAP_PROT (PROT_READ|PROT_WRITE) 214#define MMAP_PROT (PROT_READ|PROT_WRITE)
172#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) 215#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
@@ -174,105 +217,134 @@ static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size)
174#endif 217#endif
175#define MMAP_FLAGS (MAP_PRIVATE|MAP_ANONYMOUS) 218#define MMAP_FLAGS (MAP_PRIVATE|MAP_ANONYMOUS)
176 219
177#if LJ_64 220#if LJ_ALLOC_MMAP_PROBE
178/* 64 bit mode needs special support for allocating memory in the lower 2GB. */
179 221
180#if defined(MAP_32BIT) 222#ifdef MAP_TRYFIXED
181 223#define MMAP_FLAGS_PROBE (MMAP_FLAGS|MAP_TRYFIXED)
182#if defined(__sun__)
183#define MMAP_REGION_START ((uintptr_t)0x1000)
184#else 224#else
185/* Actually this only gives us max. 1GB in current Linux kernels. */ 225#define MMAP_FLAGS_PROBE MMAP_FLAGS
186#define MMAP_REGION_START ((uintptr_t)0)
187#endif 226#endif
188 227
189static LJ_AINLINE void *CALL_MMAP(size_t size) 228#define LJ_ALLOC_MMAP_PROBE_MAX 30
229#define LJ_ALLOC_MMAP_PROBE_LINEAR 5
230
231#define LJ_ALLOC_MMAP_PROBE_LOWER ((uintptr_t)0x4000)
232
233static void *mmap_probe(PRNGState *rs, size_t size)
190{ 234{
235 /* Hint for next allocation. Doesn't need to be thread-safe. */
236 static uintptr_t hint_addr = 0;
191 int olderr = errno; 237 int olderr = errno;
192 void *ptr = mmap((void *)MMAP_REGION_START, size, MMAP_PROT, MAP_32BIT|MMAP_FLAGS, -1, 0); 238 int retry;
239 for (retry = 0; retry < LJ_ALLOC_MMAP_PROBE_MAX; retry++) {
240 void *p = mmap((void *)hint_addr, size, MMAP_PROT, MMAP_FLAGS_PROBE, -1, 0);
241 uintptr_t addr = (uintptr_t)p;
242 if ((addr >> LJ_ALLOC_MBITS) == 0 && addr >= LJ_ALLOC_MMAP_PROBE_LOWER &&
243 ((addr + size) >> LJ_ALLOC_MBITS) == 0) {
244 /* We got a suitable address. Bump the hint address. */
245 hint_addr = addr + size;
246 errno = olderr;
247 return p;
248 }
249 if (p != MFAIL) {
250 munmap(p, size);
251 } else if (errno == ENOMEM) {
252 return MFAIL;
253 }
254 if (hint_addr) {
255 /* First, try linear probing. */
256 if (retry < LJ_ALLOC_MMAP_PROBE_LINEAR) {
257 hint_addr += 0x1000000;
258 if (((hint_addr + size) >> LJ_ALLOC_MBITS) != 0)
259 hint_addr = 0;
260 continue;
261 } else if (retry == LJ_ALLOC_MMAP_PROBE_LINEAR) {
262 /* Next, try a no-hint probe to get back an ASLR address. */
263 hint_addr = 0;
264 continue;
265 }
266 }
267 /* Finally, try pseudo-random probing. */
268 do {
269 hint_addr = lj_prng_u64(rs) & (((uintptr_t)1<<LJ_ALLOC_MBITS)-LJ_PAGESIZE);
270 } while (hint_addr < LJ_ALLOC_MMAP_PROBE_LOWER);
271 }
193 errno = olderr; 272 errno = olderr;
194 return ptr; 273 return MFAIL;
195} 274}
196 275
197#elif LJ_TARGET_OSX || LJ_TARGET_PS4 || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__sun__) || LJ_TARGET_CYGWIN 276#endif
277
278#if LJ_ALLOC_MMAP32
198 279
199/* OSX and FreeBSD mmap() use a naive first-fit linear search. 280#if LJ_TARGET_SOLARIS
200** That's perfect for us. Except that -pagezero_size must be set for OSX, 281#define LJ_ALLOC_MMAP32_START ((uintptr_t)0x1000)
201** otherwise the lower 4GB are blocked. And the 32GB RLIMIT_DATA needs
202** to be reduced to 250MB on FreeBSD.
203*/
204#if LJ_TARGET_OSX || defined(__DragonFly__)
205#define MMAP_REGION_START ((uintptr_t)0x10000)
206#elif LJ_TARGET_PS4
207#define MMAP_REGION_START ((uintptr_t)0x4000)
208#else 282#else
209#define MMAP_REGION_START ((uintptr_t)0x10000000) 283#define LJ_ALLOC_MMAP32_START ((uintptr_t)0)
210#endif 284#endif
211#define MMAP_REGION_END ((uintptr_t)0x80000000)
212 285
213#if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) && !LJ_TARGET_PS4 286#if LJ_ALLOC_MMAP_PROBE
214#include <sys/resource.h> 287static void *mmap_map32(PRNGState *rs, size_t size)
288#else
289static void *mmap_map32(size_t size)
215#endif 290#endif
216
217static LJ_AINLINE void *CALL_MMAP(size_t size)
218{ 291{
219 int olderr = errno; 292#if LJ_ALLOC_MMAP_PROBE
220 /* Hint for next allocation. Doesn't need to be thread-safe. */ 293 static int fallback = 0;
221 static uintptr_t alloc_hint = MMAP_REGION_START; 294 if (fallback)
222 int retry = 0; 295 return mmap_probe(rs, size);
223#if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) && !LJ_TARGET_PS4
224 static int rlimit_modified = 0;
225 if (LJ_UNLIKELY(rlimit_modified == 0)) {
226 struct rlimit rlim;
227 rlim.rlim_cur = rlim.rlim_max = MMAP_REGION_START;
228 setrlimit(RLIMIT_DATA, &rlim); /* Ignore result. May fail below. */
229 rlimit_modified = 1;
230 }
231#endif 296#endif
232 for (;;) { 297 {
233 void *p = mmap((void *)alloc_hint, size, MMAP_PROT, MMAP_FLAGS, -1, 0); 298 int olderr = errno;
234 if ((uintptr_t)p >= MMAP_REGION_START && 299 void *ptr = mmap((void *)LJ_ALLOC_MMAP32_START, size, MMAP_PROT, MAP_32BIT|MMAP_FLAGS, -1, 0);
235 (uintptr_t)p + size < MMAP_REGION_END) { 300 errno = olderr;
236 alloc_hint = (uintptr_t)p + size; 301 /* This only allows 1GB on Linux. So fallback to probing to get 2GB. */
237 errno = olderr; 302#if LJ_ALLOC_MMAP_PROBE
238 return p; 303 if (ptr == MFAIL) {
304 fallback = 1;
305 return mmap_probe(rs, size);
239 } 306 }
240 if (p != CMFAIL) munmap(p, size);
241#if defined(__sun__) || defined(__DragonFly__)
242 alloc_hint += 0x1000000; /* Need near-exhaustive linear scan. */
243 if (alloc_hint + size < MMAP_REGION_END) continue;
244#endif 307#endif
245 if (retry) break; 308 return ptr;
246 retry = 1;
247 alloc_hint = MMAP_REGION_START;
248 } 309 }
249 errno = olderr;
250 return CMFAIL;
251} 310}
252 311
253#else
254
255#error "NYI: need an equivalent of MAP_32BIT for this 64 bit OS"
256
257#endif 312#endif
258 313
314#if LJ_ALLOC_MMAP32
315#if LJ_ALLOC_MMAP_PROBE
316#define CALL_MMAP(prng, size) mmap_map32(prng, size)
259#else 317#else
260 318#define CALL_MMAP(prng, size) mmap_map32(size)
261/* 32 bit mode is easy. */ 319#endif
262static LJ_AINLINE void *CALL_MMAP(size_t size) 320#elif LJ_ALLOC_MMAP_PROBE
321#define CALL_MMAP(prng, size) mmap_probe(prng, size)
322#else
323static void *mmap_plain(size_t size)
263{ 324{
264 int olderr = errno; 325 int olderr = errno;
265 void *ptr = mmap(NULL, size, MMAP_PROT, MMAP_FLAGS, -1, 0); 326 void *ptr = mmap(NULL, size, MMAP_PROT, MMAP_FLAGS, -1, 0);
266 errno = olderr; 327 errno = olderr;
267 return ptr; 328 return ptr;
268} 329}
269 330#define CALL_MMAP(prng, size) mmap_plain(size)
270#endif 331#endif
271 332
272#define INIT_MMAP() ((void)0) 333#if LJ_64 && !LJ_GC64 && ((defined(__FreeBSD__) && __FreeBSD__ < 10) || defined(__FreeBSD_kernel__)) && !LJ_TARGET_PS4
273#define DIRECT_MMAP(s) CALL_MMAP(s) 334
335#include <sys/resource.h>
274 336
275static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size) 337static void init_mmap(void)
338{
339 struct rlimit rlim;
340 rlim.rlim_cur = rlim.rlim_max = 0x10000;
341 setrlimit(RLIMIT_DATA, &rlim); /* Ignore result. May fail later. */
342}
343#define INIT_MMAP() init_mmap()
344
345#endif
346
347static int CALL_MUNMAP(void *ptr, size_t size)
276{ 348{
277 int olderr = errno; 349 int olderr = errno;
278 int ret = munmap(ptr, size); 350 int ret = munmap(ptr, size);
@@ -280,10 +352,9 @@ static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size)
280 return ret; 352 return ret;
281} 353}
282 354
283#if LJ_TARGET_LINUX 355#if LJ_ALLOC_MREMAP
284/* Need to define _GNU_SOURCE to get the mremap prototype. */ 356/* Need to define _GNU_SOURCE to get the mremap prototype. */
285static LJ_AINLINE void *CALL_MREMAP_(void *ptr, size_t osz, size_t nsz, 357static void *CALL_MREMAP_(void *ptr, size_t osz, size_t nsz, int flags)
286 int flags)
287{ 358{
288 int olderr = errno; 359 int olderr = errno;
289 ptr = mremap(ptr, osz, nsz, flags); 360 ptr = mremap(ptr, osz, nsz, flags);
@@ -294,7 +365,7 @@ static LJ_AINLINE void *CALL_MREMAP_(void *ptr, size_t osz, size_t nsz,
294#define CALL_MREMAP(addr, osz, nsz, mv) CALL_MREMAP_((addr), (osz), (nsz), (mv)) 365#define CALL_MREMAP(addr, osz, nsz, mv) CALL_MREMAP_((addr), (osz), (nsz), (mv))
295#define CALL_MREMAP_NOMOVE 0 366#define CALL_MREMAP_NOMOVE 0
296#define CALL_MREMAP_MAYMOVE 1 367#define CALL_MREMAP_MAYMOVE 1
297#if LJ_64 368#if LJ_64 && (!LJ_GC64 || LJ_TARGET_ARM64)
298#define CALL_MREMAP_MV CALL_MREMAP_NOMOVE 369#define CALL_MREMAP_MV CALL_MREMAP_NOMOVE
299#else 370#else
300#define CALL_MREMAP_MV CALL_MREMAP_MAYMOVE 371#define CALL_MREMAP_MV CALL_MREMAP_MAYMOVE
@@ -303,6 +374,15 @@ static LJ_AINLINE void *CALL_MREMAP_(void *ptr, size_t osz, size_t nsz,
303 374
304#endif 375#endif
305 376
377
378#ifndef INIT_MMAP
379#define INIT_MMAP() ((void)0)
380#endif
381
382#ifndef DIRECT_MMAP
383#define DIRECT_MMAP(prng, s) CALL_MMAP(prng, s)
384#endif
385
306#ifndef CALL_MREMAP 386#ifndef CALL_MREMAP
307#define CALL_MREMAP(addr, osz, nsz, mv) ((void)osz, MFAIL) 387#define CALL_MREMAP(addr, osz, nsz, mv) ((void)osz, MFAIL)
308#endif 388#endif
@@ -459,6 +539,7 @@ struct malloc_state {
459 mchunkptr smallbins[(NSMALLBINS+1)*2]; 539 mchunkptr smallbins[(NSMALLBINS+1)*2];
460 tbinptr treebins[NTREEBINS]; 540 tbinptr treebins[NTREEBINS];
461 msegment seg; 541 msegment seg;
542 PRNGState *prng;
462}; 543};
463 544
464typedef struct malloc_state *mstate; 545typedef struct malloc_state *mstate;
@@ -516,7 +597,7 @@ static int has_segment_link(mstate m, msegmentptr ss)
516 noncontiguous segments are added. 597 noncontiguous segments are added.
517*/ 598*/
518#define TOP_FOOT_SIZE\ 599#define TOP_FOOT_SIZE\
519 (align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE) 600 (align_offset(TWO_SIZE_T_SIZES)+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE)
520 601
521/* ---------------------------- Indexing Bins ---------------------------- */ 602/* ---------------------------- Indexing Bins ---------------------------- */
522 603
@@ -741,11 +822,11 @@ static int has_segment_link(mstate m, msegmentptr ss)
741 822
742/* ----------------------- Direct-mmapping chunks ----------------------- */ 823/* ----------------------- Direct-mmapping chunks ----------------------- */
743 824
744static void *direct_alloc(size_t nb) 825static void *direct_alloc(mstate m, size_t nb)
745{ 826{
746 size_t mmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK); 827 size_t mmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
747 if (LJ_LIKELY(mmsize > nb)) { /* Check for wrap around 0 */ 828 if (LJ_LIKELY(mmsize > nb)) { /* Check for wrap around 0 */
748 char *mm = (char *)(DIRECT_MMAP(mmsize)); 829 char *mm = (char *)(DIRECT_MMAP(m->prng, mmsize));
749 if (mm != CMFAIL) { 830 if (mm != CMFAIL) {
750 size_t offset = align_offset(chunk2mem(mm)); 831 size_t offset = align_offset(chunk2mem(mm));
751 size_t psize = mmsize - offset - DIRECT_FOOT_PAD; 832 size_t psize = mmsize - offset - DIRECT_FOOT_PAD;
@@ -757,6 +838,7 @@ static void *direct_alloc(size_t nb)
757 return chunk2mem(p); 838 return chunk2mem(p);
758 } 839 }
759 } 840 }
841 UNUSED(m);
760 return NULL; 842 return NULL;
761} 843}
762 844
@@ -905,7 +987,7 @@ static void *alloc_sys(mstate m, size_t nb)
905 987
906 /* Directly map large chunks */ 988 /* Directly map large chunks */
907 if (LJ_UNLIKELY(nb >= DEFAULT_MMAP_THRESHOLD)) { 989 if (LJ_UNLIKELY(nb >= DEFAULT_MMAP_THRESHOLD)) {
908 void *mem = direct_alloc(nb); 990 void *mem = direct_alloc(m, nb);
909 if (mem != 0) 991 if (mem != 0)
910 return mem; 992 return mem;
911 } 993 }
@@ -914,7 +996,7 @@ static void *alloc_sys(mstate m, size_t nb)
914 size_t req = nb + TOP_FOOT_SIZE + SIZE_T_ONE; 996 size_t req = nb + TOP_FOOT_SIZE + SIZE_T_ONE;
915 size_t rsize = granularity_align(req); 997 size_t rsize = granularity_align(req);
916 if (LJ_LIKELY(rsize > nb)) { /* Fail if wraps around zero */ 998 if (LJ_LIKELY(rsize > nb)) { /* Fail if wraps around zero */
917 char *mp = (char *)(CALL_MMAP(rsize)); 999 char *mp = (char *)(CALL_MMAP(m->prng, rsize));
918 if (mp != CMFAIL) { 1000 if (mp != CMFAIL) {
919 tbase = mp; 1001 tbase = mp;
920 tsize = rsize; 1002 tsize = rsize;
@@ -1141,12 +1223,13 @@ static void *tmalloc_small(mstate m, size_t nb)
1141 1223
1142/* ----------------------------------------------------------------------- */ 1224/* ----------------------------------------------------------------------- */
1143 1225
1144void *lj_alloc_create(void) 1226void *lj_alloc_create(PRNGState *rs)
1145{ 1227{
1146 size_t tsize = DEFAULT_GRANULARITY; 1228 size_t tsize = DEFAULT_GRANULARITY;
1147 char *tbase; 1229 char *tbase;
1148 INIT_MMAP(); 1230 INIT_MMAP();
1149 tbase = (char *)(CALL_MMAP(tsize)); 1231 UNUSED(rs);
1232 tbase = (char *)(CALL_MMAP(rs, tsize));
1150 if (tbase != CMFAIL) { 1233 if (tbase != CMFAIL) {
1151 size_t msize = pad_request(sizeof(struct malloc_state)); 1234 size_t msize = pad_request(sizeof(struct malloc_state));
1152 mchunkptr mn; 1235 mchunkptr mn;
@@ -1165,6 +1248,12 @@ void *lj_alloc_create(void)
1165 return NULL; 1248 return NULL;
1166} 1249}
1167 1250
1251void lj_alloc_setprng(void *msp, PRNGState *rs)
1252{
1253 mstate ms = (mstate)msp;
1254 ms->prng = rs;
1255}
1256
1168void lj_alloc_destroy(void *msp) 1257void lj_alloc_destroy(void *msp)
1169{ 1258{
1170 mstate ms = (mstate)msp; 1259 mstate ms = (mstate)msp;