diff options
author | Benoit 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 |
---|---|---|
committer | Benoit 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 |
commit | 623a8f48a624510a0461b0893da647e22e08cdd7 (patch) | |
tree | d414e72f4dedb4d196a24a9b0adc8c4393bbd46c /src/lanes.c | |
parent | f823c6887e28c815234f8b4bd355887b4f554857 (diff) | |
download | lanes-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/lanes.c')
-rw-r--r-- | src/lanes.c | 120 |
1 files changed, 53 insertions, 67 deletions
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 | ||
55 | char const* VERSION = "3.6.5"; | 55 | char 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! |
2878 | void EnableCrashingOnCrashes() | 2874 | static 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; |