aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES6
-rw-r--r--docs/index.html2
-rw-r--r--src/keeper.c2
-rw-r--r--src/lanes.c120
-rw-r--r--src/lanes.lua19
-rw-r--r--src/tools.c8
6 files changed, 71 insertions, 86 deletions
diff --git a/CHANGES b/CHANGES
index a52a404..96ac6c6 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,11 @@
1CHANGES: 1CHANGES:
2 2
3CHANGE 70: BGe 27-Step-13
4 * version 3.6.6
5 * no longer call core.configure with dummy params when requiring lanes more than once (fixes potential multithreading issues with LuaJIT allocator)
6 * activated EnableCrashingOnCrashes() is active on Win32 debug builds
7 * fixed some comments in code
8
3CHANGE 69: BGe 26-Sept-13 9CHANGE 69: BGe 26-Sept-13
4 * version 3.6.5 10 * version 3.6.5
5 * Reduce memory footprint, simplify module order setup in conjuction with Lanes, and send over native functions a bit faster as well 11 * Reduce memory footprint, simplify module order setup in conjuction with Lanes, and send over native functions a bit faster as well
diff --git a/docs/index.html b/docs/index.html
index ac4fa6b..b0ef8a3 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -70,7 +70,7 @@
70 </p> 70 </p>
71 71
72 <p> 72 <p>
73 This document was revised on 26-Sept-13, and applies to version <tt>3.6.5</tt>. 73 This document was revised on 27-Sept-13, and applies to version <tt>3.6.6</tt>.
74 </p> 74 </p>
75 </font> 75 </font>
76 </center> 76 </center>
diff --git a/src/keeper.c b/src/keeper.c
index 8d9f7ec..bd232cd 100644
--- a/src/keeper.c
+++ b/src/keeper.c
@@ -572,8 +572,6 @@ char const* init_keepers( lua_State* L, int _on_state_create, int const _nbKeepe
572 lua_State* K; 572 lua_State* K;
573 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "### init_keepers %d BEGIN\n" INDENT_END, i)); 573 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "### init_keepers %d BEGIN\n" INDENT_END, i));
574 DEBUGSPEW_CODE( ++ debugspew_indent_depth); 574 DEBUGSPEW_CODE( ++ debugspew_indent_depth);
575 // We need to load all base libraries in the keeper states so that the transfer databases are populated properly
576 //
577 // we don't need any libs in the keeper states 575 // we don't need any libs in the keeper states
578 K = luaG_newstate( L, _on_state_create, NULL); 576 K = luaG_newstate( L, _on_state_create, NULL);
579 577
diff --git a/src/lanes.c b/src/lanes.c
index dc1eeed..f4427a4 100644
--- a/src/lanes.c
+++ b/src/lanes.c
@@ -52,7 +52,7 @@
52 * ... 52 * ...
53 */ 53 */
54 54
55char const* VERSION = "3.6.5"; 55char const* VERSION = "3.6.6";
56 56
57/* 57/*
58=============================================================================== 58===============================================================================
@@ -414,8 +414,8 @@ LUAG_FUNC( linda_send)
414 414
415 STACK_GROW(L, 1); 415 STACK_GROW(L, 1);
416 { 416 {
417 struct s_Keeper *K = keeper_acquire( linda); 417 struct s_Keeper* K = keeper_acquire( linda);
418 lua_State *KL = K->L; // need to do this for 'STACK_CHECK' 418 lua_State* KL = K->L; // need to do this for 'STACK_CHECK'
419 STACK_CHECK( KL); 419 STACK_CHECK( KL);
420 for( ;;) 420 for( ;;)
421 { 421 {
@@ -2734,7 +2734,6 @@ LUAG_FUNC( configure)
2734 char const* name = luaL_checkstring( L, lua_upvalueindex( 1)); 2734 char const* name = luaL_checkstring( L, lua_upvalueindex( 1));
2735 // all parameter checks are done lua-side 2735 // all parameter checks are done lua-side
2736 int const nbKeepers = (int)lua_tointeger( L, 1); 2736 int const nbKeepers = (int)lua_tointeger( L, 1);
2737 // all these can be nil when lanes.core is required internally! (but are only processed at first init anyway)
2738 int const on_state_create = lua_isfunction( L, 2) ? 2 : 0; 2737 int const on_state_create = lua_isfunction( L, 2) ? 2 : 0;
2739 lua_Number shutdown_timeout = lua_tonumber( L, 3); 2738 lua_Number shutdown_timeout = lua_tonumber( L, 3);
2740 bool_t track_lanes = lua_toboolean( L, 4); 2739 bool_t track_lanes = lua_toboolean( L, 4);
@@ -2759,6 +2758,45 @@ LUAG_FUNC( configure)
2759 lua_setallocf( L, protected_lua_Alloc, s); 2758 lua_setallocf( L, protected_lua_Alloc, s);
2760 } 2759 }
2761 } 2760 }
2761 STACK_MID( L, 0);
2762
2763 /*
2764 ** Making one-time initializations.
2765 **
2766 ** When the host application is single-threaded (and all threading happens via Lanes)
2767 ** there is no problem. But if the host is multithreaded, we need to lock around the
2768 ** initializations.
2769 */
2770#if THREADAPI == THREADAPI_WINDOWS
2771 {
2772 static volatile int /*bool*/ go_ahead; // = 0
2773 if( InterlockedCompareExchange( &s_initCount, 1, 0) == 0)
2774 {
2775 init_once_LOCKED( L, on_state_create, nbKeepers, shutdown_timeout, track_lanes, verbose_errors);
2776 go_ahead = 1; // let others pass
2777 }
2778 else
2779 {
2780 while( !go_ahead) { Sleep(1); } // changes threads
2781 }
2782 }
2783#else // THREADAPI == THREADAPI_PTHREAD
2784 if( s_initCount == 0)
2785 {
2786 static pthread_mutex_t my_lock = PTHREAD_MUTEX_INITIALIZER;
2787 pthread_mutex_lock( &my_lock);
2788 {
2789 // Recheck now that we're within the lock
2790 //
2791 if( s_initCount == 0)
2792 {
2793 init_once_LOCKED( L, on_state_create, nbKeepers, shutdown_timeout, track_lanes, verbose_errors);
2794 s_initCount = 1;
2795 }
2796 }
2797 pthread_mutex_unlock( &my_lock);
2798 }
2799#endif // THREADAPI == THREADAPI_PTHREAD
2762 2800
2763 // Create main module interface table 2801 // Create main module interface table
2764 lua_pushvalue( L, lua_upvalueindex( 2)); // ... M 2802 lua_pushvalue( L, lua_upvalueindex( 2)); // ... M
@@ -2818,49 +2856,7 @@ LUAG_FUNC( configure)
2818 populate_func_lookup_table( L, -1, NULL); 2856 populate_func_lookup_table( L, -1, NULL);
2819 lua_pop( L, 1); // ... M 2857 lua_pop( L, 1); // ... M
2820 2858
2821 STACK_MID( L, 1); 2859 ASSERT_L( timer_deep != NULL);
2822 /*
2823 ** Making one-time initializations.
2824 **
2825 ** When the host application is single-threaded (and all threading happens via Lanes)
2826 ** there is no problem. But if the host is multithreaded, we need to lock around the
2827 ** initializations.
2828 ** we must do this after the populate_func_lookup_table is called, else populating the keepers will fail
2829 ** because this makes a copy of packages.loaders, which requires the lookup tables to exist!
2830 */
2831#if THREADAPI == THREADAPI_WINDOWS
2832 {
2833 static volatile int /*bool*/ go_ahead; // = 0
2834 if( InterlockedCompareExchange( &s_initCount, 1, 0) == 0)
2835 {
2836 init_once_LOCKED( L, on_state_create, nbKeepers, shutdown_timeout, track_lanes, verbose_errors);
2837 go_ahead = 1; // let others pass
2838 }
2839 else
2840 {
2841 while( !go_ahead ) { Sleep(1); } // changes threads
2842 }
2843 }
2844#else // THREADAPI == THREADAPI_PTHREAD
2845 if( s_initCount == 0)
2846 {
2847 static pthread_mutex_t my_lock = PTHREAD_MUTEX_INITIALIZER;
2848 pthread_mutex_lock( &my_lock);
2849 {
2850 // Recheck now that we're within the lock
2851 //
2852 if( s_initCount == 0)
2853 {
2854 init_once_LOCKED( L, on_state_create, nbKeepers, shutdown_timeout, track_lanes, verbose_errors);
2855 s_initCount = 1;
2856 }
2857 }
2858 pthread_mutex_unlock( &my_lock);
2859 }
2860#endif // THREADAPI == THREADAPI_PTHREAD
2861 STACK_MID( L, 1);
2862
2863 assert( timer_deep != NULL);
2864 // init_once_LOCKED initializes timer_deep, so we must do this after, of course 2860 // init_once_LOCKED initializes timer_deep, so we must do this after, of course
2865 luaG_push_proxy( L, linda_id, (DEEP_PRELUDE*) timer_deep); // ... M timer_deep 2861 luaG_push_proxy( L, linda_id, (DEEP_PRELUDE*) timer_deep); // ... M timer_deep
2866 lua_setfield( L, -2, "timer_gateway"); // ... M 2862 lua_setfield( L, -2, "timer_gateway"); // ... M
@@ -2875,9 +2871,9 @@ LUAG_FUNC( configure)
2875 2871
2876// helper to have correct callstacks when crashing a Win32 running on 64 bits Windows 2872// helper to have correct callstacks when crashing a Win32 running on 64 bits Windows
2877// don't forget to toggle Debug/Exceptions/Win32 in visual Studio too! 2873// don't forget to toggle Debug/Exceptions/Win32 in visual Studio too!
2878void EnableCrashingOnCrashes() 2874static void EnableCrashingOnCrashes( void)
2879{ 2875{
2880#if 0 && defined PLATFORM_WIN32 2876#if defined PLATFORM_WIN32 && !defined NDEBUG
2881 typedef BOOL (WINAPI *tGetPolicy)(LPDWORD lpFlags); 2877 typedef BOOL (WINAPI *tGetPolicy)(LPDWORD lpFlags);
2882 typedef BOOL (WINAPI *tSetPolicy)(DWORD dwFlags); 2878 typedef BOOL (WINAPI *tSetPolicy)(DWORD dwFlags);
2883 const DWORD EXCEPTION_SWALLOWING = 0x1; 2879 const DWORD EXCEPTION_SWALLOWING = 0x1;
@@ -2885,13 +2881,13 @@ void EnableCrashingOnCrashes()
2885 HMODULE kernel32 = LoadLibraryA("kernel32.dll"); 2881 HMODULE kernel32 = LoadLibraryA("kernel32.dll");
2886 tGetPolicy pGetPolicy = (tGetPolicy)GetProcAddress(kernel32, "GetProcessUserModeExceptionPolicy"); 2882 tGetPolicy pGetPolicy = (tGetPolicy)GetProcAddress(kernel32, "GetProcessUserModeExceptionPolicy");
2887 tSetPolicy pSetPolicy = (tSetPolicy)GetProcAddress(kernel32, "SetProcessUserModeExceptionPolicy"); 2883 tSetPolicy pSetPolicy = (tSetPolicy)GetProcAddress(kernel32, "SetProcessUserModeExceptionPolicy");
2888 if (pGetPolicy && pSetPolicy) 2884 if( pGetPolicy && pSetPolicy)
2889 { 2885 {
2890 DWORD dwFlags; 2886 DWORD dwFlags;
2891 if (pGetPolicy(&dwFlags)) 2887 if( pGetPolicy( &dwFlags))
2892 { 2888 {
2893 // Turn off the filter 2889 // Turn off the filter
2894 pSetPolicy(dwFlags & ~EXCEPTION_SWALLOWING); 2890 pSetPolicy( dwFlags & ~EXCEPTION_SWALLOWING);
2895 } 2891 }
2896 } 2892 }
2897#endif // PLATFORM_WIN32 2893#endif // PLATFORM_WIN32
@@ -2906,21 +2902,11 @@ int LANES_API luaopen_lanes_core( lua_State* L)
2906 2902
2907 // Create main module interface table 2903 // Create main module interface table
2908 // we only have 1 closure, which must be called to configure Lanes 2904 // we only have 1 closure, which must be called to configure Lanes
2909 lua_newtable(L); // M 2905 lua_newtable( L); // M
2910 lua_pushvalue(L, 1); // M "lanes.core" 2906 lua_pushvalue( L, 1); // M "lanes.core"
2911 lua_pushvalue(L, -2); // M "lanes.core" M 2907 lua_pushvalue( L, -2); // M "lanes.core" M
2912 lua_pushcclosure( L, LG_configure, 2); // M LG_configure() 2908 lua_pushcclosure( L, LG_configure, 2); // M LG_configure()
2913 if( s_initCount == 0) 2909 lua_setfield( L, -2, "configure"); // M
2914 {
2915 lua_setfield( L, -2, "configure"); // M
2916 }
2917 else // already initialized: call it immediately and be done
2918 {
2919 // any parameter value will do, they will be ignored
2920 lua_pushinteger( L, 666); // M LG_configure() 666
2921 lua_pushnil( L); // M LG_configure() 666 nil
2922 lua_call( L, 2, 0); // M
2923 }
2924 2910
2925 STACK_END( L, 1); 2911 STACK_END( L, 1);
2926 return 1; 2912 return 1;
diff --git a/src/lanes.lua b/src/lanes.lua
index 175002a..173db00 100644
--- a/src/lanes.lua
+++ b/src/lanes.lua
@@ -145,23 +145,18 @@ lanes.configure = function( _params)
145 145
146 local core = require "lanes.core" 146 local core = require "lanes.core"
147 assert( type( core)=="table") 147 assert( type( core)=="table")
148 148 core.configure( _params.nb_keepers, _params.on_state_create, _params.shutdown_timeout, _params.track_lanes, _params.protect_allocator, _params.verbose_errors)
149 -- configure() is available only the first time lanes.core is required process-wide, and we *must* call it to have the other functions in the interface
150 if core.configure then core.configure( _params.nb_keepers, _params.on_state_create, _params.shutdown_timeout, _params.track_lanes, _params.protect_allocator, _params.verbose_errors) end
151
152 local thread_new = assert( core.thread_new) 149 local thread_new = assert( core.thread_new)
153
154 local set_singlethreaded = assert( core.set_singlethreaded) 150 local set_singlethreaded = assert( core.set_singlethreaded)
155
156 local max_prio = assert( core.max_prio) 151 local max_prio = assert( core.max_prio)
157 152
158lanes.ABOUT= 153lanes.ABOUT =
159{ 154{
160 author= "Asko Kauppi <akauppi@gmail.com>, Benoit Germain <bnt.germain@gmail.com>", 155 author= "Asko Kauppi <akauppi@gmail.com>, Benoit Germain <bnt.germain@gmail.com>",
161 description= "Running multiple Lua states in parallel", 156 description= "Running multiple Lua states in parallel",
162 license= "MIT/X11", 157 license= "MIT/X11",
163 copyright= "Copyright (c) 2007-10, Asko Kauppi; (c) 2011-12, Benoit Germain", 158 copyright= "Copyright (c) 2007-10, Asko Kauppi; (c) 2011-13, Benoit Germain",
164 version = assert( core.version) 159 version = assert( core.version)
165} 160}
166 161
167 162
diff --git a/src/tools.c b/src/tools.c
index a957f41..49194d0 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -1461,12 +1461,12 @@ static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i, enum eLoo
1461{ 1461{
1462 char const* fqn; // L // L2 1462 char const* fqn; // L // L2
1463 size_t len; 1463 size_t len;
1464 _ASSERT_L( L, lua_isfunction( L, i)); // ... f ... 1464 ASSERT_L( lua_isfunction( L, i)); // ... f ...
1465 STACK_CHECK( L); 1465 STACK_CHECK( L);
1466 if( mode_ == eLM_FromKeeper) 1466 if( mode_ == eLM_FromKeeper)
1467 { 1467 {
1468 lua_CFunction f = lua_tocfunction( L, i); // should *always* be sentinelfunc! 1468 lua_CFunction f = lua_tocfunction( L, i); // should *always* be sentinelfunc!
1469 _ASSERT_L( L, f == sentinelfunc); 1469 ASSERT_L( f == sentinelfunc);
1470 lua_getupvalue( L, i, 1); // ... f ... "f.q.n" 1470 lua_getupvalue( L, i, 1); // ... f ... "f.q.n"
1471 fqn = lua_tolstring( L, -1, &len); 1471 fqn = lua_tolstring( L, -1, &len);
1472 } 1472 }
@@ -1474,7 +1474,7 @@ static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i, enum eLoo
1474 { 1474 {
1475 // fetch the name from the source state's lookup table 1475 // fetch the name from the source state's lookup table
1476 lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_KEY); // ... f ... {} 1476 lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_KEY); // ... f ... {}
1477 _ASSERT_L( L, lua_istable( L, -1)); 1477 ASSERT_L( lua_istable( L, -1));
1478 lua_pushvalue( L, i); // ... f ... {} f 1478 lua_pushvalue( L, i); // ... f ... {} f
1479 lua_rawget( L, -2); // ... f ... {} "f.q.n" 1479 lua_rawget( L, -2); // ... f ... {} "f.q.n"
1480 fqn = lua_tolstring( L, -1, &len); 1480 fqn = lua_tolstring( L, -1, &len);
@@ -1521,7 +1521,7 @@ static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i, enum eLoo
1521 else 1521 else
1522 { 1522 {
1523 lua_getfield( L2, LUA_REGISTRYINDEX, LOOKUP_KEY); // {} 1523 lua_getfield( L2, LUA_REGISTRYINDEX, LOOKUP_KEY); // {}
1524 _ASSERT_L( L2, lua_istable( L2, -1)); 1524 ASSERT_L( lua_istable( L2, -1));
1525 lua_pushlstring( L2, fqn, len); // {} "f.q.n" 1525 lua_pushlstring( L2, fqn, len); // {} "f.q.n"
1526 lua_rawget( L2, -2); // {} f 1526 lua_rawget( L2, -2); // {} f
1527 if( !lua_isfunction( L2, -1)) 1527 if( !lua_isfunction( L2, -1))