aboutsummaryrefslogtreecommitdiff
path: root/src/lanes.c
diff options
context:
space:
mode:
authorBenoit Germain <bnt.germain@gmail.com>2011-11-14 19:41:28 +0100
committerBenoit Germain <bnt.germain@gmail.com>2011-11-14 19:41:28 +0100
commit87431bcc0ece1eaf9305593223bb0c5145004044 (patch)
treee1a76ea727e8019d3c26c4829dbb95253dd7e1f6 /src/lanes.c
parent1d2b45823fd2a13761bd2d19b1b5a1e8bb11f7b9 (diff)
downloadlanes-87431bcc0ece1eaf9305593223bb0c5145004044.tar.gz
lanes-87431bcc0ece1eaf9305593223bb0c5145004044.tar.bz2
lanes-87431bcc0ece1eaf9305593223bb0c5145004044.zip
* removed packagepath and packagecpath options, replaced by a package table, whose fields path, cpath, loaders, preload are transfered
* code cleanup to facilitate transition between WIN32 and PTHREAD impleentations * tentative fix for desinit crashes when free running lanes are killed at process shutdown
Diffstat (limited to 'src/lanes.c')
-rw-r--r--src/lanes.c161
1 files changed, 71 insertions, 90 deletions
diff --git a/src/lanes.c b/src/lanes.c
index aef1015..40af6c0 100644
--- a/src/lanes.c
+++ b/src/lanes.c
@@ -139,7 +139,7 @@ struct s_lane {
139 // M: sets to FALSE, flags TRUE for cancel request 139 // M: sets to FALSE, flags TRUE for cancel request
140 // S: reads to see if cancel is requested 140 // S: reads to see if cancel is requested
141 141
142#if !( (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN) ) 142#if THREADWAIT_METHOD == THREADWAIT_CONDVAR
143 SIGNAL_T done_signal_; 143 SIGNAL_T done_signal_;
144 // 144 //
145 // M: Waited upon at lane ending (if Posix with no PTHREAD_TIMEDJOIN) 145 // M: Waited upon at lane ending (if Posix with no PTHREAD_TIMEDJOIN)
@@ -149,7 +149,7 @@ struct s_lane {
149 // 149 //
150 // Lock required by 'done_signal' condition variable, protecting 150 // Lock required by 'done_signal' condition variable, protecting
151 // lane status changes to DONE/ERROR_ST/CANCELLED. 151 // lane status changes to DONE/ERROR_ST/CANCELLED.
152#endif 152#endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR
153 153
154 volatile enum { 154 volatile enum {
155 NORMAL, // normal master side state 155 NORMAL, // normal master side state
@@ -1150,9 +1150,17 @@ static int selfdestruct_atexit( lua_State *L)
1150 { 1150 {
1151 struct s_lane *next_s= s->selfdestruct_next; 1151 struct s_lane *next_s= s->selfdestruct_next;
1152 s->selfdestruct_next= NULL; // detach from selfdestruct chain 1152 s->selfdestruct_next= NULL; // detach from selfdestruct chain
1153 if( s->thread) // can be NULL if previous 'soft' termination succeeded 1153 if( !THREAD_ISNULL( s->thread)) // can be NULL if previous 'soft' termination succeeded
1154 {
1154 THREAD_KILL( &s->thread); 1155 THREAD_KILL( &s->thread);
1156 // make sure the thread is really stopped!
1157 THREAD_WAIT( &s->thread, -1, &s->done_signal_, &s->done_lock_, &s->status);
1158 }
1155 // NO lua_close() in this case because we don't know where execution of the state was interrupted 1159 // NO lua_close() in this case because we don't know where execution of the state was interrupted
1160#if THREADWAIT_METHOD == THREADWAIT_CONDVAR
1161 SIGNAL_FREE( &s->done_signal_);
1162 MUTEX_FREE( &s->done_lock_);
1163#endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR
1156 free( s); 1164 free( s);
1157 s = next_s; 1165 s = next_s;
1158 n++; 1166 n++;
@@ -1374,11 +1382,7 @@ LUAG_FUNC( set_debug_threadname)
1374} 1382}
1375 1383
1376//--- 1384//---
1377#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) 1385static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs)
1378 static THREAD_RETURN_T __stdcall lane_main( void *vs )
1379#else
1380 static THREAD_RETURN_T lane_main( void *vs )
1381#endif
1382{ 1386{
1383 struct s_lane *s= (struct s_lane *)vs; 1387 struct s_lane *s= (struct s_lane *)vs;
1384 int rc, rc2; 1388 int rc, rc2;
@@ -1475,13 +1479,15 @@ LUAG_FUNC( set_debug_threadname)
1475 lua_close( s->L ); 1479 lua_close( s->L );
1476 s->L = L = 0; 1480 s->L = L = 0;
1477 1481
1478 #if !( (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN) ) 1482 #if THREADWAIT_METHOD == THREADWAIT_CONDVAR
1479 SIGNAL_FREE( &s->done_signal_ ); 1483 SIGNAL_FREE( &s->done_signal_);
1480 MUTEX_FREE( &s->done_lock_ ); 1484 MUTEX_FREE( &s->done_lock_);
1481 #endif 1485 #endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR
1482 free(s); 1486 free(s);
1483 1487
1484 } else { 1488 }
1489 else
1490 {
1485 // leave results (1..top) or error message + stack trace (1..2) on the stack - master will copy them 1491 // leave results (1..top) or error message + stack trace (1..2) on the stack - master will copy them
1486 1492
1487 enum e_status st= 1493 enum e_status st=
@@ -1492,16 +1498,16 @@ LUAG_FUNC( set_debug_threadname)
1492 // Posix no PTHREAD_TIMEDJOIN: 1498 // Posix no PTHREAD_TIMEDJOIN:
1493 // 'done_lock' protects the -> DONE|ERROR_ST|CANCELLED state change 1499 // 'done_lock' protects the -> DONE|ERROR_ST|CANCELLED state change
1494 // 1500 //
1495 #if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN) 1501#if THREADWAIT_METHOD == THREADWAIT_CONDVAR
1496 s->status= st; 1502 MUTEX_LOCK( &s->done_lock_);
1497 #else
1498 MUTEX_LOCK( &s->done_lock_ );
1499 { 1503 {
1500 s->status= st; 1504#endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR
1501 SIGNAL_ONE( &s->done_signal_ ); // wake up master (while 's->done_lock' is on) 1505 s->status = st;
1506#if THREADWAIT_METHOD == THREADWAIT_CONDVAR
1507 SIGNAL_ONE( &s->done_signal_); // wake up master (while 's->done_lock' is on)
1502 } 1508 }
1503 MUTEX_UNLOCK( &s->done_lock_ ); 1509 MUTEX_UNLOCK( &s->done_lock_);
1504 #endif 1510#endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR
1505 } 1511 }
1506 return 0; // ignored 1512 return 0; // ignored
1507} 1513}
@@ -1512,7 +1518,7 @@ LUAG_FUNC( set_debug_threadname)
1512// [cancelstep_uint=0], 1518// [cancelstep_uint=0],
1513// [prio_int=0], 1519// [prio_int=0],
1514// [globals_tbl], 1520// [globals_tbl],
1515// [packagepath], 1521// [package_tbl],
1516// [required], 1522// [required],
1517// [... args ...] ) 1523// [... args ...] )
1518// 1524//
@@ -1553,11 +1559,10 @@ LUAG_FUNC( thread_new )
1553 uint_t cs= luaG_optunsigned( L, 3,0); 1559 uint_t cs= luaG_optunsigned( L, 3,0);
1554 int prio= (int)luaL_optinteger( L, 4,0); 1560 int prio= (int)luaL_optinteger( L, 4,0);
1555 uint_t glob= luaG_isany(L,5) ? 5:0; 1561 uint_t glob= luaG_isany(L,5) ? 5:0;
1556 uint_t ppath = luaG_isany(L,6) ? 6:0; 1562 uint_t package = luaG_isany(L,6) ? 6:0;
1557 uint_t pcpath = luaG_isany(L,7) ? 7:0; 1563 uint_t required = luaG_isany(L,7) ? 7:0;
1558 uint_t required = luaG_isany(L,8) ? 8:0;
1559 1564
1560#define FIXED_ARGS (8) 1565#define FIXED_ARGS (7)
1561 uint_t args= lua_gettop(L) - FIXED_ARGS; 1566 uint_t args= lua_gettop(L) - FIXED_ARGS;
1562 1567
1563 if (prio < THREAD_PRIO_MIN || prio > THREAD_PRIO_MAX) 1568 if (prio < THREAD_PRIO_MIN || prio > THREAD_PRIO_MAX)
@@ -1588,46 +1593,35 @@ LUAG_FUNC( thread_new )
1588 ASSERT_L( lua_gettop(L2) == 0); 1593 ASSERT_L( lua_gettop(L2) == 0);
1589 1594
1590 // package.path 1595 // package.path
1596 STACK_CHECK(L)
1591 STACK_CHECK(L2) 1597 STACK_CHECK(L2)
1592 if( ppath) 1598 if( package)
1593 {
1594 if (lua_type(L,ppath) != LUA_TSTRING)
1595 luaL_error( L, "expected packagepath as string, got %s", luaG_typename(L,ppath));
1596 lua_getglobal( L2, "package");
1597 if( lua_isnil( L2, -1)) // package library not loaded: do nothing
1598 {
1599 lua_pop( L2, 1);
1600 }
1601 else
1602 {
1603 lua_pushvalue( L, ppath);
1604 luaG_inter_move( L, L2, 1); // moves the new path to L2
1605 lua_setfield( L2, -2, "path"); // set package.path
1606 lua_pop( L2, 1);
1607 }
1608 }
1609 STACK_END(L2,0)
1610
1611 // package.cpath
1612 STACK_CHECK(L2)
1613 if( pcpath)
1614 { 1599 {
1615 if (lua_type(L,pcpath) != LUA_TSTRING) 1600 if (lua_type(L,package) != LUA_TTABLE)
1616 luaL_error( L, "expected packagecpath as string, got %s", luaG_typename(L,pcpath)); 1601 luaL_error( L, "expected package as table, got %s", luaG_typename(L,package));
1617 lua_getglobal( L2, "package"); 1602 lua_getglobal( L2, "package");
1618 if( lua_isnil( L2, -1)) // // package library not loaded: do nothing 1603 if( !lua_isnil( L2, -1)) // package library not loaded: do nothing
1619 { 1604 {
1620 lua_pop( L2, 1); 1605 int i;
1621 } 1606 char const *entries[] = { "path", "cpath", "preload", "loaders", NULL};
1622 else 1607 for( i = 0; entries[i]; ++ i)
1623 { 1608 {
1624 lua_pushvalue( L, pcpath); 1609 lua_getfield( L, package, entries[i]);
1625 luaG_inter_move( L, L2, 1); // moves the new cpath to L2 1610 if( lua_isnil( L, -1))
1626 lua_setfield( L2, -2, "cpath"); // set package.cpath 1611 {
1627 lua_pop( L2, 1); 1612 lua_pop( L, 1);
1613 }
1614 else
1615 {
1616 luaG_inter_move( L, L2, 1); // moves the entry to L2
1617 lua_setfield( L2, -2, entries[i]); // set package[entries[i]]
1618 }
1619 }
1628 } 1620 }
1621 lua_pop( L2, 1);
1629 } 1622 }
1630 STACK_END(L2,0) 1623 STACK_END(L2,0)
1624 STACK_END(L,0)
1631 1625
1632 // modules to require in the target lane *before* the function is transfered! 1626 // modules to require in the target lane *before* the function is transfered!
1633 1627
@@ -1738,10 +1732,10 @@ LUAG_FUNC( thread_new )
1738 s->waiting_on = NULL; 1732 s->waiting_on = NULL;
1739 s->cancel_request= FALSE; 1733 s->cancel_request= FALSE;
1740 1734
1741#if !( (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN) ) 1735#if THREADWAIT_METHOD == THREADWAIT_CONDVAR
1742 MUTEX_INIT( &s->done_lock_ ); 1736 MUTEX_INIT( &s->done_lock_);
1743 SIGNAL_INIT( &s->done_signal_ ); 1737 SIGNAL_INIT( &s->done_signal_);
1744#endif 1738#endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR
1745 s->mstatus= NORMAL; 1739 s->mstatus= NORMAL;
1746 s->selfdestruct_next= NULL; 1740 s->selfdestruct_next= NULL;
1747 1741
@@ -1813,6 +1807,7 @@ LUAG_FUNC( thread_gc )
1813 { 1807 {
1814 // Make sure a kill has proceeded, before cleaning up the data structure. 1808 // Make sure a kill has proceeded, before cleaning up the data structure.
1815 // 1809 //
1810 // NO lua_close() in this case because we don't know where execution of the state was interrupted
1816 // If not doing 'THREAD_WAIT()' we should close the Lua state here 1811 // If not doing 'THREAD_WAIT()' we should close the Lua state here
1817 // (can it be out of order, since we killed the lane abruptly?) 1812 // (can it be out of order, since we killed the lane abruptly?)
1818 // 1813 //
@@ -1821,11 +1816,7 @@ LUAG_FUNC( thread_gc )
1821 s->L = 0; 1816 s->L = 0;
1822#else // 0 1817#else // 0
1823 DEBUGEXEC(fprintf( stderr, "** Joining with a killed thread (needs testing) **" )); 1818 DEBUGEXEC(fprintf( stderr, "** Joining with a killed thread (needs testing) **" ));
1824#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN) 1819 THREAD_WAIT( &s->thread, -1, &s->done_signal_, &s->done_lock_, &s->status);
1825 THREAD_WAIT( &s->thread, -1 );
1826#else
1827 THREAD_WAIT( &s->thread, &s->done_signal_, &s->done_lock_, &s->status, -1 );
1828#endif
1829 DEBUGEXEC(fprintf( stderr, "** Joined ok **" )); 1820 DEBUGEXEC(fprintf( stderr, "** Joined ok **" ));
1830#endif // 0 1821#endif // 0
1831 } 1822 }
@@ -1837,12 +1828,12 @@ LUAG_FUNC( thread_gc )
1837 1828
1838 // Clean up after a (finished) thread 1829 // Clean up after a (finished) thread
1839 // 1830 //
1840#if (! ((defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN))) 1831#if THREADWAIT_METHOD == THREADWAIT_CONDVAR
1841 SIGNAL_FREE( &s->done_signal_ ); 1832 SIGNAL_FREE( &s->done_signal_);
1842 MUTEX_FREE( &s->done_lock_ ); 1833 MUTEX_FREE( &s->done_lock_);
1843#endif 1834#endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR
1844 1835
1845 free(s); 1836 free( s);
1846 1837
1847 return 0; 1838 return 0;
1848} 1839}
@@ -1871,6 +1862,7 @@ static bool_t thread_cancel( struct s_lane *s, double secs, bool_t force)
1871 // 1862 //
1872 if( s->status < DONE) 1863 if( s->status < DONE)
1873 { 1864 {
1865 s->cancel_request = TRUE; // it's now signaled to stop
1874 // signal the linda the wake up the thread so that it can react to the cancel query 1866 // signal the linda the wake up the thread so that it can react to the cancel query
1875 // let us hope we never land here with a pointer on a linda that has been destroyed... 1867 // let us hope we never land here with a pointer on a linda that has been destroyed...
1876 //MUTEX_LOCK( &selfdestruct_cs ); 1868 //MUTEX_LOCK( &selfdestruct_cs );
@@ -1882,13 +1874,7 @@ static bool_t thread_cancel( struct s_lane *s, double secs, bool_t force)
1882 } 1874 }
1883 } 1875 }
1884 //MUTEX_UNLOCK( &selfdestruct_cs ); 1876 //MUTEX_UNLOCK( &selfdestruct_cs );
1885 s->cancel_request = TRUE; // it's now signalled to stop 1877 done = THREAD_WAIT( &s->thread, secs, &s->done_signal_, &s->done_lock_, &s->status);
1886 done=
1887#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN)
1888 THREAD_WAIT( &s->thread, secs);
1889#else
1890 THREAD_WAIT( &s->thread, &s->done_signal_, &s->done_lock_, &s->status, secs);
1891#endif
1892 1878
1893 if ((!done) && force) 1879 if ((!done) && force)
1894 { 1880 {
@@ -1986,12 +1972,7 @@ LUAG_FUNC( thread_join )
1986 int ret; 1972 int ret;
1987 bool_t done; 1973 bool_t done;
1988 1974
1989 done = (s->thread == 0) || 1975 done = THREAD_ISNULL( s->thread) || THREAD_WAIT( &s->thread, wait_secs, &s->done_signal_, &s->done_lock_, &s->status);
1990#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN)
1991 THREAD_WAIT( &s->thread, wait_secs );
1992#else
1993 THREAD_WAIT( &s->thread, &s->done_signal_, &s->done_lock_, &s->status, wait_secs);
1994#endif
1995 if (!done || !L2) 1976 if (!done || !L2)
1996 return 0; // timeout: pushes none, leaves 'L2' alive 1977 return 0; // timeout: pushes none, leaves 'L2' alive
1997 1978
@@ -2365,7 +2346,7 @@ LUAG_FUNC( configure )
2365 * there is no problem. But if the host is multithreaded, we need to lock around the 2346 * there is no problem. But if the host is multithreaded, we need to lock around the
2366 * initializations. 2347 * initializations.
2367 */ 2348 */
2368#ifdef PLATFORM_WIN32 2349#if THREADAPI == THREADAPI_WINDOWS
2369 { 2350 {
2370 static volatile int /*bool*/ go_ahead; // = 0 2351 static volatile int /*bool*/ go_ahead; // = 0
2371 if( InterlockedCompareExchange( &s_initCount, 1, 0) == 0) 2352 if( InterlockedCompareExchange( &s_initCount, 1, 0) == 0)
@@ -2378,7 +2359,7 @@ LUAG_FUNC( configure )
2378 while( !go_ahead ) { Sleep(1); } // changes threads 2359 while( !go_ahead ) { Sleep(1); } // changes threads
2379 } 2360 }
2380 } 2361 }
2381#else 2362#else // THREADAPI == THREADAPI_PTHREAD
2382 if( s_initCount == 0) 2363 if( s_initCount == 0)
2383 { 2364 {
2384 static pthread_mutex_t my_lock= PTHREAD_MUTEX_INITIALIZER; 2365 static pthread_mutex_t my_lock= PTHREAD_MUTEX_INITIALIZER;
@@ -2394,7 +2375,7 @@ LUAG_FUNC( configure )
2394 } 2375 }
2395 pthread_mutex_unlock(&my_lock); 2376 pthread_mutex_unlock(&my_lock);
2396 } 2377 }
2397#endif 2378#endif // THREADAPI == THREADAPI_PTHREAD
2398 assert( timer_deep != 0 ); 2379 assert( timer_deep != 0 );
2399 2380
2400 // Create main module interface table 2381 // Create main module interface table
@@ -2453,7 +2434,7 @@ LUAG_FUNC( configure )
2453int 2434int
2454#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) 2435#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)
2455__declspec(dllexport) 2436__declspec(dllexport)
2456#endif 2437#endif // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)
2457luaopen_lanes( lua_State *L ) 2438luaopen_lanes( lua_State *L )
2458{ 2439{
2459 // Create main module interface table 2440 // Create main module interface table