summaryrefslogtreecommitdiff
path: root/src/lanes.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lanes.c')
-rw-r--r--src/lanes.c371
1 files changed, 211 insertions, 160 deletions
diff --git a/src/lanes.c b/src/lanes.c
index 8a67621..6fec951 100644
--- a/src/lanes.c
+++ b/src/lanes.c
@@ -52,13 +52,13 @@
52 * ... 52 * ...
53 */ 53 */
54 54
55char const* VERSION = "3.4.2"; 55char const* VERSION = "3.4.3";
56 56
57/* 57/*
58=============================================================================== 58===============================================================================
59 59
60Copyright (C) 2007-10 Asko Kauppi <akauppi@gmail.com> 60Copyright (C) 2007-10 Asko Kauppi <akauppi@gmail.com>
61 2011-12 Benoit Germain <bnt.germain@gmail.com> 61 2011-13 Benoit Germain <bnt.germain@gmail.com>
62 62
63Permission is hereby granted, free of charge, to any person obtaining a copy 63Permission is hereby granted, free of charge, to any person obtaining a copy
64of this software and associated documentation files (the "Software"), to deal 64of this software and associated documentation files (the "Software"), to deal
@@ -1114,7 +1114,8 @@ static int run_finalizers( lua_State*L, int lua_rc )
1114 // 1114 //
1115 // LUA_ERRRUN / LUA_ERRMEM 1115 // LUA_ERRRUN / LUA_ERRMEM
1116 1116
1117 if (rc!=0) { 1117 if( rc != LUA_OK)
1118 {
1118 // [-1]: error message 1119 // [-1]: error message
1119 // 1120 //
1120 // If one finalizer fails, don't run the others. Return this 1121 // If one finalizer fails, don't run the others. Return this
@@ -1269,7 +1270,7 @@ static bool_t selfdestruct_remove( struct s_lane *s )
1269// Initialized by 'init_once_LOCKED()': the deep userdata Linda object 1270// Initialized by 'init_once_LOCKED()': the deep userdata Linda object
1270// used for timers (each lane will get a proxy to this) 1271// used for timers (each lane will get a proxy to this)
1271// 1272//
1272volatile DEEP_PRELUDE *timer_deep; // = NULL 1273volatile DEEP_PRELUDE* timer_deep; // = NULL
1273 1274
1274/* 1275/*
1275* Process end; cancel any still free-running threads 1276* Process end; cancel any still free-running threads
@@ -1349,7 +1350,7 @@ static int selfdestruct_gc( lua_State*L)
1349 t_now = now_secs(); 1350 t_now = now_secs();
1350 if( n == 0 || ( t_now >= t_until)) 1351 if( n == 0 || ( t_now >= t_until))
1351 { 1352 {
1352 DEBUGEXEC(fprintf( stderr, "%d uncancelled lane(s) remain after waiting %fs at process end.\n", n, shutdown_timeout - (t_until - t_now))); 1353 DEBUGSPEW_CODE( fprintf( stderr, "%d uncancelled lane(s) remain after waiting %fs at process end.\n", n, shutdown_timeout - (t_until - t_now)));
1353 break; 1354 break;
1354 } 1355 }
1355 } 1356 }
@@ -1379,7 +1380,7 @@ static int selfdestruct_gc( lua_State*L)
1379//we want to free memory and such when we exit. 1380//we want to free memory and such when we exit.
1380 // 2.0.2: at least timer lane is still here 1381 // 2.0.2: at least timer lane is still here
1381 // 1382 //
1382 DEBUGEXEC(fprintf( stderr, "Left %d lane(s) with cancel request at process end.\n", n )); 1383 DEBUGSPEW_CODE( fprintf( stderr, "Left %d lane(s) with cancel request at process end.\n", n ));
1383 n=0; 1384 n=0;
1384#else 1385#else
1385 // first thing we did was to raise the linda signals the threads were waiting on (if any) 1386 // first thing we did was to raise the linda signals the threads were waiting on (if any)
@@ -1409,7 +1410,7 @@ static int selfdestruct_gc( lua_State*L)
1409 } 1410 }
1410 MUTEX_UNLOCK( &selfdestruct_cs ); 1411 MUTEX_UNLOCK( &selfdestruct_cs );
1411 1412
1412 DEBUGEXEC(fprintf( stderr, "Killed %d lane(s) at process end.\n", n )); 1413 DEBUGSPEW_CODE( fprintf( stderr, "Killed %d lane(s) at process end.\n", n));
1413#endif 1414#endif
1414 } 1415 }
1415#if !HAVE_KEEPER_ATEXIT_DESINIT 1416#if !HAVE_KEEPER_ATEXIT_DESINIT
@@ -1654,6 +1655,39 @@ LUAG_FUNC( set_debug_threadname)
1654 return 0; 1655 return 0;
1655} 1656}
1656 1657
1658#if USE_DEBUG_SPEW
1659// can't use direct LUA_x errcode indexing because the sequence is not the same between Lua 5.1 and 5.2 :-(
1660// LUA_ERRERR doesn't have the same value
1661struct errcode_name
1662{
1663 int code;
1664 char const* name;
1665};
1666
1667static struct errcode_name s_errcodes[] =
1668{
1669 { LUA_OK, "LUA_OK"},
1670 { LUA_YIELD, "LUA_YIELD"},
1671 { LUA_ERRRUN, "LUA_ERRRUN"},
1672 { LUA_ERRSYNTAX, "LUA_ERRSYNTAX"},
1673 { LUA_ERRMEM, "LUA_ERRMEM"},
1674 { LUA_ERRGCMM, "LUA_ERRGCMM"},
1675 { LUA_ERRERR, "LUA_ERRERR"},
1676};
1677static char const* get_errcode_name( int _code)
1678{
1679 int i;
1680 for( i = 0; i < 7; ++ i)
1681 {
1682 if( s_errcodes[i].code == _code)
1683 {
1684 return s_errcodes[i].name;
1685 }
1686 }
1687 return "<NULL>";
1688}
1689#endif // USE_DEBUG_SPEW
1690
1657//--- 1691//---
1658static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs) 1692static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs)
1659{ 1693{
@@ -1713,7 +1747,8 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs)
1713 // Lua 5.1 error handler is limited to one return value; taking stack trace 1747 // Lua 5.1 error handler is limited to one return value; taking stack trace
1714 // via registry 1748 // via registry
1715 // 1749 //
1716 if (rc!=0) { 1750 if( rc != 0)
1751 {
1717 STACK_GROW(L,1); 1752 STACK_GROW(L,1);
1718 lua_pushlightuserdata( L, STACK_TRACE_KEY ); 1753 lua_pushlightuserdata( L, STACK_TRACE_KEY );
1719 lua_gettable(L, LUA_REGISTRYINDEX); 1754 lua_gettable(L, LUA_REGISTRYINDEX);
@@ -1733,16 +1768,19 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs)
1733 // [2..top]: parameters 1768 // [2..top]: parameters
1734 // 1769 //
1735 rc= lua_pcall( L, lua_gettop(L)-1, LUA_MULTRET, 0 /*no error handler*/ ); 1770 rc= lua_pcall( L, lua_gettop(L)-1, LUA_MULTRET, 0 /*no error handler*/ );
1736 // 0: no error 1771 // LUA_OK(0): no error
1737 // LUA_ERRRUN: a runtime error (error pushed on stack) 1772 // LUA_ERRRUN(2): a runtime error (error pushed on stack)
1738 // LUA_ERRMEM: memory allocation error 1773 // LUA_ERRMEM(4): memory allocation error
1739#endif 1774#endif
1740 1775
1741//STACK_DUMP(L); 1776 DEBUGSPEW_CODE( fprintf( stderr, "Lane %p body: %s\n", L, get_errcode_name( rc)));
1777 //STACK_DUMP(L);
1742 // Call finalizers, if the script has set them up. 1778 // Call finalizers, if the script has set them up.
1743 // 1779 //
1744 rc2= run_finalizers(L,rc); 1780 rc2 = run_finalizers( L, rc);
1745 if (rc2!=0) { 1781 DEBUGSPEW_CODE( fprintf( stderr, "Lane %p finalizer: %s\n", L, get_errcode_name( rc2)));
1782 if( rc2 != LUA_OK)
1783 {
1746 // Error within a finalizer! 1784 // Error within a finalizer!
1747 // 1785 //
1748 // [-1]: error message 1786 // [-1]: error message
@@ -1766,7 +1804,6 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs)
1766 s->L = L = 0; 1804 s->L = L = 0;
1767 1805
1768 lane_cleanup( s); 1806 lane_cleanup( s);
1769
1770 } 1807 }
1771 else 1808 else
1772 { 1809 {
@@ -1809,10 +1846,10 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs)
1809 1846
1810// helper function to require a module in the keeper states and in the target state 1847// helper function to require a module in the keeper states and in the target state
1811// source state contains module name at the top of the stack 1848// source state contains module name at the top of the stack
1812static void require_one_module( lua_State*L, lua_State*L2, bool_t _fatal) 1849static void require_one_module( lua_State* L, lua_State* L2, bool_t _fatal)
1813{ 1850{
1814 size_t len; 1851 size_t len;
1815 char const *name = lua_tolstring( L, -1, &len); 1852 char const* name = lua_tolstring( L, -1, &len);
1816 // require the module in the target lane 1853 // require the module in the target lane
1817 STACK_GROW( L2, 2); 1854 STACK_GROW( L2, 2);
1818 lua_getglobal( L2, "require"); 1855 lua_getglobal( L2, "require");
@@ -1872,39 +1909,11 @@ LUAG_FUNC( thread_new )
1872 1909
1873 ASSERT_L( lua_gettop(L2) == 0); 1910 ASSERT_L( lua_gettop(L2) == 0);
1874 1911
1875 // package.path 1912 // package
1876 STACK_CHECK(L)
1877 STACK_CHECK(L2)
1878 if( package) 1913 if( package)
1879 { 1914 {
1880 if( lua_type( L, package) != LUA_TTABLE) 1915 luaG_inter_copy_package( L, L2, package);
1881 {
1882 return luaL_error( L, "expected package as table, got %s", luaL_typename( L, package));
1883 }
1884 lua_getglobal( L2, "package");
1885 if( !lua_isnil( L2, -1)) // package library not loaded: do nothing
1886 {
1887 int i;
1888 // package.loaders is renamed package.searchers in Lua 5.2
1889 char const* entries[] = { "path", "cpath", "preload", (LUA_VERSION_NUM == 501) ? "loaders" : "searchers", NULL};
1890 for( i = 0; entries[i]; ++ i)
1891 {
1892 lua_getfield( L, package, entries[i]);
1893 if( lua_isnil( L, -1))
1894 {
1895 lua_pop( L, 1);
1896 }
1897 else
1898 {
1899 luaG_inter_move( L, L2, 1); // moves the entry to L2
1900 lua_setfield( L2, -2, entries[i]); // set package[entries[i]]
1901 }
1902 }
1903 }
1904 lua_pop( L2, 1);
1905 } 1916 }
1906 STACK_END(L2,0)
1907 STACK_END(L,0)
1908 1917
1909 // modules to require in the target lane *before* the function is transfered! 1918 // modules to require in the target lane *before* the function is transfered!
1910 1919
@@ -1924,14 +1933,14 @@ LUAG_FUNC( thread_new )
1924 { 1933 {
1925 int nbRequired = 1; 1934 int nbRequired = 1;
1926 // should not happen, was checked in lanes.lua before calling thread_new() 1935 // should not happen, was checked in lanes.lua before calling thread_new()
1927 if (lua_type(L, required) != LUA_TTABLE) 1936 if( lua_type( L, required) != LUA_TTABLE)
1928 { 1937 {
1929 return luaL_error( L, "expected required module list as a table, got %s", luaL_typename( L, required)); 1938 return luaL_error( L, "expected required module list as a table, got %s", luaL_typename( L, required));
1930 } 1939 }
1931 lua_pushnil( L); 1940 lua_pushnil( L);
1932 while( lua_next( L, required) != 0) 1941 while( lua_next( L, required) != 0)
1933 { 1942 {
1934 if (lua_type(L,-1) != LUA_TSTRING || lua_type(L,-2) != LUA_TNUMBER || lua_tonumber( L, -2) != nbRequired) 1943 if( lua_type( L, -1) != LUA_TSTRING || lua_type( L, -2) != LUA_TNUMBER || lua_tonumber( L, -2) != nbRequired)
1935 { 1944 {
1936 return luaL_error( L, "required module list should be a list of strings"); 1945 return luaL_error( L, "required module list should be a list of strings");
1937 } 1946 }
@@ -1949,13 +1958,13 @@ LUAG_FUNC( thread_new )
1949 // Appending the specified globals to the global environment 1958 // Appending the specified globals to the global environment
1950 // *after* stdlibs have been loaded and modules required, in case we transfer references to native functions they exposed... 1959 // *after* stdlibs have been loaded and modules required, in case we transfer references to native functions they exposed...
1951 // 1960 //
1952 if (glob!=0) 1961 if( glob != 0)
1953 { 1962 {
1954 STACK_CHECK(L) 1963 STACK_CHECK(L)
1955 STACK_CHECK(L2) 1964 STACK_CHECK(L2)
1956 if( !lua_istable( L, glob)) 1965 if( !lua_istable( L, glob))
1957 { 1966 {
1958 return luaL_error( L, "Expected table, got %s", luaL_typename(L,glob)); 1967 return luaL_error( L, "Expected table, got %s", luaL_typename( L, glob));
1959 } 1968 }
1960 1969
1961 lua_pushnil( L); 1970 lua_pushnil( L);
@@ -1987,7 +1996,7 @@ LUAG_FUNC( thread_new )
1987 } 1996 }
1988 STACK_MID(L,0) 1997 STACK_MID(L,0)
1989 } 1998 }
1990 else if( lua_type(L, 1) == LUA_TSTRING) 1999 else if( lua_type( L, 1) == LUA_TSTRING)
1991 { 2000 {
1992 // compile the string 2001 // compile the string
1993 if( luaL_loadstring( L2, lua_tostring( L, 1)) != 0) 2002 if( luaL_loadstring( L2, lua_tostring( L, 1)) != 0)
@@ -2089,7 +2098,7 @@ LUAG_FUNC( thread_gc)
2089 // Make sure a kill has proceeded, before cleaning up the data structure. 2098 // Make sure a kill has proceeded, before cleaning up the data structure.
2090 // 2099 //
2091 // NO lua_close() in this case because we don't know where execution of the state was interrupted 2100 // NO lua_close() in this case because we don't know where execution of the state was interrupted
2092 DEBUGEXEC(fprintf( stderr, "** Joining with a killed thread (needs testing) **" )); 2101 DEBUGSPEW_CODE( fprintf( stderr, "** Joining with a killed thread (needs testing) **"));
2093 // make sure the thread is no longer running, just like thread_join() 2102 // make sure the thread is no longer running, just like thread_join()
2094 if(! THREAD_ISNULL( s->thread)) 2103 if(! THREAD_ISNULL( s->thread))
2095 THREAD_WAIT( &s->thread, -1, &s->done_signal, &s->done_lock, &s->status); 2104 THREAD_WAIT( &s->thread, -1, &s->done_signal, &s->done_lock, &s->status);
@@ -2100,7 +2109,7 @@ LUAG_FUNC( thread_gc)
2100 lua_close( s->L); 2109 lua_close( s->L);
2101 s->L = 0; 2110 s->L = 0;
2102 } 2111 }
2103 DEBUGEXEC(fprintf( stderr, "** Joined ok **" )); 2112 DEBUGSPEW_CODE( fprintf( stderr, "** Joined ok **"));
2104 } 2113 }
2105 else if( s->status < DONE) 2114 else if( s->status < DONE)
2106 { 2115 {
@@ -2265,7 +2274,7 @@ LUAG_FUNC( thread_join)
2265 break; 2274 break;
2266 2275
2267 default: 2276 default:
2268 DEBUGEXEC(fprintf( stderr, "Status: %d\n", s->status)); 2277 DEBUGSPEW_CODE( fprintf( stderr, "Status: %d\n", s->status));
2269 ASSERT_L( FALSE ); ret= 0; 2278 ASSERT_L( FALSE ); ret= 0;
2270 } 2279 }
2271 lua_close( L2); 2280 lua_close( L2);
@@ -2547,9 +2556,9 @@ static const struct luaL_Reg lanes_functions [] = {
2547/* 2556/*
2548* One-time initializations 2557* One-time initializations
2549*/ 2558*/
2550static void init_once_LOCKED( lua_State* L, volatile DEEP_PRELUDE** timer_deep_ref, int const nbKeepers, lua_CFunction _on_state_create, lua_Number _shutdown_timeout, bool_t _track_lanes) 2559static void init_once_LOCKED( lua_State* L, int const nbKeepers, lua_CFunction _on_state_create, lua_Number _shutdown_timeout, bool_t _track_lanes)
2551{ 2560{
2552 const char *err; 2561 char const* err;
2553 2562
2554#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) 2563#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)
2555 now_secs(); // initialize 'now_secs()' internal offset 2564 now_secs(); // initialize 'now_secs()' internal offset
@@ -2604,7 +2613,7 @@ static void init_once_LOCKED( lua_State* L, volatile DEEP_PRELUDE** timer_deep_r
2604 } 2613 }
2605 #endif 2614 #endif
2606#endif 2615#endif
2607 err = init_keepers( nbKeepers, _on_state_create); 2616 err = init_keepers( L, nbKeepers, _on_state_create);
2608 if (err) 2617 if (err)
2609 { 2618 {
2610 (void) luaL_error( L, "Unable to initialize: %s", err ); 2619 (void) luaL_error( L, "Unable to initialize: %s", err );
@@ -2612,7 +2621,7 @@ static void init_once_LOCKED( lua_State* L, volatile DEEP_PRELUDE** timer_deep_r
2612 2621
2613 // Initialize 'timer_deep'; a common Linda object shared by all states 2622 // Initialize 'timer_deep'; a common Linda object shared by all states
2614 // 2623 //
2615 ASSERT_L( timer_deep_ref && (!(*timer_deep_ref)) ); 2624 ASSERT_L( timer_deep == NULL);
2616 2625
2617 STACK_CHECK(L) 2626 STACK_CHECK(L)
2618 { 2627 {
@@ -2627,8 +2636,8 @@ static void init_once_LOCKED( lua_State* L, volatile DEEP_PRELUDE** timer_deep_r
2627 2636
2628 // Proxy userdata contents is only a 'DEEP_PRELUDE*' pointer 2637 // Proxy userdata contents is only a 'DEEP_PRELUDE*' pointer
2629 // 2638 //
2630 *timer_deep_ref= * (DEEP_PRELUDE**) lua_touserdata( L, -1 ); 2639 timer_deep = * (DEEP_PRELUDE**) lua_touserdata( L, -1);
2631 ASSERT_L( (*timer_deep_ref) && (*timer_deep_ref)->refcount==1 && (*timer_deep_ref)->deep ); 2640 ASSERT_L( timer_deep && (timer_deep->refcount == 1) && timer_deep->deep);
2632 2641
2633 // The host Lua state must always have a reference to this Linda object in order for our 'timer_deep_ref' to be valid. 2642 // The host Lua state must always have a reference to this Linda object in order for our 'timer_deep_ref' to be valid.
2634 // So store a reference that we will never actually use. 2643 // So store a reference that we will never actually use.
@@ -2644,8 +2653,8 @@ static void init_once_LOCKED( lua_State* L, volatile DEEP_PRELUDE** timer_deep_r
2644 lua_setfield( L, -2, "__metatable"); 2653 lua_setfield( L, -2, "__metatable");
2645 lua_setmetatable( L, -2); 2654 lua_setmetatable( L, -2);
2646 } 2655 }
2647 lua_insert(L, -2); // Swap key with the Linda object 2656 lua_insert( L, -2); // Swap key with the Linda object
2648 lua_rawset(L, LUA_REGISTRYINDEX); 2657 lua_rawset( L, LUA_REGISTRYINDEX);
2649 2658
2650 } 2659 }
2651 STACK_END(L,0) 2660 STACK_END(L,0)
@@ -2653,107 +2662,147 @@ static void init_once_LOCKED( lua_State* L, volatile DEEP_PRELUDE** timer_deep_r
2653 2662
2654static volatile long s_initCount = 0; 2663static volatile long s_initCount = 0;
2655 2664
2656LUAG_FUNC( configure ) 2665// upvalue 1: module name
2666// upvalue 2: module table
2667LUAG_FUNC( configure)
2657{ 2668{
2658 char const* name = luaL_checkstring( L, lua_upvalueindex( 1)); 2669 char const* name = luaL_checkstring( L, lua_upvalueindex( 1));
2659 // all parameter checks are done lua-side 2670 // all parameter checks are done lua-side
2660 int const nbKeepers = (int)lua_tointeger( L, 1); 2671 int const nbKeepers = (int)lua_tointeger( L, 1);
2661 lua_CFunction on_state_create = lua_iscfunction( L, 2) ? lua_tocfunction( L, 2) : NULL; 2672 lua_CFunction on_state_create = lua_iscfunction( L, 2) ? lua_tocfunction( L, 2) : NULL;
2662 lua_Number shutdown_timeout = lua_tonumber( L, 3); 2673 lua_Number shutdown_timeout = lua_tonumber( L, 3);
2663 bool_t track_lanes = lua_toboolean( L, 4); 2674 bool_t track_lanes = lua_toboolean( L, 4);
2664 /* 2675
2665 * Making one-time initializations. 2676 STACK_CHECK( L)
2666 * 2677 // Create main module interface table
2667 * When the host application is single-threaded (and all threading happens via Lanes) 2678 lua_pushvalue( L, lua_upvalueindex( 2)); // ... M
2668 * there is no problem. But if the host is multithreaded, we need to lock around the 2679 // remove configure() (this function) from the module interface
2669 * initializations. 2680 lua_pushnil( L); // ... M nil
2670 */ 2681 lua_setfield( L, -2, "configure"); // ... M
2682 // add functions to the module's table
2683 luaG_registerlibfuncs( L, lanes_functions);
2684 STACK_MID( L, 1)
2685
2686 // metatable for threads
2687 // contains keys: { __gc, __index, cached_error, cached_tostring, cancel, join }
2688 //
2689 lua_newtable( L); // ... M mt
2690 lua_pushcfunction( L, LG_thread_gc); // ... M mt LG_thread_gc
2691 lua_setfield( L, -2, "__gc"); // ... M mt
2692 lua_pushcfunction( L, LG_thread_index); // ... M mt LG_thread_index
2693 lua_setfield( L, -2, "__index"); // ... M mt
2694 lua_getglobal( L, "error"); // ... M mt error
2695 ASSERT_L( lua_isfunction( L, -1));
2696 lua_setfield( L, -2, "cached_error"); // ... M mt
2697 lua_getglobal( L, "tostring"); // ... M mt tostring
2698 ASSERT_L( lua_isfunction( L, -1));
2699 lua_setfield( L, -2, "cached_tostring"); // ... M mt
2700 lua_pushcfunction( L, LG_thread_join); // ... M mt LG_thread_join
2701 lua_setfield( L, -2, "join"); // ... M mt
2702 lua_pushcfunction( L, LG_thread_cancel); // ... M mt LG_thread_cancel
2703 lua_setfield( L, -2, "cancel"); // ... M mt
2704 lua_pushliteral( L, "Lane"); // ... M mt "Lane"
2705 lua_setfield( L, -2, "__metatable"); // ... M mt
2706
2707 lua_pushcclosure( L, LG_thread_new, 1); // ... M LG_thread_new
2708 lua_setfield(L, -2, "thread_new"); // ... M
2709
2710 lua_pushstring(L, VERSION); // ... M VERSION
2711 lua_setfield(L, -2, "version"); // ... M
2712
2713 lua_pushinteger(L, THREAD_PRIO_MAX); // ... M THREAD_PRIO_MAX
2714 lua_setfield(L, -2, "max_prio"); // ... M
2715
2716 lua_pushlightuserdata( L, CANCEL_ERROR); // ... M CANCEL_ERROR
2717 lua_setfield(L, -2, "cancel_error"); // ... M
2718
2719 // register all native functions found in that module in the transferable functions database
2720 // we process it before _G because we don't want to find the module when scanning _G (this would generate longer names)
2721 // for example in package.loaded.lanes.core.*
2722 populate_func_lookup_table( L, -1, name);
2723
2724 // record all existing C/JIT-fast functions
2725 // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack
2726 lua_pushglobaltable( L); // ... M _G
2727 populate_func_lookup_table( L, -1, NULL);
2728 lua_pop( L, 1); // ... M
2729
2730 STACK_MID( L, 1)
2731 /*
2732 * Making one-time initializations.
2733 *
2734 * When the host application is single-threaded (and all threading happens via Lanes)
2735 * there is no problem. But if the host is multithreaded, we need to lock around the
2736 * initializations.
2737 *
2738 * we must do this after the populate_func_lookup_table is called, else populating the keepers will fail
2739 * because this makes a copy of packages.loaders, which requires the lookup tables to exist!
2740 */
2671#if THREADAPI == THREADAPI_WINDOWS 2741#if THREADAPI == THREADAPI_WINDOWS
2672 { 2742 {
2673 static volatile int /*bool*/ go_ahead; // = 0 2743 static volatile int /*bool*/ go_ahead; // = 0
2674 if( InterlockedCompareExchange( &s_initCount, 1, 0) == 0) 2744 if( InterlockedCompareExchange( &s_initCount, 1, 0) == 0)
2675 { 2745 {
2676 init_once_LOCKED( L, &timer_deep, nbKeepers, on_state_create, shutdown_timeout, track_lanes); 2746 init_once_LOCKED( L, nbKeepers, on_state_create, shutdown_timeout, track_lanes);
2677 go_ahead= 1; // let others pass 2747 go_ahead = 1; // let others pass
2678 } 2748 }
2679 else 2749 else
2680 { 2750 {
2681 while( !go_ahead ) { Sleep(1); } // changes threads 2751 while( !go_ahead ) { Sleep(1); } // changes threads
2682 } 2752 }
2683 } 2753 }
2684#else // THREADAPI == THREADAPI_PTHREAD 2754#else // THREADAPI == THREADAPI_PTHREAD
2685 if( s_initCount == 0) 2755 if( s_initCount == 0)
2686 { 2756 {
2687 static pthread_mutex_t my_lock= PTHREAD_MUTEX_INITIALIZER; 2757 static pthread_mutex_t my_lock = PTHREAD_MUTEX_INITIALIZER;
2688 pthread_mutex_lock( &my_lock); 2758 pthread_mutex_lock( &my_lock);
2689 { 2759 {
2690 // Recheck now that we're within the lock 2760 // Recheck now that we're within the lock
2691 // 2761 //
2692 if( s_initCount == 0) 2762 if( s_initCount == 0)
2693 { 2763 {
2694 init_once_LOCKED( L, &timer_deep, nbKeepers, on_state_create, shutdown_timeout, track_lanes); 2764 init_once_LOCKED( L, nbKeepers, on_state_create, shutdown_timeout, track_lanes);
2695 s_initCount = 1; 2765 s_initCount = 1;
2696 } 2766 }
2697 } 2767 }
2698 pthread_mutex_unlock(&my_lock); 2768 pthread_mutex_unlock( &my_lock);
2699 } 2769 }
2700#endif // THREADAPI == THREADAPI_PTHREAD 2770#endif // THREADAPI == THREADAPI_PTHREAD
2701 assert( timer_deep != 0 ); 2771 assert( timer_deep != NULL);
2702 2772 STACK_MID( L, 1)
2703 // Create main module interface table 2773
2704 lua_pushvalue( L, lua_upvalueindex( 2)); 2774 // init_once_LOCKED initializes timer_deep, so we must do this after, of course
2705 // remove configure() (this function) from the module interface 2775 luaG_push_proxy( L, linda_id, (DEEP_PRELUDE*) timer_deep); // ... M timer_deep
2706 lua_pushnil( L); 2776 lua_setfield( L, -2, "timer_gateway"); // ... M
2707 lua_setfield( L, -2, "configure"); 2777
2708 // add functions to the module's table 2778 lua_pop( L, 1); // ...
2709 luaG_registerlibfuncs(L, lanes_functions); 2779 STACK_END( L, 0)
2710 2780 // Return nothing
2711 // metatable for threads 2781 return 0;
2712 // contains keys: { __gc, __index, cached_error, cached_tostring, cancel, join } 2782}
2713 // 2783
2714 lua_newtable( L); 2784// helper to have correct callstacks when crashing a Win32 running on 64 bits Windows
2715 lua_pushcfunction( L, LG_thread_gc); 2785// don't forget to toggle Debug/Exceptions/Win32 in visual Studio too!
2716 lua_setfield( L, -2, "__gc"); 2786void EnableCrashingOnCrashes()
2717 lua_pushcfunction( L, LG_thread_index); 2787{
2718 lua_setfield( L, -2, "__index"); 2788#if 0 && defined PLATFORM_WIN32
2719 lua_getglobal( L, "error"); 2789 typedef BOOL (WINAPI *tGetPolicy)(LPDWORD lpFlags);
2720 ASSERT_L( lua_isfunction( L, -1)); 2790 typedef BOOL (WINAPI *tSetPolicy)(DWORD dwFlags);
2721 lua_setfield( L, -2, "cached_error"); 2791 const DWORD EXCEPTION_SWALLOWING = 0x1;
2722 lua_getglobal( L, "tostring"); 2792
2723 ASSERT_L( lua_isfunction( L, -1)); 2793 HMODULE kernel32 = LoadLibraryA("kernel32.dll");
2724 lua_setfield( L, -2, "cached_tostring"); 2794 tGetPolicy pGetPolicy = (tGetPolicy)GetProcAddress(kernel32, "GetProcessUserModeExceptionPolicy");
2725 lua_pushcfunction( L, LG_thread_join); 2795 tSetPolicy pSetPolicy = (tSetPolicy)GetProcAddress(kernel32, "SetProcessUserModeExceptionPolicy");
2726 lua_setfield( L, -2, "join"); 2796 if (pGetPolicy && pSetPolicy)
2727 lua_pushcfunction( L, LG_thread_cancel); 2797 {
2728 lua_setfield( L, -2, "cancel"); 2798 DWORD dwFlags;
2729 lua_pushliteral( L, "Lane"); 2799 if (pGetPolicy(&dwFlags))
2730 lua_setfield( L, -2, "__metatable"); 2800 {
2731 2801 // Turn off the filter
2732 lua_pushcclosure( L, LG_thread_new, 1 ); // metatable as closure param 2802 pSetPolicy(dwFlags & ~EXCEPTION_SWALLOWING);
2733 lua_setfield(L, -2, "thread_new"); 2803 }
2734 2804 }
2735 luaG_push_proxy( L, linda_id, (DEEP_PRELUDE *) timer_deep ); 2805#endif // PLATFORM_WIN32
2736 lua_setfield(L, -2, "timer_gateway");
2737
2738 lua_pushstring(L, VERSION);
2739 lua_setfield(L, -2, "version");
2740
2741 lua_pushinteger(L, THREAD_PRIO_MAX);
2742 lua_setfield(L, -2, "max_prio");
2743
2744 lua_pushlightuserdata( L, CANCEL_ERROR );
2745 lua_setfield(L, -2, "cancel_error");
2746
2747 // register all native functions found in that module in the transferable functions database
2748 // we process it before _G because we don't want to find the module when scanning _G (this would generate longer names)
2749 populate_func_lookup_table( L, -1, name);
2750 lua_pop( L, 1);
2751 // record all existing C/JIT-fast functions
2752 lua_pushglobaltable( L); // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack
2753 populate_func_lookup_table( L, -1, NULL);
2754 lua_pop( L, 1); // done with globals table, pop it
2755 // Return nothing
2756 return 0;
2757} 2806}
2758 2807
2759int 2808int
@@ -2762,6 +2811,8 @@ __declspec(dllexport)
2762#endif // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) 2811#endif // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)
2763luaopen_lanes_core( lua_State* L) 2812luaopen_lanes_core( lua_State* L)
2764{ 2813{
2814 EnableCrashingOnCrashes();
2815
2765 STACK_GROW( L, 3); 2816 STACK_GROW( L, 3);
2766 STACK_CHECK( L) 2817 STACK_CHECK( L)
2767 2818