diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/lanes.c | 143 |
1 files changed, 112 insertions, 31 deletions
diff --git a/src/lanes.c b/src/lanes.c index 6789e4e..161de59 100644 --- a/src/lanes.c +++ b/src/lanes.c | |||
| @@ -103,6 +103,11 @@ THE SOFTWARE. | |||
| 103 | # include <sys/types.h> | 103 | # include <sys/types.h> |
| 104 | #endif | 104 | #endif |
| 105 | 105 | ||
| 106 | /* | ||
| 107 | * Do we want to activate full lane tracking feature? (EXPERIMENTAL) | ||
| 108 | */ | ||
| 109 | #define HAVE_LANE_TRACKING 1 | ||
| 110 | |||
| 106 | /* Do you want full call stacks, or just the line where the error happened? | 111 | /* Do you want full call stacks, or just the line where the error happened? |
| 107 | * | 112 | * |
| 108 | * TBD: The full stack feature does not seem to work (try 'make error'). | 113 | * TBD: The full stack feature does not seem to work (try 'make error'). |
| @@ -118,7 +123,9 @@ struct s_lane { | |||
| 118 | // M: sub-thread OS thread | 123 | // M: sub-thread OS thread |
| 119 | // S: not used | 124 | // S: not used |
| 120 | 125 | ||
| 121 | lua_State *L; | 126 | char const* debug_name; |
| 127 | |||
| 128 | lua_State* L; | ||
| 122 | // | 129 | // |
| 123 | // M: prepares the state, and reads results | 130 | // M: prepares the state, and reads results |
| 124 | // S: while S is running, M must keep out of modifying the state | 131 | // S: while S is running, M must keep out of modifying the state |
| @@ -164,8 +171,8 @@ struct s_lane { | |||
| 164 | // S: cleans up after itself if non-NULL at lane exit | 171 | // S: cleans up after itself if non-NULL at lane exit |
| 165 | }; | 172 | }; |
| 166 | 173 | ||
| 167 | static bool_t cancel_test( lua_State *L ); | 174 | static bool_t cancel_test( lua_State*L ); |
| 168 | static void cancel_error( lua_State *L ); | 175 | static void cancel_error( lua_State*L ); |
| 169 | 176 | ||
| 170 | #define CANCEL_TEST_KEY ((void*)cancel_test) // used as registry key | 177 | #define CANCEL_TEST_KEY ((void*)cancel_test) // used as registry key |
| 171 | #define CANCEL_ERROR ((void*)cancel_error) // 'cancel_error' sentinel | 178 | #define CANCEL_ERROR ((void*)cancel_error) // 'cancel_error' sentinel |
| @@ -204,7 +211,7 @@ struct s_Linda; | |||
| 204 | * Returns: TRUE if a table was pushed | 211 | * Returns: TRUE if a table was pushed |
| 205 | * FALSE if no table found, not created, and nothing pushed | 212 | * FALSE if no table found, not created, and nothing pushed |
| 206 | */ | 213 | */ |
| 207 | static bool_t push_registry_table( lua_State *L, void *key, bool_t create ) { | 214 | static bool_t push_registry_table( lua_State*L, void *key, bool_t create ) { |
| 208 | 215 | ||
| 209 | STACK_GROW(L,3); | 216 | STACK_GROW(L,3); |
| 210 | 217 | ||
| @@ -247,7 +254,7 @@ static void linda_id( lua_State*, char const * const which); | |||
| 247 | #define lua_toLinda(L,n) ((struct s_Linda *)luaG_todeep( L, linda_id, n )) | 254 | #define lua_toLinda(L,n) ((struct s_Linda *)luaG_todeep( L, linda_id, n )) |
| 248 | 255 | ||
| 249 | 256 | ||
| 250 | static void check_key_types( lua_State *L, int _start, int _end) | 257 | static void check_key_types( lua_State*L, int _start, int _end) |
| 251 | { | 258 | { |
| 252 | int i; | 259 | int i; |
| 253 | for( i = _start; i <= _end; ++ i) | 260 | for( i = _start; i <= _end; ++ i) |
| @@ -305,7 +312,7 @@ LUAG_FUNC( linda_send) | |||
| 305 | STACK_GROW(L, 1); | 312 | STACK_GROW(L, 1); |
| 306 | { | 313 | { |
| 307 | struct s_Keeper *K = keeper_acquire( linda); | 314 | struct s_Keeper *K = keeper_acquire( linda); |
| 308 | lua_State *KL = K->L; // need to do this for 'STACK_CHECK' | 315 | lua_State*KL = K->L; // need to do this for 'STACK_CHECK' |
| 309 | STACK_CHECK( KL) | 316 | STACK_CHECK( KL) |
| 310 | for( ;;) | 317 | for( ;;) |
| 311 | { | 318 | { |
| @@ -720,8 +727,6 @@ LUAG_FUNC( linda_deep ) { | |||
| 720 | 727 | ||
| 721 | static int linda_tostring( lua_State* L, int _idx, bool_t _opt) | 728 | static int linda_tostring( lua_State* L, int _idx, bool_t _opt) |
| 722 | { | 729 | { |
| 723 | char text[32]; | ||
| 724 | int len; | ||
| 725 | struct s_Linda* linda = lua_toLinda( L, _idx); | 730 | struct s_Linda* linda = lua_toLinda( L, _idx); |
| 726 | if( !_opt) | 731 | if( !_opt) |
| 727 | { | 732 | { |
| @@ -729,6 +734,8 @@ static int linda_tostring( lua_State* L, int _idx, bool_t _opt) | |||
| 729 | } | 734 | } |
| 730 | if( linda) | 735 | if( linda) |
| 731 | { | 736 | { |
| 737 | char text[32]; | ||
| 738 | int len; | ||
| 732 | if( linda->name[0]) | 739 | if( linda->name[0]) |
| 733 | len = sprintf( text, "Linda: %.*s", (int)sizeof(text) - 8, linda->name); | 740 | len = sprintf( text, "Linda: %.*s", (int)sizeof(text) - 8, linda->name); |
| 734 | else | 741 | else |
| @@ -808,7 +815,7 @@ LUAG_FUNC( linda_dump) | |||
| 808 | * For any other strings, the ID function must not react at all. This allows | 815 | * For any other strings, the ID function must not react at all. This allows |
| 809 | * future extensions of the system. | 816 | * future extensions of the system. |
| 810 | */ | 817 | */ |
| 811 | static void linda_id( lua_State *L, char const * const which) | 818 | static void linda_id( lua_State*L, char const * const which) |
| 812 | { | 819 | { |
| 813 | if (strcmp( which, "new" )==0) | 820 | if (strcmp( which, "new" )==0) |
| 814 | { | 821 | { |
| @@ -981,7 +988,7 @@ LUAG_FUNC( set_finalizer ) | |||
| 981 | // | 988 | // |
| 982 | // TBD: should we add stack trace on failing finalizer, wouldn't be hard.. | 989 | // TBD: should we add stack trace on failing finalizer, wouldn't be hard.. |
| 983 | // | 990 | // |
| 984 | static int run_finalizers( lua_State *L, int lua_rc ) | 991 | static int run_finalizers( lua_State*L, int lua_rc ) |
| 985 | { | 992 | { |
| 986 | unsigned error_index, tbl_index; | 993 | unsigned error_index, tbl_index; |
| 987 | unsigned n; | 994 | unsigned n; |
| @@ -1176,7 +1183,7 @@ volatile DEEP_PRELUDE *timer_deep; // = NULL | |||
| 1176 | /* | 1183 | /* |
| 1177 | * Process end; cancel any still free-running threads | 1184 | * Process end; cancel any still free-running threads |
| 1178 | */ | 1185 | */ |
| 1179 | static int selfdestruct_gc( lua_State *L) | 1186 | static int selfdestruct_gc( lua_State*L) |
| 1180 | { | 1187 | { |
| 1181 | (void)L; // unused | 1188 | (void)L; // unused |
| 1182 | if (selfdestruct_first == SELFDESTRUCT_END) return 0; // no free-running threads | 1189 | if (selfdestruct_first == SELFDESTRUCT_END) return 0; // no free-running threads |
| @@ -1341,7 +1348,7 @@ static int selfdestruct_gc( lua_State *L) | |||
| 1341 | * Returns TRUE if any locks are to be exited, and 'cancel_error()' called, | 1348 | * Returns TRUE if any locks are to be exited, and 'cancel_error()' called, |
| 1342 | * to make execution of the lane end. | 1349 | * to make execution of the lane end. |
| 1343 | */ | 1350 | */ |
| 1344 | static bool_t cancel_test( lua_State *L ) { | 1351 | static bool_t cancel_test( lua_State*L ) { |
| 1345 | struct s_lane *s; | 1352 | struct s_lane *s; |
| 1346 | 1353 | ||
| 1347 | STACK_GROW(L,1); | 1354 | STACK_GROW(L,1); |
| @@ -1358,13 +1365,13 @@ static bool_t cancel_test( lua_State *L ) { | |||
| 1358 | return s && s->cancel_request; | 1365 | return s && s->cancel_request; |
| 1359 | } | 1366 | } |
| 1360 | 1367 | ||
| 1361 | static void cancel_error( lua_State *L ) { | 1368 | static void cancel_error( lua_State*L ) { |
| 1362 | STACK_GROW(L,1); | 1369 | STACK_GROW(L,1); |
| 1363 | lua_pushlightuserdata( L, CANCEL_ERROR ); // special error value | 1370 | lua_pushlightuserdata( L, CANCEL_ERROR ); // special error value |
| 1364 | lua_error(L); // no return | 1371 | lua_error(L); // no return |
| 1365 | } | 1372 | } |
| 1366 | 1373 | ||
| 1367 | static void cancel_hook( lua_State *L, lua_Debug *ar ) { | 1374 | static void cancel_hook( lua_State*L, lua_Debug *ar ) { |
| 1368 | (void)ar; | 1375 | (void)ar; |
| 1369 | if (cancel_test(L)) cancel_error(L); | 1376 | if (cancel_test(L)) cancel_error(L); |
| 1370 | } | 1377 | } |
| @@ -1546,19 +1553,39 @@ static int lane_error( lua_State* L) | |||
| 1546 | 1553 | ||
| 1547 | LUAG_FUNC( set_debug_threadname) | 1554 | LUAG_FUNC( set_debug_threadname) |
| 1548 | { | 1555 | { |
| 1549 | luaL_checktype( L, -1, LUA_TSTRING); | 1556 | struct s_lane* s = lua_touserdata( L, lua_upvalueindex( 1)); |
| 1550 | THREAD_SETNAME( lua_tostring( L, -1)); | 1557 | luaL_checktype( L, -1, LUA_TSTRING); // "name" |
| 1558 | // store a hidden reference in the registry to make sure the string is kept around even if a lane decides to manually change the "decoda_name" global... | ||
| 1559 | lua_pushlightuserdata( L, LG_set_debug_threadname); // "name" lud | ||
| 1560 | lua_pushvalue( L, -2); // "name" lud "name" | ||
| 1561 | lua_rawset( L, LUA_REGISTRYINDEX); // "name" | ||
| 1562 | s->debug_name = lua_tostring( L, -1); | ||
| 1563 | // keep a direct pointer on the string | ||
| 1564 | THREAD_SETNAME( s->debug_name); | ||
| 1551 | // to see VM name in Decoda debugger Virtual Machine window | 1565 | // to see VM name in Decoda debugger Virtual Machine window |
| 1552 | lua_setglobal( L, "decoda_name"); | 1566 | lua_setglobal( L, "decoda_name"); // |
| 1553 | return 0; | 1567 | return 0; |
| 1554 | } | 1568 | } |
| 1555 | 1569 | ||
| 1570 | #if HAVE_LANE_TRACKING | ||
| 1571 | static bool_t GTrackLanes = FALSE; | ||
| 1572 | #endif // HAVE_LANE_TRACKING | ||
| 1573 | |||
| 1556 | //--- | 1574 | //--- |
| 1557 | static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs) | 1575 | static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs) |
| 1558 | { | 1576 | { |
| 1559 | struct s_lane *s= (struct s_lane *)vs; | 1577 | struct s_lane *s= (struct s_lane *)vs; |
| 1560 | int rc, rc2; | 1578 | int rc, rc2; |
| 1561 | lua_State *L= s->L; | 1579 | lua_State*L= s->L; |
| 1580 | |||
| 1581 | #if HAVE_LANE_TRACKING | ||
| 1582 | if( GTrackLanes) | ||
| 1583 | { | ||
| 1584 | // If we track lanes, we add them right now to the list so that its traversal hits all known lanes | ||
| 1585 | // (else we get only the still running lanes for which GC was called, IOW not accessible anymore from a script) | ||
| 1586 | selfdestruct_add( s); | ||
| 1587 | } | ||
| 1588 | #endif // HAVE_LANE_TRACKING | ||
| 1562 | 1589 | ||
| 1563 | s->status= RUNNING; // PENDING -> RUNNING | 1590 | s->status= RUNNING; // PENDING -> RUNNING |
| 1564 | 1591 | ||
| @@ -1569,7 +1596,8 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs) | |||
| 1569 | 1596 | ||
| 1570 | // Tie "set_debug_threadname()" to the state | 1597 | // Tie "set_debug_threadname()" to the state |
| 1571 | // | 1598 | // |
| 1572 | lua_pushcfunction( L, LG_set_debug_threadname); | 1599 | lua_pushlightuserdata( L, s); |
| 1600 | lua_pushcclosure( L, LG_set_debug_threadname, 1); | ||
| 1573 | lua_setglobal( L, "set_debug_threadname" ); | 1601 | lua_setglobal( L, "set_debug_threadname" ); |
| 1574 | 1602 | ||
| 1575 | // Tie "cancel_test()" to the state | 1603 | // Tie "cancel_test()" to the state |
| @@ -1704,7 +1732,7 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs) | |||
| 1704 | 1732 | ||
| 1705 | // helper function to require a module in the keeper states and in the target state | 1733 | // helper function to require a module in the keeper states and in the target state |
| 1706 | // source state contains module name at the top of the stack | 1734 | // source state contains module name at the top of the stack |
| 1707 | static void require_one_module( lua_State *L, lua_State *L2, bool_t _fatal) | 1735 | static void require_one_module( lua_State*L, lua_State*L2, bool_t _fatal) |
| 1708 | { | 1736 | { |
| 1709 | size_t len; | 1737 | size_t len; |
| 1710 | char const *name = lua_tolstring( L, -1, &len); | 1738 | char const *name = lua_tolstring( L, -1, &len); |
| @@ -1728,7 +1756,7 @@ static void require_one_module( lua_State *L, lua_State *L2, bool_t _fatal) | |||
| 1728 | 1756 | ||
| 1729 | LUAG_FUNC( thread_new ) | 1757 | LUAG_FUNC( thread_new ) |
| 1730 | { | 1758 | { |
| 1731 | lua_State *L2; | 1759 | lua_State*L2; |
| 1732 | struct s_lane *s; | 1760 | struct s_lane *s; |
| 1733 | struct s_lane **ud; | 1761 | struct s_lane **ud; |
| 1734 | 1762 | ||
| @@ -1918,6 +1946,7 @@ LUAG_FUNC( thread_new ) | |||
| 1918 | s->L= L2; | 1946 | s->L= L2; |
| 1919 | s->status= PENDING; | 1947 | s->status= PENDING; |
| 1920 | s->waiting_on = NULL; | 1948 | s->waiting_on = NULL; |
| 1949 | s->debug_name = NULL; | ||
| 1921 | s->cancel_request= FALSE; | 1950 | s->cancel_request= FALSE; |
| 1922 | 1951 | ||
| 1923 | #if THREADWAIT_METHOD == THREADWAIT_CONDVAR | 1952 | #if THREADWAIT_METHOD == THREADWAIT_CONDVAR |
| @@ -1995,9 +2024,14 @@ LUAG_FUNC( thread_gc) | |||
| 1995 | } | 2024 | } |
| 1996 | else if( s->status < DONE) | 2025 | else if( s->status < DONE) |
| 1997 | { | 2026 | { |
| 1998 | // still running: will have to be cleaned up later | 2027 | #if HAVE_LANE_TRACKING |
| 1999 | selfdestruct_add( s); | 2028 | if( !GTrackLanes) |
| 2000 | assert( s->selfdestruct_next); | 2029 | #endif // HAVE_LANE_TRACKING |
| 2030 | { | ||
| 2031 | // still running: will have to be cleaned up later | ||
| 2032 | selfdestruct_add( s); | ||
| 2033 | assert( s->selfdestruct_next); | ||
| 2034 | } | ||
| 2001 | return 0; | 2035 | return 0; |
| 2002 | 2036 | ||
| 2003 | } | 2037 | } |
| @@ -2008,6 +2042,14 @@ LUAG_FUNC( thread_gc) | |||
| 2008 | s->L = 0; | 2042 | s->L = 0; |
| 2009 | } | 2043 | } |
| 2010 | 2044 | ||
| 2045 | #if HAVE_LANE_TRACKING | ||
| 2046 | if( GTrackLanes) | ||
| 2047 | { | ||
| 2048 | // Lane was cleaned up, no need to handle at process termination | ||
| 2049 | selfdestruct_remove( s); | ||
| 2050 | } | ||
| 2051 | #endif // HAVE_LANE_TRACKING | ||
| 2052 | |||
| 2011 | // Clean up after a (finished) thread | 2053 | // Clean up after a (finished) thread |
| 2012 | // | 2054 | // |
| 2013 | #if THREADWAIT_METHOD == THREADWAIT_CONDVAR | 2055 | #if THREADWAIT_METHOD == THREADWAIT_CONDVAR |
| @@ -2091,7 +2133,7 @@ static char const * thread_status_string( struct s_lane *s) | |||
| 2091 | return str; | 2133 | return str; |
| 2092 | } | 2134 | } |
| 2093 | 2135 | ||
| 2094 | static int push_thread_status( lua_State *L, struct s_lane *s) | 2136 | static int push_thread_status( lua_State*L, struct s_lane *s) |
| 2095 | { | 2137 | { |
| 2096 | char const * const str = thread_status_string( s); | 2138 | char const * const str = thread_status_string( s); |
| 2097 | ASSERT_L( str); | 2139 | ASSERT_L( str); |
| @@ -2113,7 +2155,7 @@ LUAG_FUNC( thread_join) | |||
| 2113 | { | 2155 | { |
| 2114 | struct s_lane* const s = lua_toLane( L, 1); | 2156 | struct s_lane* const s = lua_toLane( L, 1); |
| 2115 | double wait_secs= luaL_optnumber(L,2,-1.0); | 2157 | double wait_secs= luaL_optnumber(L,2,-1.0); |
| 2116 | lua_State *L2= s->L; | 2158 | lua_State*L2= s->L; |
| 2117 | int ret; | 2159 | int ret; |
| 2118 | bool_t done; | 2160 | bool_t done; |
| 2119 | 2161 | ||
| @@ -2329,6 +2371,37 @@ LUAG_FUNC( thread_index) | |||
| 2329 | return 0; | 2371 | return 0; |
| 2330 | } | 2372 | } |
| 2331 | 2373 | ||
| 2374 | #if HAVE_LANE_TRACKING | ||
| 2375 | //--- | ||
| 2376 | // threads() -> {}|nil | ||
| 2377 | // | ||
| 2378 | // Return a list of all known lanes | ||
| 2379 | LUAG_FUNC( threads) | ||
| 2380 | { | ||
| 2381 | int const top = lua_gettop( L); | ||
| 2382 | // List _all_ still running threads | ||
| 2383 | // | ||
| 2384 | MUTEX_LOCK( &selfdestruct_cs); | ||
| 2385 | if( selfdestruct_first != SELFDESTRUCT_END) | ||
| 2386 | { | ||
| 2387 | struct s_lane* s = selfdestruct_first; | ||
| 2388 | lua_newtable( L); // {} | ||
| 2389 | while( s != SELFDESTRUCT_END) | ||
| 2390 | { | ||
| 2391 | if( s->debug_name) | ||
| 2392 | lua_pushstring( L, s->debug_name); // {} "name" | ||
| 2393 | else | ||
| 2394 | lua_pushfstring( L, "Lane %p", s); // {} "name" | ||
| 2395 | push_thread_status( L, s); // {} "name" "status" | ||
| 2396 | lua_rawset( L, -3); // {} | ||
| 2397 | s = s->selfdestruct_next; | ||
| 2398 | } | ||
| 2399 | } | ||
| 2400 | MUTEX_UNLOCK( &selfdestruct_cs); | ||
| 2401 | return lua_gettop( L) - top; | ||
| 2402 | } | ||
| 2403 | #endif // HAVE_LANE_TRACKING | ||
| 2404 | |||
| 2332 | /* | 2405 | /* |
| 2333 | * ############################################################################################### | 2406 | * ############################################################################################### |
| 2334 | * ######################################## Timer support ######################################## | 2407 | * ######################################## Timer support ######################################## |
| @@ -2401,6 +2474,9 @@ LUAG_FUNC( wakeup_conv ) | |||
| 2401 | static const struct luaL_Reg lanes_functions [] = { | 2474 | static const struct luaL_Reg lanes_functions [] = { |
| 2402 | {"linda", LG_linda}, | 2475 | {"linda", LG_linda}, |
| 2403 | {"now_secs", LG_now_secs}, | 2476 | {"now_secs", LG_now_secs}, |
| 2477 | #if HAVE_LANE_TRACKING | ||
| 2478 | {"threads", LG_threads}, | ||
| 2479 | #endif // HAVE_LANE_TRACKING | ||
| 2404 | {"wakeup_conv", LG_wakeup_conv}, | 2480 | {"wakeup_conv", LG_wakeup_conv}, |
| 2405 | {"nameof", luaG_nameof}, | 2481 | {"nameof", luaG_nameof}, |
| 2406 | {"set_singlethreaded", LG_set_singlethreaded}, | 2482 | {"set_singlethreaded", LG_set_singlethreaded}, |
| @@ -2410,7 +2486,7 @@ static const struct luaL_Reg lanes_functions [] = { | |||
| 2410 | /* | 2486 | /* |
| 2411 | * One-time initializations | 2487 | * One-time initializations |
| 2412 | */ | 2488 | */ |
| 2413 | static 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) | 2489 | static 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) |
| 2414 | { | 2490 | { |
| 2415 | const char *err; | 2491 | const char *err; |
| 2416 | 2492 | ||
| @@ -2421,7 +2497,11 @@ static void init_once_LOCKED( lua_State* L, volatile DEEP_PRELUDE** timer_deep_r | |||
| 2421 | #if (defined PLATFORM_OSX) && (defined _UTILBINDTHREADTOCPU) | 2497 | #if (defined PLATFORM_OSX) && (defined _UTILBINDTHREADTOCPU) |
| 2422 | chudInitialize(); | 2498 | chudInitialize(); |
| 2423 | #endif | 2499 | #endif |
| 2424 | 2500 | ||
| 2501 | #if HAVE_LANE_TRACKING | ||
| 2502 | GTrackLanes = _track_lanes; | ||
| 2503 | #endif // HAVE_LANE_TRACKING | ||
| 2504 | |||
| 2425 | // Locks for 'tools.c' inc/dec counters | 2505 | // Locks for 'tools.c' inc/dec counters |
| 2426 | // | 2506 | // |
| 2427 | MUTEX_INIT( &deep_lock ); | 2507 | MUTEX_INIT( &deep_lock ); |
| @@ -2516,6 +2596,7 @@ LUAG_FUNC( configure ) | |||
| 2516 | int const nbKeepers = (int)lua_tointeger( L, 1); | 2596 | int const nbKeepers = (int)lua_tointeger( L, 1); |
| 2517 | lua_CFunction on_state_create = lua_iscfunction( L, 2) ? lua_tocfunction( L, 2) : NULL; | 2597 | lua_CFunction on_state_create = lua_iscfunction( L, 2) ? lua_tocfunction( L, 2) : NULL; |
| 2518 | lua_Number shutdown_timeout = lua_tonumber( L, 3); | 2598 | lua_Number shutdown_timeout = lua_tonumber( L, 3); |
| 2599 | bool_t track_lanes = lua_toboolean( L, 4); | ||
| 2519 | /* | 2600 | /* |
| 2520 | * Making one-time initializations. | 2601 | * Making one-time initializations. |
| 2521 | * | 2602 | * |
| @@ -2528,7 +2609,7 @@ LUAG_FUNC( configure ) | |||
| 2528 | static volatile int /*bool*/ go_ahead; // = 0 | 2609 | static volatile int /*bool*/ go_ahead; // = 0 |
| 2529 | if( InterlockedCompareExchange( &s_initCount, 1, 0) == 0) | 2610 | if( InterlockedCompareExchange( &s_initCount, 1, 0) == 0) |
| 2530 | { | 2611 | { |
| 2531 | init_once_LOCKED( L, &timer_deep, nbKeepers, on_state_create, shutdown_timeout); | 2612 | init_once_LOCKED( L, &timer_deep, nbKeepers, on_state_create, shutdown_timeout, track_lanes); |
| 2532 | go_ahead= 1; // let others pass | 2613 | go_ahead= 1; // let others pass |
| 2533 | } | 2614 | } |
| 2534 | else | 2615 | else |
| @@ -2546,7 +2627,7 @@ LUAG_FUNC( configure ) | |||
| 2546 | // | 2627 | // |
| 2547 | if( s_initCount == 0) | 2628 | if( s_initCount == 0) |
| 2548 | { | 2629 | { |
| 2549 | init_once_LOCKED( L, &timer_deep, nbKeepers, on_state_create, shutdown_timeout); | 2630 | init_once_LOCKED( L, &timer_deep, nbKeepers, on_state_create, shutdown_timeout, track_lanes); |
| 2550 | s_initCount = 1; | 2631 | s_initCount = 1; |
| 2551 | } | 2632 | } |
| 2552 | } | 2633 | } |
| @@ -2569,7 +2650,7 @@ LUAG_FUNC( configure ) | |||
| 2569 | lua_newtable( L); | 2650 | lua_newtable( L); |
| 2570 | lua_pushcfunction( L, LG_thread_gc); | 2651 | lua_pushcfunction( L, LG_thread_gc); |
| 2571 | lua_setfield( L, -2, "__gc"); | 2652 | lua_setfield( L, -2, "__gc"); |
| 2572 | lua_pushcfunction( L, LG_thread_index); | 2653 | lua_pushcfunction( L, LG_thread_index); |
| 2573 | lua_setfield( L, -2, "__index"); | 2654 | lua_setfield( L, -2, "__index"); |
| 2574 | lua_getglobal( L, "error"); | 2655 | lua_getglobal( L, "error"); |
| 2575 | ASSERT_L( lua_isfunction( L, -1)); | 2656 | ASSERT_L( lua_isfunction( L, -1)); |
