@ -50,7 +50,7 @@
# include "common.h"
# include "common.h"
/* merge from https://github.com/toffaletti/state-threads/commit/7f57fc9acc05e657bca1223f1e5b9b1a45ed929b */
/* merge from https://github.com/toffaletti/state-threads/commit/7f57fc9acc05e657bca1223f1e5b9b1a45ed929b */
# if ndef N VALGRIND
# if def MD_ VALGRIND
# include <valgrind/valgrind.h>
# include <valgrind/valgrind.h>
# endif
# endif
@ -89,7 +89,7 @@ int st_poll(struct pollfd *pds, int npds, st_utime_t timeout)
struct pollfd * pd ;
struct pollfd * pd ;
struct pollfd * epd = pds + npds ;
struct pollfd * epd = pds + npds ;
_st_pollq_t pq ;
_st_pollq_t pq ;
_st_thread_t * me = _ST_CURRENT_THREAD ( ) ;
_st_thread_t * me = _st_this_thread ;
int n ;
int n ;
if ( me - > flags & _ST_FL_INTERRUPT ) {
if ( me - > flags & _ST_FL_INTERRUPT ) {
@ -105,17 +105,17 @@ int st_poll(struct pollfd *pds, int npds, st_utime_t timeout)
pq . npds = npds ;
pq . npds = npds ;
pq . thread = me ;
pq . thread = me ;
pq . on_ioq = 1 ;
pq . on_ioq = 1 ;
_ST_ADD_IOQ( p q) ;
st_clist_insert_before( & pq . links , & _st_this_vp . io_ q) ;
if ( timeout ! = ST_UTIME_NO_TIMEOUT )
if ( timeout ! = ST_UTIME_NO_TIMEOUT )
_ ST_ADD_SLEEPQ ( me , timeout ) ;
_ st_add_sleep_q ( me , timeout ) ;
me - > state = _ST_ST_IO_WAIT ;
me - > state = _ST_ST_IO_WAIT ;
_ ST_SWITCH_CONTEXT ( me ) ;
_ st_switch_context ( me ) ;
n = 0 ;
n = 0 ;
if ( pq . on_ioq ) {
if ( pq . on_ioq ) {
/* If we timed out, the pollq might still be on the ioq. Remove it */
/* If we timed out, the pollq might still be on the ioq. Remove it */
_ST_DEL_IOQ( pq ) ;
st_clist_remove( & pq . links ) ;
( * _st_eventsys - > pollset_del ) ( pds , npds ) ;
( * _st_eventsys - > pollset_del ) ( pds , npds ) ;
} else {
} else {
/* Count the number of ready descriptors */
/* Count the number of ready descriptors */
@ -139,14 +139,14 @@ void _st_vp_schedule(void)
{
{
_st_thread_t * thread ;
_st_thread_t * thread ;
if ( _ ST_RUNQ. next ! = & _ST_RUNQ ) {
if ( _ st_this_vp. run_q . next ! = & _st_this_vp . run_q ) {
# if defined(DEBUG) && defined(DEBUG_STATS)
# if defined(DEBUG) && defined(DEBUG_STATS)
+ + _st_stat_thread_run ;
+ + _st_stat_thread_run ;
# endif
# endif
/* Pull thread off of the run queue */
/* Pull thread off of the run queue */
thread = _ST_THREAD_PTR ( _ ST_RUNQ . next ) ;
thread = _ST_THREAD_PTR ( _ st_this_vp. run_q . next ) ;
_ST_DEL_RUNQ( thread ) ;
st_clist_remove( & thread - > links ) ;
} else {
} else {
# if defined(DEBUG) && defined(DEBUG_STATS)
# if defined(DEBUG) && defined(DEBUG_STATS)
+ + _st_stat_thread_idle ;
+ + _st_stat_thread_idle ;
@ -159,7 +159,7 @@ void _st_vp_schedule(void)
/* Resume the thread */
/* Resume the thread */
thread - > state = _ST_ST_RUNNING ;
thread - > state = _ST_ST_RUNNING ;
_ ST_RESTORE_CONTEXT ( thread ) ;
_ st_restore_context ( thread ) ;
}
}
@ -182,16 +182,16 @@ int st_init(void)
return - 1 ;
return - 1 ;
// Initialize the thread-local variables.
// Initialize the thread-local variables.
ST_INIT_CLIST ( & _st_free_stacks ) ;
st_clist_init ( & _st_free_stacks ) ;
// Initialize ST.
// Initialize ST.
memset ( & _st_this_vp , 0 , sizeof ( _st_vp_t ) ) ;
memset ( & _st_this_vp , 0 , sizeof ( _st_vp_t ) ) ;
ST_INIT_CLIST( & _ST_RUNQ ) ;
st_clist_init( & _st_this_vp . run_q ) ;
ST_INIT_CLIST( & _ST_IOQ ) ;
st_clist_init( & _st_this_vp . io_q ) ;
ST_INIT_CLIST( & _ST_ZOMBIEQ ) ;
st_clist_init( & _st_this_vp . zombie_q ) ;
# ifdef DEBUG
# ifdef DEBUG
ST_INIT_CLIST( & _ST_THREADQ ) ;
st_clist_init( & _st_this_vp . thread_q ) ;
# endif
# endif
if ( ( * _st_eventsys - > init ) ( ) < 0 )
if ( ( * _st_eventsys - > init ) ( ) < 0 )
@ -208,7 +208,7 @@ int st_init(void)
return - 1 ;
return - 1 ;
_st_this_vp . idle_thread - > flags = _ST_FL_IDLE_THREAD ;
_st_this_vp . idle_thread - > flags = _ST_FL_IDLE_THREAD ;
_st_active_count - - ;
_st_active_count - - ;
_ST_DEL_RUNQ( _st_this_vp . idle_thread ) ;
st_clist_remove( & _st_this_vp . idle_thread - > links ) ;
/*
/*
* Initialize primordial thread
* Initialize primordial thread
@ -219,10 +219,10 @@ int st_init(void)
thread - > private_data = ( void * * ) ( thread + 1 ) ;
thread - > private_data = ( void * * ) ( thread + 1 ) ;
thread - > state = _ST_ST_RUNNING ;
thread - > state = _ST_ST_RUNNING ;
thread - > flags = _ST_FL_PRIMORDIAL ;
thread - > flags = _ST_FL_PRIMORDIAL ;
_ST_SET_CURRENT_THREAD ( thread ) ;
_st_this_thread = thread ;
_st_active_count + + ;
_st_active_count + + ;
# ifdef DEBUG
# ifdef DEBUG
_ST_ADD_THREADQ( thread ) ;
st_clist_insert_before( & thread - > tlink , & _st_this_vp . thread_q ) ;
# endif
# endif
return 0 ;
return 0 ;
@ -261,17 +261,17 @@ st_switch_cb_t st_set_switch_out_cb(st_switch_cb_t cb)
/* ARGSUSED */
/* ARGSUSED */
void * _st_idle_thread_start ( void * arg )
void * _st_idle_thread_start ( void * arg )
{
{
_st_thread_t * me = _ST_CURRENT_THREAD ( ) ;
_st_thread_t * me = _st_this_thread ;
while ( _st_active_count > 0 ) {
while ( _st_active_count > 0 ) {
/* Idle vp till I/O is ready or the smallest timeout expired */
/* Idle vp till I/O is ready or the smallest timeout expired */
_ST_VP_IDLE ( ) ;
( * _st_eventsys - > dispatch ) ( ) ;
/* Check sleep queue for expired threads */
/* Check sleep queue for expired threads */
_st_vp_check_clock ( ) ;
_st_vp_check_clock ( ) ;
me - > state = _ST_ST_RUNNABLE ;
me - > state = _ST_ST_RUNNABLE ;
_ ST_SWITCH_CONTEXT ( me ) ;
_ st_switch_context ( me ) ;
}
}
/* No more threads */
/* No more threads */
@ -284,7 +284,7 @@ void *_st_idle_thread_start(void *arg)
void st_thread_exit ( void * retval )
void st_thread_exit ( void * retval )
{
{
_st_thread_t * thread = _ST_CURRENT_THREAD ( ) ;
_st_thread_t * thread = _st_this_thread ;
thread - > retval = retval ;
thread - > retval = retval ;
_st_thread_cleanup ( thread ) ;
_st_thread_cleanup ( thread ) ;
@ -292,13 +292,13 @@ void st_thread_exit(void *retval)
if ( thread - > term ) {
if ( thread - > term ) {
/* Put thread on the zombie queue */
/* Put thread on the zombie queue */
thread - > state = _ST_ST_ZOMBIE ;
thread - > state = _ST_ST_ZOMBIE ;
_ST_ADD_ZOMBIEQ( thread ) ;
st_clist_insert_before( & thread - > links , & _st_this_vp . zombie_q ) ;
/* Notify on our termination condition variable */
/* Notify on our termination condition variable */
st_cond_signal ( thread - > term ) ;
st_cond_signal ( thread - > term ) ;
/* Switch context and come back later */
/* Switch context and come back later */
_ ST_SWITCH_CONTEXT ( thread ) ;
_ st_switch_context ( thread ) ;
/* Continue the cleanup */
/* Continue the cleanup */
st_cond_destroy ( thread - > term ) ;
st_cond_destroy ( thread - > term ) ;
@ -306,11 +306,11 @@ void st_thread_exit(void *retval)
}
}
# ifdef DEBUG
# ifdef DEBUG
_ST_DEL_THREADQ( thread ) ;
st_clist_remove( & thread - > tlink ) ;
# endif
# endif
/* merge from https://github.com/toffaletti/state-threads/commit/7f57fc9acc05e657bca1223f1e5b9b1a45ed929b */
/* merge from https://github.com/toffaletti/state-threads/commit/7f57fc9acc05e657bca1223f1e5b9b1a45ed929b */
# if ndef N VALGRIND
# if def MD_ VALGRIND
if ( ! ( thread - > flags & _ST_FL_PRIMORDIAL ) ) {
if ( ! ( thread - > flags & _ST_FL_PRIMORDIAL ) ) {
VALGRIND_STACK_DEREGISTER ( thread - > stack - > valgrind_stack_id ) ;
VALGRIND_STACK_DEREGISTER ( thread - > stack - > valgrind_stack_id ) ;
}
}
@ -320,7 +320,7 @@ void st_thread_exit(void *retval)
_st_stack_free ( thread - > stack ) ;
_st_stack_free ( thread - > stack ) ;
/* Find another thread to run */
/* Find another thread to run */
_ ST_SWITCH_CONTEXT ( thread ) ;
_ st_switch_context ( thread ) ;
/* Not going to land here */
/* Not going to land here */
}
}
@ -334,7 +334,7 @@ int st_thread_join(_st_thread_t *thread, void **retvalp)
errno = EINVAL ;
errno = EINVAL ;
return - 1 ;
return - 1 ;
}
}
if ( _ST_CURRENT_THREAD ( ) = = thread ) {
if ( _st_this_thread = = thread ) {
errno = EDEADLK ;
errno = EDEADLK ;
return - 1 ;
return - 1 ;
}
}
@ -358,8 +358,8 @@ int st_thread_join(_st_thread_t *thread, void **retvalp)
* When it gets scheduled later , it will do the clean up .
* When it gets scheduled later , it will do the clean up .
*/
*/
thread - > state = _ST_ST_RUNNABLE ;
thread - > state = _ST_ST_RUNNABLE ;
_ST_DEL_ZOMBIEQ( thread ) ;
st_clist_remove( & thread - > links ) ;
_ST_ADD_RUNQ( thread ) ;
st_clist_insert_before( & thread - > links , & _st_this_vp . run_q ) ;
return 0 ;
return 0 ;
}
}
@ -367,7 +367,7 @@ int st_thread_join(_st_thread_t *thread, void **retvalp)
void _st_thread_main ( void )
void _st_thread_main ( void )
{
{
_st_thread_t * thread = _ST_CURRENT_THREAD ( ) ;
_st_thread_t * thread = _st_this_thread ;
/*
/*
* Cap the stack by zeroing out the saved return address register
* Cap the stack by zeroing out the saved return address register
@ -392,7 +392,7 @@ void _st_thread_main(void)
static _st_thread_t * * heap_insert ( _st_thread_t * thread ) {
static _st_thread_t * * heap_insert ( _st_thread_t * thread ) {
int target = thread - > heap_index ;
int target = thread - > heap_index ;
int s = target ;
int s = target ;
_st_thread_t * * p = & _ ST_SLEEPQ ;
_st_thread_t * * p = & _ st_this_vp. sleep_q ;
int bits = 0 ;
int bits = 0 ;
int bit ;
int bit ;
int index = 1 ;
int index = 1 ;
@ -434,14 +434,14 @@ static void heap_delete(_st_thread_t *thread) {
int s , bit ;
int s , bit ;
/* First find and unlink the last heap element */
/* First find and unlink the last heap element */
p = & _ ST_SLEEPQ ;
p = & _ st_this_vp. sleep_q ;
s = _ ST_SLEEPQ_SIZE ;
s = _ st_this_vp. sleepq_size ;
while ( s ) {
while ( s ) {
s > > = 1 ;
s > > = 1 ;
bits + + ;
bits + + ;
}
}
for ( bit = bits - 2 ; bit > = 0 ; bit - - ) {
for ( bit = bits - 2 ; bit > = 0 ; bit - - ) {
if ( _ ST_SLEEPQ_SIZE & ( 1 < < bit ) ) {
if ( _ st_this_vp. sleepq_size & ( 1 < < bit ) ) {
p = & ( ( * p ) - > right ) ;
p = & ( ( * p ) - > right ) ;
} else {
} else {
p = & ( ( * p ) - > left ) ;
p = & ( ( * p ) - > left ) ;
@ -449,7 +449,7 @@ static void heap_delete(_st_thread_t *thread) {
}
}
t = * p ;
t = * p ;
* p = NULL ;
* p = NULL ;
- - _ ST_SLEEPQ_SIZE ;
- - _ st_this_vp. sleepq_size ;
if ( t ! = thread ) {
if ( t ! = thread ) {
/*
/*
* Insert the unlinked last element in place of the element we are deleting
* Insert the unlinked last element in place of the element we are deleting
@ -503,9 +503,9 @@ static void heap_delete(_st_thread_t *thread) {
void _st_add_sleep_q ( _st_thread_t * thread , st_utime_t timeout )
void _st_add_sleep_q ( _st_thread_t * thread , st_utime_t timeout )
{
{
thread - > due = _ ST_LAST_CLOCK + timeout ;
thread - > due = _ st_this_vp. last_clock + timeout ;
thread - > flags | = _ST_FL_ON_SLEEPQ ;
thread - > flags | = _ST_FL_ON_SLEEPQ ;
thread - > heap_index = + + _ ST_SLEEPQ_SIZE ;
thread - > heap_index = + + _ st_this_vp. sleepq_size ;
heap_insert ( thread ) ;
heap_insert ( thread ) ;
}
}
@ -527,9 +527,9 @@ void _st_vp_check_clock(void)
now = st_utime ( ) ;
now = st_utime ( ) ;
# if defined(DEBUG) && defined(DEBUG_STATS)
# if defined(DEBUG) && defined(DEBUG_STATS)
elapsed = now < _ ST_LAST_CLOCK? 0 : now - _ST_LAST_CLOCK ; // Might step back.
elapsed = now < _ st_this_vp. last_clock ? 0 : now - _st_this_vp . last_clock ; // Might step back.
# endif
# endif
_ ST_LAST_CLOCK = now ;
_ st_this_vp. last_clock = now ;
# if defined(DEBUG) && defined(DEBUG_STATS)
# if defined(DEBUG) && defined(DEBUG_STATS)
if ( elapsed < = 10000 ) {
if ( elapsed < = 10000 ) {
@ -558,12 +558,12 @@ void _st_vp_check_clock(void)
_st_last_tset = now ;
_st_last_tset = now ;
}
}
while ( _ ST_SLEEPQ ! = NULL ) {
while ( _ st_this_vp. sleep_q ! = NULL ) {
thread = _ ST_SLEEPQ ;
thread = _ st_this_vp. sleep_q ;
ST_ASSERT ( thread - > flags & _ST_FL_ON_SLEEPQ ) ;
ST_ASSERT ( thread - > flags & _ST_FL_ON_SLEEPQ ) ;
if ( thread - > due > now )
if ( thread - > due > now )
break ;
break ;
_ ST_DEL_SLEEPQ ( thread ) ;
_ st_del_sleep_q ( thread ) ;
/* If thread is waiting on condition variable, set the time out flag */
/* If thread is waiting on condition variable, set the time out flag */
if ( thread - > state = = _ST_ST_COND_WAIT )
if ( thread - > state = = _ST_ST_COND_WAIT )
@ -573,14 +573,14 @@ void _st_vp_check_clock(void)
ST_ASSERT ( ! ( thread - > flags & _ST_FL_IDLE_THREAD ) ) ;
ST_ASSERT ( ! ( thread - > flags & _ST_FL_IDLE_THREAD ) ) ;
thread - > state = _ST_ST_RUNNABLE ;
thread - > state = _ST_ST_RUNNABLE ;
// Insert at the head of RunQ, to execute timer first.
// Insert at the head of RunQ, to execute timer first.
_ST_INSERT_RUNQ( thread ) ;
st_clist_insert_after( & thread - > links , & _st_this_vp . run_q ) ;
}
}
}
}
void st_thread_yield ( )
void st_thread_yield ( )
{
{
_st_thread_t * me = _ST_CURRENT_THREAD ( ) ;
_st_thread_t * me = _st_this_thread ;
# if defined(DEBUG) && defined(DEBUG_STATS)
# if defined(DEBUG) && defined(DEBUG_STATS)
+ + _st_stat_thread_yield ;
+ + _st_stat_thread_yield ;
@ -590,7 +590,7 @@ void st_thread_yield()
_st_vp_check_clock ( ) ;
_st_vp_check_clock ( ) ;
// If not thread in RunQ to yield to, ignore and continue to run.
// If not thread in RunQ to yield to, ignore and continue to run.
if ( _ ST_RUNQ. next = = & _ST_RUNQ ) {
if ( _ st_this_vp. run_q . next = = & _st_this_vp . run_q ) {
return ;
return ;
}
}
@ -600,10 +600,10 @@ void st_thread_yield()
// Append thread to the tail of RunQ, we will back after all threads executed.
// Append thread to the tail of RunQ, we will back after all threads executed.
me - > state = _ST_ST_RUNNABLE ;
me - > state = _ST_ST_RUNNABLE ;
_ST_ADD_RUNQ( me ) ;
st_clist_insert_before( & me - > links , & _st_this_vp . run_q ) ;
// Yield to other threads in the RunQ.
// Yield to other threads in the RunQ.
_ ST_SWITCH_CONTEXT ( me ) ;
_ st_switch_context ( me ) ;
}
}
@ -619,11 +619,11 @@ void st_thread_interrupt(_st_thread_t *thread)
return ;
return ;
if ( thread - > flags & _ST_FL_ON_SLEEPQ )
if ( thread - > flags & _ST_FL_ON_SLEEPQ )
_ ST_DEL_SLEEPQ ( thread ) ;
_ st_del_sleep_q ( thread ) ;
/* Make thread runnable */
/* Make thread runnable */
thread - > state = _ST_ST_RUNNABLE ;
thread - > state = _ST_ST_RUNNABLE ;
_ST_ADD_RUNQ( thread ) ;
st_clist_insert_before( & thread - > links , & _st_this_vp . run_q ) ;
}
}
@ -637,7 +637,7 @@ _st_thread_t *st_thread_create(void *(*start)(void *arg), void *arg, int joinabl
/* Adjust stack size */
/* Adjust stack size */
if ( stk_size = = 0 )
if ( stk_size = = 0 )
stk_size = ST_DEFAULT_STACK_SIZE ;
stk_size = ST_DEFAULT_STACK_SIZE ;
stk_size = ( ( stk_size + _ ST_PAGE_SIZE - 1 ) / _ST_PAGE_SIZE ) * _ST_PAGE_SIZE ;
stk_size = ( ( stk_size + _ st_this_vp. pagesize - 1 ) / _st_this_vp . pagesize ) * _st_this_vp . pagesize ;
stack = _st_stack_new ( stk_size ) ;
stack = _st_stack_new ( stk_size ) ;
if ( ! stack )
if ( ! stack )
return NULL ;
return NULL ;
@ -663,7 +663,10 @@ _st_thread_t *st_thread_create(void *(*start)(void *arg), void *arg, int joinabl
thread - > start = start ;
thread - > start = start ;
thread - > arg = arg ;
thread - > arg = arg ;
_ST_INIT_CONTEXT ( thread , stack - > sp , _st_thread_main ) ;
/* Note that we must directly call rather than call any functions. */
if ( _st_md_cxt_save ( thread - > context ) )
_st_thread_main ( ) ;
MD_GET_SP ( thread ) = ( long ) ( stack - > sp ) ;
/* If thread is joinable, allocate a termination condition variable */
/* If thread is joinable, allocate a termination condition variable */
if ( joinable ) {
if ( joinable ) {
@ -677,13 +680,13 @@ _st_thread_t *st_thread_create(void *(*start)(void *arg), void *arg, int joinabl
/* Make thread runnable */
/* Make thread runnable */
thread - > state = _ST_ST_RUNNABLE ;
thread - > state = _ST_ST_RUNNABLE ;
_st_active_count + + ;
_st_active_count + + ;
_ST_ADD_RUNQ( thread ) ;
st_clist_insert_before( & thread - > links , & _st_this_vp . run_q ) ;
# ifdef DEBUG
# ifdef DEBUG
_ST_ADD_THREADQ( thread ) ;
st_clist_insert_before( & thread - > tlink , & _st_this_vp . thread_q ) ;
# endif
# endif
/* merge from https://github.com/toffaletti/state-threads/commit/7f57fc9acc05e657bca1223f1e5b9b1a45ed929b */
/* merge from https://github.com/toffaletti/state-threads/commit/7f57fc9acc05e657bca1223f1e5b9b1a45ed929b */
# if ndef N VALGRIND
# if def MD_ VALGRIND
if ( ! ( thread - > flags & _ST_FL_PRIMORDIAL ) ) {
if ( ! ( thread - > flags & _ST_FL_PRIMORDIAL ) ) {
thread - > stack - > valgrind_stack_id = VALGRIND_STACK_REGISTER ( thread - > stack - > stk_top , thread - > stack - > stk_bottom ) ;
thread - > stack - > valgrind_stack_id = VALGRIND_STACK_REGISTER ( thread - > stack - > stk_top , thread - > stack - > stk_bottom ) ;
}
}
@ -695,7 +698,7 @@ _st_thread_t *st_thread_create(void *(*start)(void *arg), void *arg, int joinabl
_st_thread_t * st_thread_self ( void )
_st_thread_t * st_thread_self ( void )
{
{
return _ST_CURRENT_THREAD ( ) ;
return _st_this_thread ;
}
}
# ifdef DEBUG
# ifdef DEBUG
@ -717,7 +720,7 @@ void _st_iterate_threads(void)
if ( ! _st_iterate_threads_flag ) {
if ( ! _st_iterate_threads_flag ) {
if ( thread ) {
if ( thread ) {
memcpy ( thread - > context , save_jb , sizeof ( _st_jmp_buf_t ) ) ;
memcpy ( thread - > context , save_jb , sizeof ( _st_jmp_buf_t ) ) ;
MD_LONGJMP ( orig_jb , 1 ) ;
_st_md_cxt_restore ( orig_jb , 1 ) ;
}
}
return ;
return ;
}
}
@ -726,25 +729,25 @@ void _st_iterate_threads(void)
memcpy ( thread - > context , save_jb , sizeof ( _st_jmp_buf_t ) ) ;
memcpy ( thread - > context , save_jb , sizeof ( _st_jmp_buf_t ) ) ;
_st_show_thread_stack ( thread , NULL ) ;
_st_show_thread_stack ( thread , NULL ) ;
} else {
} else {
if ( MD_SETJMP ( orig_jb ) ) {
if ( _st_md_cxt_save ( orig_jb ) ) {
_st_iterate_threads_flag = 0 ;
_st_iterate_threads_flag = 0 ;
thread = NULL ;
thread = NULL ;
_st_show_thread_stack ( thread , " Iteration completed " ) ;
_st_show_thread_stack ( thread , " Iteration completed " ) ;
return ;
return ;
}
}
thread = _ST_CURRENT_THREAD ( ) ;
thread = _st_this_thread ;
_st_show_thread_stack ( thread , " Iteration started " ) ;
_st_show_thread_stack ( thread , " Iteration started " ) ;
}
}
q = thread - > tlink . next ;
q = thread - > tlink . next ;
if ( q = = & _ ST_THREADQ )
if ( q = = & _ st_this_vp. thread_q )
q = q - > next ;
q = q - > next ;
ST_ASSERT ( q ! = & _ ST_THREADQ ) ;
ST_ASSERT ( q ! = & _ st_this_vp. thread_q ) ;
thread = _ST_THREAD_THREADQ_PTR ( q ) ;
thread = _ST_THREAD_THREADQ_PTR ( q ) ;
if ( thread = = _ST_CURRENT_THREAD ( ) )
if ( thread = = _st_this_thread )
MD_LONGJMP ( orig_jb , 1 ) ;
_st_md_cxt_restore ( orig_jb , 1 ) ;
memcpy ( save_jb , thread - > context , sizeof ( _st_jmp_buf_t ) ) ;
memcpy ( save_jb , thread - > context , sizeof ( _st_jmp_buf_t ) ) ;
MD_LONGJMP ( thread - > context , 1 ) ;
_st_md_cxt_restore ( thread - > context , 1 ) ;
}
}
# endif /* DEBUG */
# endif /* DEBUG */