aboutsummaryrefslogtreecommitdiff
path: root/src/lanes.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lanes.c')
-rw-r--r--src/lanes.c74
1 files changed, 41 insertions, 33 deletions
diff --git a/src/lanes.c b/src/lanes.c
index 0a04d88..5a1f94a 100644
--- a/src/lanes.c
+++ b/src/lanes.c
@@ -93,6 +93,7 @@ THE SOFTWARE.
93#include "tools.h" 93#include "tools.h"
94#include "universe.h" 94#include "universe.h"
95#include "keeper.h" 95#include "keeper.h"
96#include "uniquekey.h"
96 97
97#if !(defined( PLATFORM_XBOX) || defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC)) 98#if !(defined( PLATFORM_XBOX) || defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC))
98# include <sys/time.h> 99# include <sys/time.h>
@@ -193,13 +194,15 @@ typedef struct s_Lane Lane;
193// 194//
194#define lua_toLane( L, i) (*((Lane**) luaL_checkudata( L, i, "Lane"))) 195#define lua_toLane( L, i) (*((Lane**) luaL_checkudata( L, i, "Lane")))
195 196
196#define CANCEL_TEST_KEY ((void*)get_lane_from_registry) // used as registry key 197// crc64/we of string "CANCEL_TEST_KEY" generated at http://www.nitrxgen.net/hashgen/
198static DECLARE_CONST_UNIQUE_KEY( CANCEL_TEST_KEY, 0xe66f5960c57d133a); // used as registry key
199
197static inline Lane* get_lane_from_registry( lua_State* L) 200static inline Lane* get_lane_from_registry( lua_State* L)
198{ 201{
199 Lane* s; 202 Lane* s;
200 STACK_GROW( L, 1); 203 STACK_GROW( L, 1);
201 STACK_CHECK( L); 204 STACK_CHECK( L);
202 lua_pushlightuserdata( L, CANCEL_TEST_KEY); 205 push_unique_key( L, CANCEL_TEST_KEY);
203 lua_rawget( L, LUA_REGISTRYINDEX); 206 lua_rawget( L, LUA_REGISTRYINDEX);
204 s = lua_touserdata( L, -1); // lightuserdata (true 's_lane' pointer) / nil 207 s = lua_touserdata( L, -1); // lightuserdata (true 's_lane' pointer) / nil
205 lua_pop( L, 1); 208 lua_pop( L, 1);
@@ -238,11 +241,13 @@ static inline enum e_cancel_request cancel_test( lua_State* L)
238 return s ? s->cancel_request : CANCEL_NONE; 241 return s ? s->cancel_request : CANCEL_NONE;
239} 242}
240 243
241#define CANCEL_ERROR ((void*)cancel_error) // 'cancel_error' sentinel 244// crc64/we of string "CANCEL_ERROR" generated at http://www.nitrxgen.net/hashgen/
245static DECLARE_CONST_UNIQUE_KEY( CANCEL_ERROR, 0xe97d41626cc97577); // 'cancel_error' sentinel
246
242static int cancel_error( lua_State* L) 247static int cancel_error( lua_State* L)
243{ 248{
244 STACK_GROW( L, 1); 249 STACK_GROW( L, 1);
245 lua_pushlightuserdata( L, CANCEL_ERROR); // special error value 250 push_unique_key( L, CANCEL_ERROR); // special error value
246 return lua_error( L); // doesn't return 251 return lua_error( L); // doesn't return
247} 252}
248 253
@@ -258,7 +263,8 @@ static void cancel_hook( lua_State* L, lua_Debug* ar)
258 263
259#if ERROR_FULL_STACK 264#if ERROR_FULL_STACK
260static int lane_error( lua_State* L); 265static int lane_error( lua_State* L);
261#define STACK_TRACE_KEY ((void*)lane_error) // used as registry key 266// crc64/we of string "STACK_TRACE_KEY" generated at http://www.nitrxgen.net/hashgen/
267static DECLARE_CONST_UNIQUE_KEY( STACK_TRACE_KEY, 0x024d5411677ce879);
262#endif // ERROR_FULL_STACK 268#endif // ERROR_FULL_STACK
263 269
264/* 270/*
@@ -463,7 +469,7 @@ LUAG_FUNC( linda_send)
463 int pushed; 469 int pushed;
464 time_d timeout = -1.0; 470 time_d timeout = -1.0;
465 uint_t key_i = 2; // index of first key, if timeout not there 471 uint_t key_i = 2; // index of first key, if timeout not there
466 void* as_nil_sentinel; // if not NULL, send() will silently send a single nil if nothing is provided 472 bool_t as_nil_sentinel; // if not NULL, send() will silently send a single nil if nothing is provided
467 473
468 if( lua_type( L, 2) == LUA_TNUMBER) // we don't want to use lua_isnumber() because of autocoercion 474 if( lua_type( L, 2) == LUA_TNUMBER) // we don't want to use lua_isnumber() because of autocoercion
469 { 475 {
@@ -475,8 +481,8 @@ LUAG_FUNC( linda_send)
475 ++ key_i; 481 ++ key_i;
476 } 482 }
477 483
478 as_nil_sentinel = lua_touserdata( L, key_i); 484 as_nil_sentinel = equal_unique_key( L, key_i, NIL_SENTINEL);
479 if( as_nil_sentinel == NIL_SENTINEL) 485 if( as_nil_sentinel)
480 { 486 {
481 // the real key to send data to is after the NIL_SENTINEL marker 487 // the real key to send data to is after the NIL_SENTINEL marker
482 ++ key_i; 488 ++ key_i;
@@ -490,10 +496,10 @@ LUAG_FUNC( linda_send)
490 // make sure there is something to send 496 // make sure there is something to send
491 if( (uint_t)lua_gettop( L) == key_i) 497 if( (uint_t)lua_gettop( L) == key_i)
492 { 498 {
493 if( as_nil_sentinel == NIL_SENTINEL) 499 if( as_nil_sentinel)
494 { 500 {
495 // send a single nil if nothing is provided 501 // send a single nil if nothing is provided
496 lua_pushlightuserdata( L, NIL_SENTINEL); 502 push_unique_key( L, NIL_SENTINEL);
497 } 503 }
498 else 504 else
499 { 505 {
@@ -584,7 +590,7 @@ LUAG_FUNC( linda_send)
584 { 590 {
585 case CANCEL_SOFT: 591 case CANCEL_SOFT:
586 // if user wants to soft-cancel, the call returns lanes.cancel_error 592 // if user wants to soft-cancel, the call returns lanes.cancel_error
587 lua_pushlightuserdata( L, CANCEL_ERROR); 593 push_unique_key( L, CANCEL_ERROR);
588 return 1; 594 return 1;
589 595
590 case CANCEL_HARD: 596 case CANCEL_HARD:
@@ -741,7 +747,7 @@ LUAG_FUNC( linda_receive)
741 { 747 {
742 case CANCEL_SOFT: 748 case CANCEL_SOFT:
743 // if user wants to soft-cancel, the call returns CANCEL_ERROR 749 // if user wants to soft-cancel, the call returns CANCEL_ERROR
744 lua_pushlightuserdata( L, CANCEL_ERROR); 750 push_unique_key( L, CANCEL_ERROR);
745 return 1; 751 return 1;
746 752
747 case CANCEL_HARD: 753 case CANCEL_HARD:
@@ -803,7 +809,7 @@ LUAG_FUNC( linda_set)
803 else // linda is cancelled 809 else // linda is cancelled
804 { 810 {
805 // do nothing and return lanes.cancel_error 811 // do nothing and return lanes.cancel_error
806 lua_pushlightuserdata( L, CANCEL_ERROR); 812 push_unique_key( L, CANCEL_ERROR);
807 pushed = 1; 813 pushed = 1;
808 } 814 }
809 keeper_release( K); 815 keeper_release( K);
@@ -871,7 +877,7 @@ LUAG_FUNC( linda_get)
871 else // linda is cancelled 877 else // linda is cancelled
872 { 878 {
873 // do nothing and return lanes.cancel_error 879 // do nothing and return lanes.cancel_error
874 lua_pushlightuserdata( L, CANCEL_ERROR); 880 push_unique_key( L, CANCEL_ERROR);
875 pushed = 1; 881 pushed = 1;
876 } 882 }
877 keeper_release( K); 883 keeper_release( K);
@@ -922,7 +928,7 @@ LUAG_FUNC( linda_limit)
922 else // linda is cancelled 928 else // linda is cancelled
923 { 929 {
924 // do nothing and return lanes.cancel_error 930 // do nothing and return lanes.cancel_error
925 lua_pushlightuserdata( L, CANCEL_ERROR); 931 push_unique_key( L, CANCEL_ERROR);
926 pushed = 1; 932 pushed = 1;
927 } 933 }
928 keeper_release( K); 934 keeper_release( K);
@@ -1249,7 +1255,7 @@ static void* linda_id( lua_State* L, enum eDeepOp op_)
1249 lua_pushliteral( L, BATCH_SENTINEL); 1255 lua_pushliteral( L, BATCH_SENTINEL);
1250 lua_setfield(L, -2, "batched"); 1256 lua_setfield(L, -2, "batched");
1251 1257
1252 lua_pushlightuserdata( L, NIL_SENTINEL); 1258 push_unique_key( L, NIL_SENTINEL);
1253 lua_setfield(L, -2, "null"); 1259 lua_setfield(L, -2, "null");
1254 1260
1255 luaG_pushdeepversion( L); 1261 luaG_pushdeepversion( L);
@@ -1815,7 +1821,8 @@ LUAG_FUNC( set_singlethreaded)
1815*/ 1821*/
1816#if ERROR_FULL_STACK 1822#if ERROR_FULL_STACK
1817 1823
1818# define EXTENDED_STACK_TRACE_KEY ((void*)LG_set_error_reporting) // used as registry key 1824// crc64/we of string "EXTENDED_STACK_TRACE_REGKEY" generated at http://www.nitrxgen.net/hashgen/
1825static DECLARE_CONST_UNIQUE_KEY( EXTENDED_STACK_TRACE_REGKEY, 0x7a59821071066e49); // used as registry key
1819 1826
1820LUAG_FUNC( set_error_reporting) 1827LUAG_FUNC( set_error_reporting)
1821{ 1828{
@@ -1836,7 +1843,7 @@ LUAG_FUNC( set_error_reporting)
1836 return luaL_error( L, "unsupported error reporting model"); 1843 return luaL_error( L, "unsupported error reporting model");
1837 } 1844 }
1838done: 1845done:
1839 lua_pushlightuserdata( L, EXTENDED_STACK_TRACE_KEY); 1846 push_unique_key( L, EXTENDED_STACK_TRACE_REGKEY);
1840 lua_pushboolean( L, equal); 1847 lua_pushboolean( L, equal);
1841 lua_rawset( L, LUA_REGISTRYINDEX); 1848 lua_rawset( L, LUA_REGISTRYINDEX);
1842 return 0; 1849 return 0;
@@ -1853,13 +1860,13 @@ static int lane_error( lua_State* L)
1853 1860
1854 // Don't do stack survey for cancelled lanes. 1861 // Don't do stack survey for cancelled lanes.
1855 // 1862 //
1856 if( lua_touserdata( L, 1) == CANCEL_ERROR) 1863 if( equal_unique_key( L, 1, CANCEL_ERROR))
1857 { 1864 {
1858 return 1; // just pass on 1865 return 1; // just pass on
1859 } 1866 }
1860 1867
1861 STACK_GROW( L, 3); 1868 STACK_GROW( L, 3);
1862 lua_pushlightuserdata( L, EXTENDED_STACK_TRACE_KEY); // some_error estk 1869 push_unique_key( L, EXTENDED_STACK_TRACE_REGKEY); // some_error estk
1863 lua_rawget( L, LUA_REGISTRYINDEX); // some_error basic|extended 1870 lua_rawget( L, LUA_REGISTRYINDEX); // some_error basic|extended
1864 extended = lua_toboolean( L, -1); 1871 extended = lua_toboolean( L, -1);
1865 lua_pop( L, 1); // some_error 1872 lua_pop( L, 1); // some_error
@@ -1913,7 +1920,7 @@ static int lane_error( lua_State* L)
1913 lua_rawseti( L, -2, (lua_Integer) n); // some_error {} 1920 lua_rawseti( L, -2, (lua_Integer) n); // some_error {}
1914 } 1921 }
1915 1922
1916 lua_pushlightuserdata( L, STACK_TRACE_KEY); // some_error {} stk 1923 push_unique_key( L, STACK_TRACE_KEY); // some_error {} stk
1917 lua_insert( L, -2); // some_error stk {} 1924 lua_insert( L, -2); // some_error stk {}
1918 lua_rawset( L, LUA_REGISTRYINDEX); // some_error 1925 lua_rawset( L, LUA_REGISTRYINDEX); // some_error
1919 1926
@@ -1936,14 +1943,14 @@ static void push_stack_trace( lua_State* L, int rc_, int stk_base_)
1936 { 1943 {
1937 // fetch the call stack table from the registry where the handler stored it 1944 // fetch the call stack table from the registry where the handler stored it
1938 STACK_GROW( L, 1); 1945 STACK_GROW( L, 1);
1939 lua_pushlightuserdata( L, STACK_TRACE_KEY); // err STACK_TRACE_KEY 1946 push_unique_key( L, STACK_TRACE_KEY); // err STACK_TRACE_KEY
1940 // yields nil if no stack was generated (in case of cancellation for example) 1947 // yields nil if no stack was generated (in case of cancellation for example)
1941 lua_rawget( L, LUA_REGISTRYINDEX); // err trace|nil 1948 lua_rawget( L, LUA_REGISTRYINDEX); // err trace|nil
1942 ASSERT_L( lua_gettop( L) == 1 + stk_base_); 1949 ASSERT_L( lua_gettop( L) == 1 + stk_base_);
1943 1950
1944 // For cancellation the error message is CANCEL_ERROR, and a stack trace isn't placed 1951 // For cancellation the error message is CANCEL_ERROR, and a stack trace isn't placed
1945 // For other errors, the message can be whatever was thrown, and we should have a stack trace table 1952 // For other errors, the message can be whatever was thrown, and we should have a stack trace table
1946 ASSERT_L( lua_type( L, 1 + stk_base_) == ((lua_touserdata( L, stk_base_) == CANCEL_ERROR) ? LUA_TNIL : LUA_TTABLE)); 1953 ASSERT_L( lua_type( L, 1 + stk_base_) == (equal_unique_key( L, stk_base_, CANCEL_ERROR) ? LUA_TNIL : LUA_TTABLE));
1947 // Just leaving the stack trace table on the stack is enough to get it through to the master. 1954 // Just leaving the stack trace table on the stack is enough to get it through to the master.
1948 break; 1955 break;
1949 } 1956 }
@@ -1953,18 +1960,19 @@ static void push_stack_trace( lua_State* L, int rc_, int stk_base_)
1953 case LUA_ERRERR: // error while running the error handler (if any, for example an out-of-memory condition) 1960 case LUA_ERRERR: // error while running the error handler (if any, for example an out-of-memory condition)
1954 default: 1961 default:
1955 // we should have a single value which is either a string (the error message) or CANCEL_ERROR 1962 // we should have a single value which is either a string (the error message) or CANCEL_ERROR
1956 ASSERT_L( (lua_gettop( L) == stk_base_) && ((lua_type( L, stk_base_) == LUA_TSTRING) || (lua_touserdata( L, stk_base_) == CANCEL_ERROR))); 1963 ASSERT_L( (lua_gettop( L) == stk_base_) && ((lua_type( L, stk_base_) == LUA_TSTRING) || equal_unique_key( L, stk_base_, CANCEL_ERROR)));
1957 break; 1964 break;
1958 } 1965 }
1959} 1966}
1960 1967
1961LUAG_FUNC( set_debug_threadname) 1968LUAG_FUNC( set_debug_threadname)
1962{ 1969{
1970 DECLARE_CONST_UNIQUE_KEY( hidden_regkey, LG_set_debug_threadname);
1963 // C s_lane structure is a light userdata upvalue 1971 // C s_lane structure is a light userdata upvalue
1964 Lane* s = lua_touserdata( L, lua_upvalueindex( 1)); 1972 Lane* s = lua_touserdata( L, lua_upvalueindex( 1));
1965 luaL_checktype( L, -1, LUA_TSTRING); // "name" 1973 luaL_checktype( L, -1, LUA_TSTRING); // "name"
1966 // 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... 1974 // 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...
1967 lua_pushlightuserdata( L, LG_set_debug_threadname); // "name" lud 1975 push_unique_key( L, hidden_regkey); // "name" lud
1968 lua_pushvalue( L, -2); // "name" lud "name" 1976 lua_pushvalue( L, -2); // "name" lud "name"
1969 lua_rawset( L, LUA_REGISTRYINDEX); // "name" 1977 lua_rawset( L, LUA_REGISTRYINDEX); // "name"
1970 s->debug_name = lua_tostring( L, -1); 1978 s->debug_name = lua_tostring( L, -1);
@@ -2089,7 +2097,7 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void* vs)
2089 // in case of error and if it exists, fetch stack trace from registry and push it 2097 // in case of error and if it exists, fetch stack trace from registry and push it
2090 push_stack_trace( L, rc, 1); // retvals|error [trace] 2098 push_stack_trace( L, rc, 1); // retvals|error [trace]
2091 2099
2092 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "Lane %p body: %s (%s)\n" INDENT_END, L, get_errcode_name( rc), (lua_touserdata( L, 1)==CANCEL_ERROR) ? "cancelled" : lua_typename( L, lua_type( L, 1)))); 2100 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "Lane %p body: %s (%s)\n" INDENT_END, L, get_errcode_name( rc), equal_unique_key( L, 1, CANCEL_ERROR) ? "cancelled" : lua_typename( L, lua_type( L, 1))));
2093 //STACK_DUMP(L); 2101 //STACK_DUMP(L);
2094 // Call finalizers, if the script has set them up. 2102 // Call finalizers, if the script has set them up.
2095 // 2103 //
@@ -2118,7 +2126,7 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void* vs)
2118 { 2126 {
2119 // leave results (1..top) or error message + stack trace (1..2) on the stack - master will copy them 2127 // leave results (1..top) or error message + stack trace (1..2) on the stack - master will copy them
2120 2128
2121 enum e_status st = (rc == 0) ? DONE : (lua_touserdata( L, 1) == CANCEL_ERROR) ? CANCELLED : ERROR_ST; 2129 enum e_status st = (rc == 0) ? DONE : equal_unique_key( L, 1, CANCEL_ERROR) ? CANCELLED : ERROR_ST;
2122 2130
2123 // Posix no PTHREAD_TIMEDJOIN: 2131 // Posix no PTHREAD_TIMEDJOIN:
2124 // 'done_lock' protects the -> DONE|ERROR_ST|CANCELLED state change 2132 // 'done_lock' protects the -> DONE|ERROR_ST|CANCELLED state change
@@ -2183,9 +2191,9 @@ LUAG_FUNC( register)
2183 return 0; 2191 return 0;
2184} 2192}
2185 2193
2194// crc64/we of string "GCCB_KEY" generated at http://www.nitrxgen.net/hashgen/
2195static DECLARE_CONST_UNIQUE_KEY( GCCB_KEY, 0xcfb1f046ef074e88);
2186 2196
2187LUAG_FUNC( thread_gc);
2188#define GCCB_KEY (void*)LG_thread_gc
2189//--- 2197//---
2190// lane_ud = lane_new( function 2198// lane_ud = lane_new( function
2191// , [libs_str] 2199// , [libs_str]
@@ -2429,7 +2437,7 @@ LUAG_FUNC( lane_new)
2429 // Store the gc_cb callback in the uservalue 2437 // Store the gc_cb callback in the uservalue
2430 if( gc_cb_idx > 0) 2438 if( gc_cb_idx > 0)
2431 { 2439 {
2432 lua_pushlightuserdata( L, GCCB_KEY); // func libs cancelstep priority globals package required gc_cb lane uv k 2440 push_unique_key( L, GCCB_KEY); // func libs cancelstep priority globals package required gc_cb lane uv k
2433 lua_pushvalue( L, gc_cb_idx); // func libs cancelstep priority globals package required gc_cb lane uv k gc_cb 2441 lua_pushvalue( L, gc_cb_idx); // func libs cancelstep priority globals package required gc_cb lane uv k gc_cb
2434 lua_rawset( L, -3); // func libs cancelstep priority globals package required gc_cb lane uv 2442 lua_rawset( L, -3); // func libs cancelstep priority globals package required gc_cb lane uv
2435 } 2443 }
@@ -2437,7 +2445,7 @@ LUAG_FUNC( lane_new)
2437 lua_setuservalue( L, -2); // func libs cancelstep priority globals package required gc_cb lane 2445 lua_setuservalue( L, -2); // func libs cancelstep priority globals package required gc_cb lane
2438 2446
2439 // Store 's' in the lane's registry, for 'cancel_test()' (even if 'cs'==0 we still do cancel tests at pending send/receive). 2447 // Store 's' in the lane's registry, for 'cancel_test()' (even if 'cs'==0 we still do cancel tests at pending send/receive).
2440 lua_pushlightuserdata( L2, CANCEL_TEST_KEY); // func [... args ...] k 2448 push_unique_key( L2, CANCEL_TEST_KEY); // func [... args ...] k
2441 lua_pushlightuserdata( L2, s); // func [... args ...] k s 2449 lua_pushlightuserdata( L2, s); // func [... args ...] k s
2442 lua_rawset( L2, LUA_REGISTRYINDEX); // func [... args ...] 2450 lua_rawset( L2, LUA_REGISTRYINDEX); // func [... args ...]
2443 2451
@@ -2476,7 +2484,7 @@ LUAG_FUNC( thread_gc)
2476 2484
2477 // if there a gc callback? 2485 // if there a gc callback?
2478 lua_getuservalue( L, 1); // ud uservalue 2486 lua_getuservalue( L, 1); // ud uservalue
2479 lua_pushlightuserdata( L, GCCB_KEY); // ud uservalue __gc 2487 push_unique_key( L, GCCB_KEY); // ud uservalue __gc
2480 lua_rawget( L, -2); // ud uservalue gc_cb|nil 2488 lua_rawget( L, -2); // ud uservalue gc_cb|nil
2481 if( !lua_isnil( L, -1)) 2489 if( !lua_isnil( L, -1))
2482 { 2490 {
@@ -3209,7 +3217,7 @@ LUAG_FUNC( configure)
3209 lua_pushinteger(L, THREAD_PRIO_MAX); // settings M THREAD_PRIO_MAX 3217 lua_pushinteger(L, THREAD_PRIO_MAX); // settings M THREAD_PRIO_MAX
3210 lua_setfield( L, -2, "max_prio"); // settings M 3218 lua_setfield( L, -2, "max_prio"); // settings M
3211 3219
3212 lua_pushlightuserdata( L, CANCEL_ERROR); // settings M CANCEL_ERROR 3220 push_unique_key( L, CANCEL_ERROR); // settings M CANCEL_ERROR
3213 lua_setfield( L, -2, "cancel_error"); // settings M 3221 lua_setfield( L, -2, "cancel_error"); // settings M
3214 3222
3215 // we'll need this every time we transfer some C function from/to this state 3223 // we'll need this every time we transfer some C function from/to this state