aboutsummaryrefslogtreecommitdiff
path: root/src/lanes.c
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-11-29 20:33:46 +0100
committerBenoit Germain <b n t DOT g e r m a i n AT g m a i l DOT c o m>2013-11-29 20:33:46 +0100
commitff74281fc94cda26b2d0a7fc2424f24fe2488718 (patch)
tree6e8aa44d300ccd5da451d02c08cee98090328b60 /src/lanes.c
parentb4cd90c9e9a7898775d173df2267d1860dcbc699 (diff)
downloadlanes-ff74281fc94cda26b2d0a7fc2424f24fe2488718.tar.gz
lanes-ff74281fc94cda26b2d0a7fc2424f24fe2488718.tar.bz2
lanes-ff74281fc94cda26b2d0a7fc2424f24fe2488718.zip
supposedly improved pthread support
* bumped version to 3.7.3 * set pthread thread cancel type to PTHREAD_CANCEL_ASYNCHRONOUS * lane_h:cancel() accepts a 3rd timeout argument used when waiting for actual thread termination (hitting the timeout raises an error) * added PROPAGATE_ALLOCF macro to select state creation mode (lua_newstate or luaL_newstate)
Diffstat (limited to 'src/lanes.c')
-rw-r--r--src/lanes.c68
1 files changed, 47 insertions, 21 deletions
diff --git a/src/lanes.c b/src/lanes.c
index 53ed5e4..9e32f9a 100644
--- a/src/lanes.c
+++ b/src/lanes.c
@@ -52,7 +52,7 @@
52 * ... 52 * ...
53 */ 53 */
54 54
55char const* VERSION = "3.7.2"; 55char const* VERSION = "3.7.3";
56 56
57/* 57/*
58=============================================================================== 58===============================================================================
@@ -1197,7 +1197,7 @@ typedef enum
1197 CR_Killed 1197 CR_Killed
1198} cancel_result; 1198} cancel_result;
1199 1199
1200static cancel_result thread_cancel( struct s_lane *s, double secs, bool_t force) 1200static cancel_result thread_cancel( lua_State* L, struct s_lane* s, double secs, bool_t force, double waitkill_timeout_)
1201{ 1201{
1202 cancel_result result; 1202 cancel_result result;
1203 1203
@@ -1239,6 +1239,15 @@ static cancel_result thread_cancel( struct s_lane *s, double secs, bool_t force)
1239 // PThread seems to have). 1239 // PThread seems to have).
1240 // 1240 //
1241 THREAD_KILL( &s->thread); 1241 THREAD_KILL( &s->thread);
1242#if THREADAPI == THREADAPI_PTHREAD
1243 // pthread: make sure the thread is really stopped!
1244 // note that this may block forever if the lane doesn't call a cancellation point and pthread doesn't honor PTHREAD_CANCEL_ASYNCHRONOUS
1245 result = THREAD_WAIT( &s->thread, waitkill_timeout_, &s->done_signal, &s->done_lock, &s->status);
1246 if( result == CR_Timeout)
1247 {
1248 return luaL_error( L, "force-killed lane failed to terminate within %f second%s", waitkill_timeout_, waitkill_timeout_ > 1 ? "s" : "");
1249 }
1250#endif // THREADAPI == THREADAPI_PTHREAD
1242 s->mstatus = KILLED; // mark 'gc' to wait for it 1251 s->mstatus = KILLED; // mark 'gc' to wait for it
1243 // note that s->status value must remain to whatever it was at the time of the kill 1252 // note that s->status value must remain to whatever it was at the time of the kill
1244 // because we need to know if we can lua_close() the Lua State or not. 1253 // because we need to know if we can lua_close() the Lua State or not.
@@ -1357,7 +1366,7 @@ static int selfdestruct_gc( lua_State* L)
1357 while( s != SELFDESTRUCT_END) 1366 while( s != SELFDESTRUCT_END)
1358 { 1367 {
1359 // attempt a regular unforced hard cancel with a small timeout 1368 // attempt a regular unforced hard cancel with a small timeout
1360 bool_t cancelled = THREAD_ISNULL( s->thread) || thread_cancel( s, 0.0001, FALSE); 1369 bool_t cancelled = THREAD_ISNULL( s->thread) || thread_cancel( L, s, 0.0001, FALSE, 0.0);
1361 // if we failed, and we know the thread is waiting on a linda 1370 // if we failed, and we know the thread is waiting on a linda
1362 if( cancelled == FALSE && s->status == WAITING && s->waiting_on != NULL) 1371 if( cancelled == FALSE && s->status == WAITING && s->waiting_on != NULL)
1363 { 1372 {
@@ -1758,6 +1767,17 @@ static char const* get_errcode_name( int _code)
1758} 1767}
1759#endif // USE_DEBUG_SPEW 1768#endif // USE_DEBUG_SPEW
1760 1769
1770#if THREADWAIT_METHOD == THREADWAIT_CONDVAR // implies THREADAPI == THREADAPI_PTHREAD
1771static void thread_cleanup_handler( void* opaque)
1772{
1773 struct s_lane* s= (struct s_lane*) opaque;
1774 MUTEX_LOCK( &s->done_lock);
1775 s->status = CANCELLED;
1776 SIGNAL_ONE( &s->done_signal); // wake up master (while 's->done_lock' is on)
1777 MUTEX_UNLOCK( &s->done_lock);
1778}
1779#endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR
1780
1761//--- 1781//---
1762static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs) 1782static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs)
1763{ 1783{
@@ -1770,7 +1790,8 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs)
1770 tracking_add( s); 1790 tracking_add( s);
1771 } 1791 }
1772#endif // HAVE_LANE_TRACKING 1792#endif // HAVE_LANE_TRACKING
1773 1793 THREAD_MAKE_ASYNCH_CANCELLABLE();
1794 THREAD_CLEANUP_PUSH( thread_cleanup_handler, s);
1774 s->status= RUNNING; // PENDING -> RUNNING 1795 s->status= RUNNING; // PENDING -> RUNNING
1775 1796
1776 // Tie "set_finalizer()" to the state 1797 // Tie "set_finalizer()" to the state
@@ -1888,7 +1909,7 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs)
1888 : ERROR_ST; 1909 : ERROR_ST;
1889 1910
1890 // Posix no PTHREAD_TIMEDJOIN: 1911 // Posix no PTHREAD_TIMEDJOIN:
1891 // 'done_lock' protects the -> DONE|ERROR_ST|CANCELLED state change 1912 // 'done_lock' protects the -> DONE|ERROR_ST|CANCELLED state change
1892 // 1913 //
1893#if THREADWAIT_METHOD == THREADWAIT_CONDVAR 1914#if THREADWAIT_METHOD == THREADWAIT_CONDVAR
1894 MUTEX_LOCK( &s->done_lock); 1915 MUTEX_LOCK( &s->done_lock);
@@ -1901,6 +1922,7 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs)
1901 MUTEX_UNLOCK( &s->done_lock); 1922 MUTEX_UNLOCK( &s->done_lock);
1902#endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR 1923#endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR
1903 } 1924 }
1925 THREAD_CLEANUP_POP( FALSE);
1904 return 0; // ignored 1926 return 0; // ignored
1905} 1927}
1906 1928
@@ -2248,6 +2270,7 @@ LUAG_FUNC( thread_gc)
2248 return 0; 2270 return 0;
2249} 2271}
2250 2272
2273// lane_h:cancel( [timeout,] force[, forcekill_timeout])
2251LUAG_FUNC( thread_cancel) 2274LUAG_FUNC( thread_cancel)
2252{ 2275{
2253 if( lua_gettop( L) < 1 || lua_type( L, 1) != LUA_TUSERDATA) 2276 if( lua_gettop( L) < 1 || lua_type( L, 1) != LUA_TUSERDATA)
@@ -2258,9 +2281,8 @@ LUAG_FUNC( thread_cancel)
2258 { 2281 {
2259 struct s_lane* s = lua_toLane( L, 1); 2282 struct s_lane* s = lua_toLane( L, 1);
2260 double secs = 0.0; 2283 double secs = 0.0;
2261 uint_t force_i = 2; 2284 int force_i = 2;
2262 cancel_result result; 2285 int forcekill_timeout_i = 3;
2263 bool_t force;
2264 2286
2265 if( lua_isnumber( L, 2)) 2287 if( lua_isnumber( L, 2))
2266 { 2288 {
@@ -2270,30 +2292,34 @@ LUAG_FUNC( thread_cancel)
2270 return luaL_error( L, "can't force a soft cancel"); 2292 return luaL_error( L, "can't force a soft cancel");
2271 } 2293 }
2272 ++ force_i; 2294 ++ force_i;
2295 ++ forcekill_timeout_i;
2273 } 2296 }
2274 else if( lua_isnil( L, 2)) 2297 else if( lua_isnil( L, 2))
2275 { 2298 {
2276 ++ force_i; 2299 ++ force_i;
2300 ++ forcekill_timeout_i;
2277 } 2301 }
2278 2302
2279 force = lua_toboolean( L, force_i); // FALSE if nothing there
2280
2281 result = thread_cancel( s, secs, force);
2282 switch( result)
2283 { 2303 {
2304 bool_t force = lua_toboolean( L, force_i); // FALSE if nothing there
2305 double forcekill_timeout = luaL_optnumber( L, forcekill_timeout_i, 0.0);
2306
2307 switch( thread_cancel( L, s, secs, force, forcekill_timeout))
2308 {
2284 case CR_Timeout: 2309 case CR_Timeout:
2285 lua_pushboolean( L, 0); 2310 lua_pushboolean( L, 0);
2286 lua_pushstring( L, "timeout"); 2311 lua_pushstring( L, "timeout");
2287 return 2; 2312 return 2;
2288 2313
2289 case CR_Cancelled: 2314 case CR_Cancelled:
2290 lua_pushboolean( L, 1); 2315 lua_pushboolean( L, 1);
2291 return 1; 2316 return 1;
2292 2317
2293 case CR_Killed: 2318 case CR_Killed:
2294 lua_pushboolean( L, 0); 2319 lua_pushboolean( L, 0);
2295 lua_pushstring( L, "killed"); 2320 lua_pushstring( L, "killed");
2296 return 2; 2321 return 2;
2322 }
2297 } 2323 }
2298 } 2324 }
2299 // should never happen, only here to prevent the compiler from complaining of "not all control paths returning a value" 2325 // should never happen, only here to prevent the compiler from complaining of "not all control paths returning a value"