152 lines
3.7 KiB
C
152 lines
3.7 KiB
C
/***** includes *****/
|
|
#include "internal.h"
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
void util_thread_starter_new( struct util_thread_starter_state **tts, lfds700_pal_uint_t number_threads )
|
|
{
|
|
lfds700_pal_uint_t
|
|
loop;
|
|
|
|
assert( tts != NULL );
|
|
// TRD : number_threads cam be any value in its range
|
|
|
|
*tts = util_malloc_wrapper( sizeof(struct util_thread_starter_state) );
|
|
|
|
(*tts)->tsts = util_malloc_wrapper( sizeof(struct util_thread_starter_thread_state) * number_threads );
|
|
(*tts)->thread_start_flag = LOWERED;
|
|
(*tts)->number_thread_states = number_threads;
|
|
|
|
for( loop = 0 ; loop < number_threads ; loop++ )
|
|
{
|
|
((*tts)->tsts+loop)->thread_ready_flag = LOWERED;
|
|
((*tts)->tsts+loop)->thread_start_flag = &(*tts)->thread_start_flag;
|
|
}
|
|
|
|
LFDS700_MISC_BARRIER_STORE;
|
|
|
|
lfds700_misc_force_store();
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
void util_thread_starter_start( struct util_thread_starter_state *tts,
|
|
test_pal_thread_state_t *thread_state,
|
|
lfds700_pal_uint_t thread_number,
|
|
struct test_pal_logical_processor *lp,
|
|
test_pal_thread_return_t (TEST_PAL_CALLING_CONVENTION *thread_function)( void *thread_user_state ),
|
|
void *thread_user_state )
|
|
{
|
|
assert( tts != NULL );
|
|
assert( thread_state != NULL );
|
|
assert( lp != NULL );
|
|
assert( thread_function != NULL );
|
|
// TRD : thread_user_state can be NULL
|
|
|
|
(tts->tsts+thread_number)->thread_user_state = thread_user_state;
|
|
|
|
util_thread_start_wrapper( thread_state, lp, thread_function, tts->tsts+thread_number );
|
|
|
|
// TRD : wait for the thread to indicate it is ready and waiting
|
|
while( (tts->tsts+thread_number)->thread_ready_flag == LOWERED );
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
void util_thread_starter_ready_and_wait( struct util_thread_starter_thread_state *tsts )
|
|
{
|
|
assert( tsts != NULL );
|
|
|
|
tsts->thread_ready_flag = RAISED;
|
|
|
|
LFDS700_MISC_BARRIER_FULL;
|
|
|
|
// TRD : threads here are all looping, so we don't need to force a store
|
|
|
|
while( *tsts->thread_start_flag == LOWERED )
|
|
LFDS700_MISC_BARRIER_LOAD;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
void util_thread_starter_run( struct util_thread_starter_state *tts )
|
|
{
|
|
assert( tts != NULL );
|
|
|
|
/* TRD : all threads at this point are ready to go
|
|
as we wait for their ready flag immediately after their spawn
|
|
*/
|
|
|
|
tts->thread_start_flag = RAISED;
|
|
|
|
LFDS700_MISC_BARRIER_STORE;
|
|
|
|
lfds700_misc_force_store();
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
void util_thread_starter_delete( struct util_thread_starter_state *tts )
|
|
{
|
|
assert( tts != NULL );
|
|
|
|
free( tts->tsts );
|
|
|
|
free( tts );
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
void util_thread_start_wrapper( test_pal_thread_state_t *thread_state,
|
|
struct test_pal_logical_processor *lp,
|
|
test_pal_thread_return_t (TEST_PAL_CALLING_CONVENTION *thread_function)(void *thread_user_state),
|
|
void *thread_user_state )
|
|
{
|
|
int
|
|
rv;
|
|
|
|
assert( thread_state != NULL );
|
|
assert( lp != NULL );
|
|
assert( thread_function != NULL );
|
|
// TRD : thread_user_state can be NULL
|
|
|
|
rv = test_pal_thread_start( thread_state, lp, thread_function, thread_user_state );
|
|
|
|
if( rv == 0 )
|
|
{
|
|
puts( "test_pal_thread_start() failed." );
|
|
exit( EXIT_FAILURE );
|
|
}
|
|
|
|
return;
|
|
}
|
|
|