aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenoit Germain <b n t DOT g e r m a i n AT g m a i l DOT c o m>2013-09-27 20:34:51 +0200
committerBenoit Germain <b n t DOT g e r m a i n AT g m a i l DOT c o m>2013-09-27 20:34:51 +0200
commit623a8f48a624510a0461b0893da647e22e08cdd7 (patch)
treed414e72f4dedb4d196a24a9b0adc8c4393bbd46c /src
parentf823c6887e28c815234f8b4bd355887b4f554857 (diff)
downloadlanes-623a8f48a624510a0461b0893da647e22e08cdd7.tar.gz
lanes-623a8f48a624510a0461b0893da647e22e08cdd7.tar.bz2
lanes-623a8f48a624510a0461b0893da647e22e08cdd7.zip
version 3.6.6
no longer call core.configure with dummy params when requiring lanes more than once (fixes potential multithreading issues with LuaJIT allocator) activated EnableCrashingOnCrashes() Win32 debug builds fixed some comments in code
Diffstat (limited to 'src')
-rw-r--r--src/keeper.c2
-rw-r--r--src/lanes.c120
-rw-r--r--src/lanes.lua19
-rw-r--r--src/tools.c8
4 files changed, 64 insertions, 85 deletions
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))