util_thread_starter.c 3.72 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
/***** 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;
}