aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Germain <bnt.germain@gmail.com>2023-08-09 12:15:54 +0200
committerBenoit Germain <bnt.germain@gmail.com>2023-08-09 12:15:54 +0200
commitad7258f68ce525845508fc0c4a329c282982ffa0 (patch)
treef6eb169911eef0a776f3b3b00eeb2b7d824ebbd7
parentd73f4cee37b0a43edadf9709289798ee4bfccc0e (diff)
downloadlanes-ad7258f68ce525845508fc0c4a329c282982ffa0.tar.gz
lanes-ad7258f68ce525845508fc0c4a329c282982ffa0.tar.bz2
lanes-ad7258f68ce525845508fc0c4a329c282982ffa0.zip
new .internal_allocator configuration IUNTESTED)
new configuration option .internal_allocator to help LuaJIT users. THIS IS YET UNTESTED, USE AT YOUR OWN RISKS.
-rw-r--r--.vs/Lanes/FileContentIndex/7013d1f4-51ff-4696-9603-47b7bcd2f51f.vsidxbin0 -> 400863 bytes
-rw-r--r--CHANGES4
-rw-r--r--docs/index.html34
-rw-r--r--src/deep.c2
-rw-r--r--src/keeper.c20
-rw-r--r--src/keeper.h2
-rw-r--r--src/lanes.c16
-rw-r--r--src/lanes.h2
-rw-r--r--src/lanes.lua8
-rw-r--r--src/linda.c14
-rw-r--r--src/macros_and_utils.h3
-rw-r--r--src/tools.c38
-rw-r--r--src/universe.h2
13 files changed, 83 insertions, 62 deletions
diff --git a/.vs/Lanes/FileContentIndex/7013d1f4-51ff-4696-9603-47b7bcd2f51f.vsidx b/.vs/Lanes/FileContentIndex/7013d1f4-51ff-4696-9603-47b7bcd2f51f.vsidx
new file mode 100644
index 0000000..7c4c705
--- /dev/null
+++ b/.vs/Lanes/FileContentIndex/7013d1f4-51ff-4696-9603-47b7bcd2f51f.vsidx
Binary files differ
diff --git a/CHANGES b/CHANGES
index 3b333b2..3c7f356 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,9 @@
1CHANGES: 1CHANGES:
2 2
3CHANGE 156: BGe 9-Aug-23
4 * new configuration option .internal_allocator to help LuaJIT users.
5 * internal version bumped to 3.16.1
6
3CHANGE 155: BGe 28-Jul-23 7CHANGE 155: BGe 28-Jul-23
4 * tweaks to linux thread priority management: do nothing if not super-user. if super-user, do nothing if nothing is provided (instead of trying to force a prio when LINUX_SCHED_RR is defined). 8 * tweaks to linux thread priority management: do nothing if not super-user. if super-user, do nothing if nothing is provided (instead of trying to force a prio when LINUX_SCHED_RR is defined).
5 9
diff --git a/docs/index.html b/docs/index.html
index 0e1a30b..b1c514d 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -64,13 +64,13 @@
64 <font size="-1"> 64 <font size="-1">
65 <p> 65 <p>
66 <br/> 66 <br/>
67 <i>Copyright &copy; 2007-22 Asko Kauppi, Benoit Germain. All rights reserved.</i> 67 <i>Copyright &copy; 2007-23 Asko Kauppi, Benoit Germain. All rights reserved.</i>
68 <br/> 68 <br/>
69 Lua Lanes is published under the same <a href="http://en.wikipedia.org/wiki/MIT_License">MIT license</a> as Lua 5.1, 5.2, 5.3 and 5.4. 69 Lua Lanes is published under the same <a href="http://en.wikipedia.org/wiki/MIT_License">MIT license</a> as Lua 5.1, 5.2, 5.3 and 5.4.
70 </p> 70 </p>
71 71
72 <p> 72 <p>
73 This document was revised on 8-Feb-22, and applies to version <tt>3.16.0</tt>. 73 This document was revised on 9-Aug-23, and applies to version <tt>3.16.1</tt>.
74 </p> 74 </p>
75 </font> 75 </font>
76 </center> 76 </center>
@@ -338,9 +338,9 @@
338 <tt>nil</tt>/<tt>"protected"</tt>/function 338 <tt>nil</tt>/<tt>"protected"</tt>/function
339 </td> 339 </td>
340 <td> 340 <td>
341 (Since v3.13.0)<br/> 341 (Since v3.13.0)<br />
342 If <tt>nil</tt>, Lua states are created with <tt>lua_newstate()</tt> and reuse the allocator from the master state.<br/> 342 If <tt>nil</tt>, Lua states are created with <tt>lua_newstate()</tt> and reuse the allocator from the master state.<br />
343 If <tt>"protected"</tt>, The default allocator obtained from <tt>lua_getallocf()</tt> in the master state is wrapped inside a critical section and used in all newly created states.<br/> 343 If <tt>"protected"</tt>, The default allocator obtained from <tt>lua_getallocf()</tt> in the master state is wrapped inside a critical section and used in all newly created states.<br />
344 If a <tt>function</tt>, this function is called prior to creating the state. It should return a full userdata containing the following structure: 344 If a <tt>function</tt>, this function is called prior to creating the state. It should return a full userdata containing the following structure:
345 <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"> 345 <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%">
346 <tr> 346 <tr>
@@ -356,6 +356,22 @@
356 </tr> 356 </tr>
357 357
358 <tr valign=top> 358 <tr valign=top>
359 <td id="internal_allocator">
360 <code>.internal_allocator</code>
361 </td>
362 <td>
363 <tt>"libc"</tt>/<tt>"allocator"</tt>
364 </td>
365 <td>
366 (Since v3.16.1)<br />
367 Controls which allocator is used for Lanest internal allocations (for keeper and deep userdata management).
368 If <tt>"libc"</tt>, Lanes uses <tt>realloc</tt> and <tt>free</tt>.<br />
369 If <tt>"allocator"</tt>, Lanes uses whatever was obtained from the <tt>"allocator"</tt> setting.<br />
370 This option is mostly useful for embedders that want control all memory allocations, but have issues when Lanes tries to use the Lua State allocator for internal purposes (especially with LuaJIT).
371 </td>
372 </tr>
373
374 <tr valign=top>
359 <td id="demote_full_userdata"> 375 <td id="demote_full_userdata">
360 <code>.demote_full_userdata</code> 376 <code>.demote_full_userdata</code>
361 </td> 377 </td>
@@ -390,18 +406,18 @@
390 </td> 406 </td>
391 <td> 407 <td>
392 If provided, will be called in every created Lua state right after initializing the base libraries. 408 If provided, will be called in every created Lua state right after initializing the base libraries.
393 <br/> 409 <br />
394 Keeper states will call it as well, but only if it is a C function (keeper states are not able to execute any user Lua code). 410 Keeper states will call it as well, but only if it is a C function (keeper states are not able to execute any user Lua code).
395 <br/> 411 <br />
396 Typical usage is twofold: 412 Typical usage is twofold:
397 <ul> 413 <ul>
398 <li>Tweak <tt>package.loaders</tt></li> 414 <li>Tweak <tt>package.loaders</tt></li>
399 <li>Load some additional C functions in the global space (of course only a C function will be able to do this).</li> 415 <li>Load some additional C functions in the global space (of course only a C function will be able to do this).</li>
400 </ul> 416 </ul>
401 That way, all changes in the state can be properly taken into account when building the function lookup database. Default is <tt>nil</tt>. 417 That way, all changes in the state can be properly taken into account when building the function lookup database. Default is <tt>nil</tt>.
402 <br/> 418 <br />
403 (Since version 3.7.6) If <tt>on_state_create()</tt> is a Lua function, it will be transfered normally before the call. 419 (Since version 3.7.6) If <tt>on_state_create()</tt> is a Lua function, it will be transfered normally before the call.
404 <br/> 420 <br />
405 If it is a C function, a C closure will be reconstructed in the created state from the C pointer. Lanes will raise an error if the function has upvalues. 421 If it is a C function, a C closure will be reconstructed in the created state from the C pointer. Lanes will raise an error if the function has upvalues.
406 </td> 422 </td>
407 </tr> 423 </tr>
diff --git a/src/deep.c b/src/deep.c
index c475dc5..9496477 100644
--- a/src/deep.c
+++ b/src/deep.c
@@ -389,7 +389,7 @@ int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc, int nuv_)
389 DeepPrelude* prelude = idfunc( L, eDO_new); 389 DeepPrelude* prelude = idfunc( L, eDO_new);
390 if( prelude == NULL) 390 if( prelude == NULL)
391 { 391 {
392 luaL_error( L, "idfunc(eDO_new) failed to create deep userdata (out of memory)"); 392 return luaL_error( L, "idfunc(eDO_new) failed to create deep userdata (out of memory)");
393 } 393 }
394 if( prelude->magic.value != DEEP_VERSION.value) 394 if( prelude->magic.value != DEEP_VERSION.value)
395 { 395 {
diff --git a/src/keeper.c b/src/keeper.c
index 19b9e1a..f4dde0a 100644
--- a/src/keeper.c
+++ b/src/keeper.c
@@ -580,7 +580,7 @@ int keepercall_count( lua_State* L)
580*/ 580*/
581 581
582// called as __gc for the keepers array userdata 582// called as __gc for the keepers array userdata
583void close_keepers( Universe* U, lua_State* L) 583void close_keepers( Universe* U)
584{ 584{
585 if( U->keepers != NULL) 585 if( U->keepers != NULL)
586 { 586 {
@@ -611,15 +611,8 @@ void close_keepers( Universe* U, lua_State* L)
611 } 611 }
612 // free the keeper bookkeeping structure 612 // free the keeper bookkeeping structure
613 { 613 {
614 // don't hijack the state allocator when running LuaJIT because it looks like LuaJIT does not expect it and might invalidate the memory unexpectedly 614 AllocatorDefinition* const allocD = &U->internal_allocator;
615#if USE_LUA_STATE_ALLOCATOR() 615 allocD->allocF( allocD->allocUD, U->keepers, sizeof( Keepers) + (nbKeepers - 1) * sizeof( Keeper), 0);
616 {
617 AllocatorDefinition* const allocD = &U->protected_allocator.definition;
618 allocD->allocF( allocD->allocUD, U->keepers, sizeof( Keepers) + (nbKeepers - 1) * sizeof( Keeper), 0);
619 }
620#else // USE_LUA_STATE_ALLOCATOR()
621 free(U->keepers);
622#endif // USE_LUA_STATE_ALLOCATOR()
623 U->keepers = NULL; 616 U->keepers = NULL;
624 } 617 }
625 } 618 }
@@ -653,15 +646,10 @@ void init_keepers( Universe* U, lua_State* L)
653 // Keepers contains an array of 1 s_Keeper, adjust for the actual number of keeper states 646 // Keepers contains an array of 1 s_Keeper, adjust for the actual number of keeper states
654 { 647 {
655 size_t const bytes = sizeof( Keepers) + (nb_keepers - 1) * sizeof( Keeper); 648 size_t const bytes = sizeof( Keepers) + (nb_keepers - 1) * sizeof( Keeper);
656 // don't hijack the state allocator when running LuaJIT because it looks like LuaJIT does not expect it and might invalidate the memory unexpectedly
657#if USE_LUA_STATE_ALLOCATOR()
658 { 649 {
659 AllocatorDefinition* const allocD = &U->protected_allocator.definition; 650 AllocatorDefinition* const allocD = &U->internal_allocator;
660 U->keepers = (Keepers*) allocD->allocF( allocD->allocUD, NULL, 0, bytes); 651 U->keepers = (Keepers*) allocD->allocF( allocD->allocUD, NULL, 0, bytes);
661 } 652 }
662#else // USE_LUA_STATE_ALLOCATOR()
663 U->keepers = (Keepers*)malloc(bytes);
664#endif // USE_LUA_STATE_ALLOCATOR()
665 if( U->keepers == NULL) 653 if( U->keepers == NULL)
666 { 654 {
667 (void) luaL_error( L, "init_keepers() failed while creating keeper array; out of memory"); 655 (void) luaL_error( L, "init_keepers() failed while creating keeper array; out of memory");
diff --git a/src/keeper.h b/src/keeper.h
index 8c09322..d30aa36 100644
--- a/src/keeper.h
+++ b/src/keeper.h
@@ -27,7 +27,7 @@ struct s_Keepers
27typedef struct s_Keepers Keepers; 27typedef struct s_Keepers Keepers;
28 28
29void init_keepers( Universe* U, lua_State* L); 29void init_keepers( Universe* U, lua_State* L);
30void close_keepers( Universe* U, lua_State* L); 30void close_keepers( Universe* U);
31 31
32Keeper* which_keeper( Keepers* keepers_, ptrdiff_t magic_); 32Keeper* which_keeper( Keepers* keepers_, ptrdiff_t magic_);
33Keeper* keeper_acquire( Keepers* keepers_, ptrdiff_t magic_); 33Keeper* keeper_acquire( Keepers* keepers_, ptrdiff_t magic_);
diff --git a/src/lanes.c b/src/lanes.c
index 9f6a4d6..0aab244 100644
--- a/src/lanes.c
+++ b/src/lanes.c
@@ -253,15 +253,10 @@ static void lane_cleanup( Lane* s)
253 } 253 }
254#endif // HAVE_LANE_TRACKING() 254#endif // HAVE_LANE_TRACKING()
255 255
256 // don't hijack the state allocator when running LuaJIT because it looks like LuaJIT does not expect it and might invalidate the memory unexpectedly
257#if USE_LUA_STATE_ALLOCATOR()
258 { 256 {
259 AllocatorDefinition* const allocD = &s->U->protected_allocator.definition; 257 AllocatorDefinition* const allocD = &s->U->internal_allocator;
260 allocD->allocF(allocD->allocUD, s, sizeof(Lane), 0); 258 allocD->allocF(allocD->allocUD, s, sizeof(Lane), 0);
261 } 259 }
262#else // USE_LUA_STATE_ALLOCATOR()
263 free(s);
264#endif // USE_LUA_STATE_ALLOCATOR()
265} 260}
266 261
267/* 262/*
@@ -584,7 +579,7 @@ static int selfdestruct_gc( lua_State* L)
584 U->timer_deep = NULL; 579 U->timer_deep = NULL;
585 } 580 }
586 581
587 close_keepers( U, L); 582 close_keepers( U);
588 583
589 // remove the protected allocator, if any 584 // remove the protected allocator, if any
590 cleanup_allocator_function( U, L); 585 cleanup_allocator_function( U, L);
@@ -1231,15 +1226,10 @@ LUAG_FUNC( lane_new)
1231 // 1226 //
1232 // a Lane full userdata needs a single uservalue 1227 // a Lane full userdata needs a single uservalue
1233 ud = lua_newuserdatauv( L, sizeof( Lane*), 1); // func libs priority globals package required gc_cb lane 1228 ud = lua_newuserdatauv( L, sizeof( Lane*), 1); // func libs priority globals package required gc_cb lane
1234 // don't hijack the state allocator when running LuaJIT because it looks like LuaJIT does not expect it and might invalidate the memory unexpectedly
1235#if USE_LUA_STATE_ALLOCATOR()
1236 { 1229 {
1237 AllocatorDefinition* const allocD = &U->protected_allocator.definition; 1230 AllocatorDefinition* const allocD = &U->internal_allocator;
1238 s = *ud = (Lane*)allocD->allocF(allocD->allocUD, NULL, 0, sizeof(Lane)); 1231 s = *ud = (Lane*)allocD->allocF(allocD->allocUD, NULL, 0, sizeof(Lane));
1239 } 1232 }
1240#else // USE_LUA_STATE_ALLOCATOR()
1241 s = *ud = (Lane*) malloc(sizeof(Lane));
1242#endif // USE_LUA_STATE_ALLOCATOR()
1243 if( s == NULL) 1233 if( s == NULL)
1244 { 1234 {
1245 return luaL_error( L, "could not create lane: out of memory"); 1235 return luaL_error( L, "could not create lane: out of memory");
diff --git a/src/lanes.h b/src/lanes.h
index 20524e6..420b31d 100644
--- a/src/lanes.h
+++ b/src/lanes.h
@@ -12,7 +12,7 @@
12 12
13#define LANES_VERSION_MAJOR 3 13#define LANES_VERSION_MAJOR 3
14#define LANES_VERSION_MINOR 16 14#define LANES_VERSION_MINOR 16
15#define LANES_VERSION_PATCH 0 15#define LANES_VERSION_PATCH 1
16 16
17#define LANES_MIN_VERSION_REQUIRED(MAJOR, MINOR, PATCH) ((LANES_VERSION_MAJOR>MAJOR) || (LANES_VERSION_MAJOR==MAJOR && (LANES_VERSION_MINOR>MINOR || (LANES_VERSION_MINOR==MINOR && LANES_VERSION_PATCH>=PATCH)))) 17#define LANES_MIN_VERSION_REQUIRED(MAJOR, MINOR, PATCH) ((LANES_VERSION_MAJOR>MAJOR) || (LANES_VERSION_MAJOR==MAJOR && (LANES_VERSION_MINOR>MINOR || (LANES_VERSION_MINOR==MINOR && LANES_VERSION_PATCH>=PATCH))))
18#define LANES_VERSION_LESS_THAN(MAJOR, MINOR, PATCH) ((LANES_VERSION_MAJOR<MAJOR) || (LANES_VERSION_MAJOR==MAJOR && (LANES_VERSION_MINOR<MINOR || (LANES_VERSION_MINOR==MINOR && LANES_VERSION_PATCH<PATCH)))) 18#define LANES_VERSION_LESS_THAN(MAJOR, MINOR, PATCH) ((LANES_VERSION_MAJOR<MAJOR) || (LANES_VERSION_MAJOR==MAJOR && (LANES_VERSION_MINOR<MINOR || (LANES_VERSION_MINOR==MINOR && LANES_VERSION_PATCH<PATCH))))
diff --git a/src/lanes.lua b/src/lanes.lua
index 0858ad7..cbcf74f 100644
--- a/src/lanes.lua
+++ b/src/lanes.lua
@@ -77,7 +77,9 @@ lanes.configure = function( settings_)
77 demote_full_userdata = nil, 77 demote_full_userdata = nil,
78 verbose_errors = false, 78 verbose_errors = false,
79 -- LuaJIT provides a thread-unsafe allocator by default, so we need to protect it when used in parallel lanes 79 -- LuaJIT provides a thread-unsafe allocator by default, so we need to protect it when used in parallel lanes
80 allocator = (package.loaded.jit and jit.version) and "protected" or nil 80 allocator = (package.loaded.jit and jit.version) and "protected" or nil,
81 -- it looks also like LuaJIT allocator may not appreciate direct use of its allocator for other purposes than the VM operation
82 internal_allocator = (package.loaded.jit and jit.version) and "libc" or "allocator"
81 } 83 }
82 local boolean_param_checker = function( val_) 84 local boolean_param_checker = function( val_)
83 -- non-'boolean-false' should be 'boolean-true' or nil 85 -- non-'boolean-false' should be 'boolean-true' or nil
@@ -94,6 +96,10 @@ lanes.configure = function( settings_)
94 -- can be nil, "protected", or a function 96 -- can be nil, "protected", or a function
95 return val_ and (type( val_) == "function" or val_ == "protected") or true 97 return val_ and (type( val_) == "function" or val_ == "protected") or true
96 end, 98 end,
99 internal_allocator = function( val_)
100 -- can be "libc" or "allocator"
101 return val_ == "libc" or val_ == "allocator"
102 end,
97 on_state_create = function( val_) 103 on_state_create = function( val_)
98 -- on_state_create may be nil or a function 104 -- on_state_create may be nil or a function
99 return val_ and type( val_) == "function" or true 105 return val_ and type( val_) == "function" or true
diff --git a/src/linda.c b/src/linda.c
index 637f909..390816b 100644
--- a/src/linda.c
+++ b/src/linda.c
@@ -794,17 +794,12 @@ static void* linda_id( lua_State* L, DeepOp op_)
794 * One can use any memory allocation scheme. 794 * One can use any memory allocation scheme.
795 * just don't use L's allocF because we don't know which state will get the honor of GCing the linda 795 * just don't use L's allocF because we don't know which state will get the honor of GCing the linda
796 */ 796 */
797 // don't hijack the state allocator when running LuaJIT because it looks like LuaJIT does not expect it and might invalidate the memory unexpectedly
798#if USE_LUA_STATE_ALLOCATOR()
799 { 797 {
800 Universe* const U = universe_get(L); 798 Universe* const U = universe_get(L);
801 AllocatorDefinition* const allocD = &U->protected_allocator.definition; 799 AllocatorDefinition* const allocD = &U->internal_allocator;
802 800
803 s = (struct s_Linda*)allocD->allocF(allocD->allocUD, NULL, 0, sizeof(struct s_Linda) + name_len); // terminating 0 is already included 801 s = (struct s_Linda*)allocD->allocF(allocD->allocUD, NULL, 0, sizeof(struct s_Linda) + name_len); // terminating 0 is already included
804 } 802 }
805#else // USE_LUA_STATE_ALLOCATOR()
806 s = (struct s_Linda*)malloc(sizeof(struct s_Linda) + name_len); // terminating 0 is already included
807#endif // USE_LUA_STATE_ALLOCATOR()
808 if( s) 803 if( s)
809 { 804 {
810 s->prelude.magic.value = DEEP_VERSION.value; 805 s->prelude.magic.value = DEEP_VERSION.value;
@@ -837,17 +832,12 @@ static void* linda_id( lua_State* L, DeepOp op_)
837 // There aren't any lanes waiting on these lindas, since all proxies have been gc'ed. Right? 832 // There aren't any lanes waiting on these lindas, since all proxies have been gc'ed. Right?
838 SIGNAL_FREE( &linda->read_happened); 833 SIGNAL_FREE( &linda->read_happened);
839 SIGNAL_FREE( &linda->write_happened); 834 SIGNAL_FREE( &linda->write_happened);
840 // don't hijack the state allocator when running LuaJIT because it looks like LuaJIT does not expect it and might invalidate the memory unexpectedly
841#if USE_LUA_STATE_ALLOCATOR()
842 { 835 {
843 Universe* const U = universe_get(L); 836 Universe* const U = universe_get(L);
844 AllocatorDefinition* const allocD = &U->protected_allocator.definition; 837 AllocatorDefinition* const allocD = &U->internal_allocator;
845 838
846 allocD->allocF(allocD->allocUD, linda, sizeof(struct s_Linda) + strlen(linda->name), 0); 839 allocD->allocF(allocD->allocUD, linda, sizeof(struct s_Linda) + strlen(linda->name), 0);
847 } 840 }
848#else // USE_LUA_STATE_ALLOCATOR()
849 free(linda);
850#endif // USE_LUA_STATE_ALLOCATOR()
851 return NULL; 841 return NULL;
852 } 842 }
853 843
diff --git a/src/macros_and_utils.h b/src/macros_and_utils.h
index 3ed234a..05a46b5 100644
--- a/src/macros_and_utils.h
+++ b/src/macros_and_utils.h
@@ -99,7 +99,4 @@ extern char const* debugspew_indent;
99 99
100#define LUAG_FUNC( func_name) int LG_##func_name( lua_State* L) 100#define LUAG_FUNC( func_name) int LG_##func_name( lua_State* L)
101 101
102// after all, it looks like we can use the state allocator for our own usage when running LuaJIT, as long as we mutex-protect it
103#define USE_LUA_STATE_ALLOCATOR() 1 // (LUAJIT_FLAVOR()==0)
104
105#endif // MACROS_AND_UTILS_H 102#endif // MACROS_AND_UTILS_H
diff --git a/src/tools.c b/src/tools.c
index 626da2b..5a6ae92 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -155,6 +155,20 @@ void luaG_dump( lua_State* L)
155 155
156// ################################################################################################ 156// ################################################################################################
157 157
158static void* libc_lua_Alloc(void* ud, void* ptr, size_t osize, size_t nsize)
159{
160 (void)ud; (void)osize; /* not used */
161 if (nsize == 0)
162 {
163 free(ptr);
164 return NULL;
165 }
166 else
167 {
168 return realloc(ptr, nsize);
169 }
170}
171
158static void* protected_lua_Alloc( void *ud, void *ptr, size_t osize, size_t nsize) 172static void* protected_lua_Alloc( void *ud, void *ptr, size_t osize, size_t nsize)
159{ 173{
160 void* p; 174 void* p;
@@ -217,6 +231,22 @@ void initialize_allocator_function( Universe* U, lua_State* L)
217 U->protected_allocator.definition.allocF = lua_getallocf( L, &U->protected_allocator.definition.allocUD); 231 U->protected_allocator.definition.allocF = lua_getallocf( L, &U->protected_allocator.definition.allocUD);
218 } 232 }
219 lua_pop( L, 1); // settings 233 lua_pop( L, 1); // settings
234 STACK_MID(L, 0);
235
236 lua_getfield( L, -1, "internal_allocator"); // settings "libc"|"allocator"
237 {
238 char const* allocator = lua_tostring( L, -1);
239 if (stricmp(allocator, "libc") == 0)
240 {
241 U->internal_allocator.allocF = libc_lua_Alloc;
242 U->internal_allocator.allocUD = NULL;
243 }
244 else
245 {
246 U->internal_allocator = U->protected_allocator.definition;
247 }
248 }
249 lua_pop( L, 1); // settings
220 STACK_END( L, 0); 250 STACK_END( L, 0);
221} 251}
222 252
@@ -1337,17 +1367,17 @@ static void copy_cached_func( Universe* U, lua_State* L2, uint_t L2_cache_i, lua
1337 1367
1338 if( lua_isnil( L2, -1)) // function is unknown 1368 if( lua_isnil( L2, -1)) // function is unknown
1339 { 1369 {
1340 lua_pop( L2, 1); // ... {cache} ... p 1370 lua_pop( L2, 1); // ... {cache} ... p
1341 1371
1342 // Set to 'true' for the duration of creation; need to find self-references 1372 // Set to 'true' for the duration of creation; need to find self-references
1343 // via upvalues 1373 // via upvalues
1344 // 1374 //
1345 // pushes a copy of the func, stores a reference in the cache 1375 // pushes a copy of the func, stores a reference in the cache
1346 copy_func( U, L2, L2_cache_i, L, i, mode_, upName_); // ... {cache} ... function 1376 copy_func( U, L2, L2_cache_i, L, i, mode_, upName_); // ... {cache} ... function
1347 } 1377 }
1348 else // found function in the cache 1378 else // found function in the cache
1349 { 1379 {
1350 lua_remove( L2, -2); // ... {cache} ... function 1380 lua_remove( L2, -2); // ... {cache} ... function
1351 } 1381 }
1352 STACK_END( L2, 1); 1382 STACK_END( L2, 1);
1353 ASSERT_L( lua_isfunction( L2, -1)); 1383 ASSERT_L( lua_isfunction( L2, -1));
@@ -1725,9 +1755,7 @@ static bool_t inter_copy_function( Universe* U, lua_State* L2, uint_t L2_cache_i
1725 { 1755 {
1726 DEBUGSPEW_CODE( fprintf( stderr, "FUNCTION %s\n", upName_)); 1756 DEBUGSPEW_CODE( fprintf( stderr, "FUNCTION %s\n", upName_));
1727 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); 1757 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
1728 STACK_CHECK( L2, 0);
1729 copy_cached_func( U, L2, L2_cache_i, L, source_i_, mode_, upName_); // ... f 1758 copy_cached_func( U, L2, L2_cache_i, L, source_i_, mode_, upName_); // ... f
1730 STACK_END( L2, 1);
1731 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 1759 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
1732 } 1760 }
1733 STACK_END( L2, 1); 1761 STACK_END( L2, 1);
diff --git a/src/universe.h b/src/universe.h
index ba00e87..03c78cf 100644
--- a/src/universe.h
+++ b/src/universe.h
@@ -63,6 +63,8 @@ struct s_Universe
63 // contains a mutex and the original allocator definition 63 // contains a mutex and the original allocator definition
64 ProtectedAllocator protected_allocator; 64 ProtectedAllocator protected_allocator;
65 65
66 AllocatorDefinition internal_allocator;
67
66 Keepers* keepers; 68 Keepers* keepers;
67 69
68 // Initialized by 'init_once_LOCKED()': the deep userdata Linda object 70 // Initialized by 'init_once_LOCKED()': the deep userdata Linda object