Пример #1
0
void _Thread_queue_Initialize(
  Thread_queue_Control         *the_thread_queue,
  Thread_queue_Disciplines      the_discipline,
  States_Control                state,
  uint32_t                      timeout_status
)
{
  if ( _Scheduler_FIXME_thread_priority_queues_are_broken ) {
    the_discipline = THREAD_QUEUE_DISCIPLINE_FIFO;
  }

  the_thread_queue->state          = state;
  the_thread_queue->discipline     = the_discipline;
  the_thread_queue->timeout_status = timeout_status;
  the_thread_queue->sync_state     = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;

  if ( the_discipline == THREAD_QUEUE_DISCIPLINE_PRIORITY ) {
    uint32_t   index;

    for( index=0 ;
         index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
         index++)
      _Chain_Initialize_empty( &the_thread_queue->Queues.Priority[index] );
  } else { /* must be THREAD_QUEUE_DISCIPLINE_FIFO */
    _Chain_Initialize_empty( &the_thread_queue->Queues.Fifo );
  }

}
Пример #2
0
void _Scheduler_simple_smp_Initialize( void )
{
  Scheduler_simple_smp_Control *self =
    _Workspace_Allocate_or_fatal_error( sizeof( *self ) );

  _Chain_Initialize_empty( &self->ready );
  _Chain_Initialize_empty( &self->scheduled );

  _Scheduler.information = self;
}
Пример #3
0
void _POSIX_signals_Manager_Initialization(void)
{
  uint32_t   signo;
  uint32_t   maximum_queued_signals;

  maximum_queued_signals = Configuration_POSIX_API.maximum_queued_signals;

  memcpy(
    _POSIX_signals_Vectors,
    _POSIX_signals_Default_vectors,
    sizeof( _POSIX_signals_Vectors )
  );

  /*
   *  Initialize the set of pending signals for the entire process
   */
  sigemptyset( &_POSIX_signals_Pending );

  /*
   *  Initialize the queue we use to block for signals
   */
  _Thread_queue_Initialize(
    &_POSIX_signals_Wait_queue,
    THREAD_QUEUE_DISCIPLINE_FIFO,
    STATES_WAITING_FOR_SIGNAL | STATES_INTERRUPTIBLE_BY_SIGNAL,
    EAGAIN
  );

  /* XXX status codes */

  /*
   *  Allocate the siginfo pools.
   */
  for ( signo=1 ; signo<= SIGRTMAX ; signo++ )
    _Chain_Initialize_empty( &_POSIX_signals_Siginfo[ signo ] );

  if ( maximum_queued_signals ) {
    _Chain_Initialize(
      &_POSIX_signals_Inactive_siginfo,
      _Workspace_Allocate_or_fatal_error(
        maximum_queued_signals * sizeof( POSIX_signals_Siginfo_node )
      ),
      maximum_queued_signals,
      sizeof( POSIX_signals_Siginfo_node )
    );
  } else {
    _Chain_Initialize_empty( &_POSIX_signals_Inactive_siginfo );
  }
}
void _Thread_Set_transient(
  Thread_Control *the_thread
)
{
  ISR_Level             level;
  uint32_t              old_state;
  Chain_Control *ready;

  ready = the_thread->ready;
  _ISR_Disable( level );

  old_state = the_thread->current_state;
  the_thread->current_state = _States_Set( STATES_TRANSIENT, old_state );

  if ( _States_Is_ready( old_state ) ) {
    if ( _Chain_Has_only_one_node( ready ) ) {

      _Chain_Initialize_empty( ready );
      _Priority_Remove_from_bit_map( &the_thread->Priority_map );

    } else
      _Chain_Extract_unprotected( &the_thread->Object.Node );
  }

  _ISR_Enable( level );

}
Пример #5
0
void _Scheduler_simple_SMP_Initialize( const Scheduler_Control *scheduler )
{
  Scheduler_simple_SMP_Context *self =
    _Scheduler_simple_SMP_Get_context( scheduler );

  _Scheduler_SMP_Initialize( &self->Base );
  _Chain_Initialize_empty( &self->Ready );
}
Пример #6
0
void _Scheduler_simple_Initialize ( void )
{
  Scheduler_simple_Control *scheduler =
    _Workspace_Allocate_or_fatal_error( sizeof( *scheduler ) );

  _Chain_Initialize_empty( &scheduler->Ready );

  _Scheduler.information = scheduler;
}
Пример #7
0
static void _Thread_queue_Priority_do_initialize(
  Thread_queue_Heads *heads
)
{
#if defined(RTEMS_SMP)
  _Chain_Initialize_empty( &heads->Heads.Fifo );
#else
  _RBTree_Initialize_empty( &heads->Heads.Priority.Queue );
#endif
}
Пример #8
0
void _Scheduler_priority_SMP_Initialize( void )
{
  Scheduler_SMP_Control *self = _Workspace_Allocate_or_fatal_error(
    sizeof( *self ) + PRIORITY_MAXIMUM * sizeof( Chain_Control )
  );

  _Chain_Initialize_empty( &self->scheduled );
  _Scheduler_priority_Ready_queue_initialize( &self->ready[ 0 ] );

  _Scheduler.information = self;
}
Пример #9
0
void _Thread_MP_Handler_initialization (
  uint32_t    maximum_proxies
)
{

  _Chain_Initialize_empty( &_Thread_MP_Active_proxies );

  if ( maximum_proxies == 0 ) {
    _Chain_Initialize_empty( &_Thread_MP_Inactive_proxies );
    return;
  }


  _Chain_Initialize(
    &_Thread_MP_Inactive_proxies,
    _Workspace_Allocate_or_fatal_error(
      maximum_proxies * sizeof( Thread_Proxy_control )
    ),
    maximum_proxies,
    sizeof( Thread_Proxy_control )
  );

}
Пример #10
0
rtems_task Init(
  rtems_task_argument argument
)
{
  rtems_time_of_day  time;
  rtems_status_code  status;
  Chain_Control      empty;

   puts( "\n*** RTEMS WATCHDOG ***" );

  puts( "INIT - report on empty watchdog chain" );
  _Chain_Initialize_empty( &empty );
  _Watchdog_Report_chain( "Empty Chain", &empty );

  build_time( &time, 12, 31, 1988, 9, 0, 0, 0 );

  status = rtems_clock_set( &time );
  directive_failed( status, "rtems_clock_set" );

  Task_name[ 1 ]  = rtems_build_name( 'T', 'A', '1', ' ' );
  Timer_name[ 1 ] = rtems_build_name( 'T', 'M', '1', ' ' );

  status = rtems_task_create(
    Task_name[ 1 ],
    1,
    RTEMS_MINIMUM_STACK_SIZE * 2,
    RTEMS_DEFAULT_MODES,
    RTEMS_DEFAULT_ATTRIBUTES,
    &Task_id[ 1 ]
  );
  directive_failed( status, "rtems_task_create of TA1" );

  status = rtems_task_start( Task_id[ 1 ], Task_1, 0 );
  directive_failed( status, "rtems_task_start of TA1" );

  puts( "INIT - rtems_timer_create - creating timer 1" );
  status = rtems_timer_create( Timer_name[ 1 ], &Timer_id[ 1 ] );
  directive_failed( status, "rtems_timer_create" );

  printf( "INIT - timer 1 has id (0x%" PRIxrtems_id ")\n", Timer_id[ 1 ] );

  status = rtems_task_delete( RTEMS_SELF );
  directive_failed( status, "rtems_task_delete of RTEMS_SELF" );


  rtems_test_exit( 0 );
}
void _Thread_Suspend(
  Thread_Control   *the_thread
)
{
  ISR_Level      level;
  Chain_Control *ready;

  ready = the_thread->ready;
  _ISR_Disable( level );
  #if defined(RTEMS_ITRON_API)
    the_thread->suspend_count++;
  #endif
  if ( !_States_Is_ready( the_thread->current_state ) ) {
    the_thread->current_state =
       _States_Set( STATES_SUSPENDED, the_thread->current_state );
    _ISR_Enable( level );
    return;
  }

  the_thread->current_state = STATES_SUSPENDED;

  if ( _Chain_Has_only_one_node( ready ) ) {

    _Chain_Initialize_empty( ready );
    _Priority_Remove_from_bit_map( &the_thread->Priority_map );

  } else
    _Chain_Extract_unprotected( &the_thread->Object.Node );

  _ISR_Flash( level );

  if ( _Thread_Is_heir( the_thread ) )
     _Thread_Calculate_heir();

  if ( _Thread_Is_executing( the_thread ) )
    _Context_Switch_necessary = true;

  _ISR_Enable( level );
}
Пример #12
0
void ReadFileIntoChain2(
  FILE *InFile
)
{
   int   line_count;
   int   max_length;
   char *line;
   char  Buffer[ BUFFER_SIZE ];
   Line_Control *new_line;

   if ( !InFile ) {
     fprintf( stderr, "Unable to open (%s)\n", "stdin" );
     exit( 1 );
   }
   assert( InFile );

   max_length = 0;
   line_count = 0;

   _Chain_Initialize_empty( &Lines );

   for ( ;; ) {
      line = fgets( Buffer, BUFFER_SIZE, InFile );
      if ( !line )
        break;

      Buffer[ strlen( Buffer ) - 1 ] = '\0';

      new_line = AllocateLine();

      strcpy( new_line->Contents, Buffer );

      new_line->number = ++line_count;

      _Chain_Append( &Lines, &new_line->Node );
   }

   fclose( InFile );
}
Пример #13
0
void _Chain_Insert_chain(
  Chain_Node    *insert_after,
  Chain_Control *to_insert
)
{
  Chain_Node *first;
  Chain_Node *last;
  Chain_Node *insert_after_next;

  first = to_insert->first;
  last = to_insert->last;

  insert_after_next = insert_after->next;

  insert_after->next = first;
  first->previous    = insert_after;

  insert_after_next->previous = last;
  last->next                  = insert_after_next;

  _Chain_Initialize_empty( to_insert );
}
Пример #14
0
Файл: smp.c Проект: gedare/rtems
void _SMP_Handler_initialize( void )
{
  uint32_t cpu_max = rtems_configuration_get_maximum_processors();
  uint32_t cpu_count;
  uint32_t cpu_index;

  for ( cpu_index = 0 ; cpu_index < cpu_max; ++cpu_index ) {
    Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );

    _ISR_lock_Initialize( &cpu->Watchdog.Lock, "Watchdog" );
    _SMP_ticket_lock_Initialize( &cpu->Lock );
    _SMP_lock_Stats_initialize( &cpu->Lock_stats, "Per-CPU" );
    _Chain_Initialize_empty( &cpu->Threads_in_need_for_help );
  }

  /*
   * Discover and initialize the secondary cores in an SMP system.
   */

  cpu_count = _CPU_SMP_Initialize();
  cpu_count = cpu_count < cpu_max ? cpu_count : cpu_max;
  _SMP_Processor_count = cpu_count;

  for ( cpu_index = cpu_count ; cpu_index < cpu_max; ++cpu_index ) {
    const Scheduler_Assignment *assignment;

    assignment = _Scheduler_Get_initial_assignment( cpu_index );

    if ( _Scheduler_Is_mandatory_processor( assignment ) ) {
      _SMP_Fatal( SMP_FATAL_MANDATORY_PROCESSOR_NOT_PRESENT );
    }
  }

  _SMP_Start_processors( cpu_count );

  _CPU_SMP_Finalize_initialization( cpu_count );
}
void _Thread_Set_state(
  Thread_Control *the_thread,
  States_Control  state
)
{
  ISR_Level      level;
  Chain_Control *ready;

  ready = the_thread->ready;
  _ISR_Disable( level );
  if ( !_States_Is_ready( the_thread->current_state ) ) {
    the_thread->current_state =
       _States_Set( state, the_thread->current_state );
    _ISR_Enable( level );
    return;
  }

  the_thread->current_state = state;

  if ( _Chain_Has_only_one_node( ready ) ) {

    _Chain_Initialize_empty( ready );
    _Priority_Remove_from_bit_map( &the_thread->Priority_map );

  } else
    _Chain_Extract_unprotected( &the_thread->Object.Node );

  _ISR_Flash( level );

  if ( _Thread_Is_heir( the_thread ) )
     _Thread_Calculate_heir();

  if ( _Thread_Is_executing( the_thread ) )
    _Context_Switch_necessary = TRUE;

  _ISR_Enable( level );
}
Пример #16
0
void _Objects_MP_Handler_initialization(void)
{

  uint32_t   maximum_global_objects;

  maximum_global_objects = _Configuration_MP_table->maximum_global_objects;

  _Objects_MP_Maximum_global_objects = maximum_global_objects;

  if ( maximum_global_objects == 0 ) {
    _Chain_Initialize_empty( &_Objects_MP_Inactive_global_objects );
    return;
  }

  _Chain_Initialize(
    &_Objects_MP_Inactive_global_objects,
    _Workspace_Allocate_or_fatal_error(
      maximum_global_objects * sizeof( Objects_MP_Control )
    ),
    maximum_global_objects,
    sizeof( Objects_MP_Control )
  );

}
Пример #17
0
void _Objects_Initialize_information(
  Objects_Information *information,
  Objects_APIs         the_api,
  uint32_t             the_class,
  uint32_t             maximum,
  uint16_t             size,
  bool                 is_string,
  uint32_t             maximum_name_length
#if defined(RTEMS_MULTIPROCESSING)
  ,
  bool                 supports_global,
  Objects_Thread_queue_Extract_callout extract
#endif
)
{
  static Objects_Control *null_local_table = NULL;
  uint32_t                minimum_index;
  uint32_t                name_length;
  uint32_t                maximum_per_allocation;
  #if defined(RTEMS_MULTIPROCESSING)
    uint32_t              index;
  #endif

  information->the_api            = the_api;
  information->the_class          = the_class;
  information->size               = size;
  information->local_table        = 0;
  information->inactive_per_block = 0;
  information->object_blocks      = 0;
  information->inactive           = 0;
  #if defined(RTEMS_SCORE_OBJECT_ENABLE_STRING_NAMES)
    information->is_string        = is_string;
  #endif

  /*
   *  Set the maximum value to 0. It will be updated when objects are
   *  added to the inactive set from _Objects_Extend_information()
   */
  information->maximum = 0;

  /*
   *  Register this Object Class in the Object Information Table.
   */
  _Objects_Information_table[ the_api ][ the_class ] = information;

  /*
   *  Are we operating in limited or unlimited (e.g. auto-extend) mode.
   */
  information->auto_extend =
        (maximum & OBJECTS_UNLIMITED_OBJECTS) ? true : false;
  maximum_per_allocation = maximum & ~OBJECTS_UNLIMITED_OBJECTS;

  /*
   *  Unlimited and maximum of zero is illogical.
   */
  if ( information->auto_extend && maximum_per_allocation == 0) {
    _Internal_error_Occurred(
      INTERNAL_ERROR_CORE,
      true,
      INTERNAL_ERROR_UNLIMITED_AND_MAXIMUM_IS_0
    );
  }

  /*
   *  The allocation unit is the maximum value
   */
  information->allocation_size = maximum_per_allocation;

  /*
   *  Provide a null local table entry for the case of any empty table.
   */
  information->local_table = &null_local_table;

  /*
   *  Calculate minimum and maximum Id's
   */
  minimum_index = (maximum_per_allocation == 0) ? 0 : 1;
  information->minimum_id =
    _Objects_Build_id( the_api, the_class, _Objects_Local_node, minimum_index );

  /*
   *  Calculate the maximum name length
   */
  name_length = maximum_name_length;

  if ( name_length & (OBJECTS_NAME_ALIGNMENT-1) )
    name_length = (name_length + OBJECTS_NAME_ALIGNMENT) &
                  ~(OBJECTS_NAME_ALIGNMENT-1);

  information->name_length = name_length;

  _Chain_Initialize_empty( &information->Inactive );

  /*
   *  Initialize objects .. if there are any
   */
  if ( maximum_per_allocation ) {
    /*
     *  Always have the maximum size available so the current performance
     *  figures are create are met.  If the user moves past the maximum
     *  number then a performance hit is taken.
     */
    _Objects_Extend_information( information );
  }

  /*
   *  Take care of multiprocessing
   */
  #if defined(RTEMS_MULTIPROCESSING)
    information->extract = extract;

    if ( (supports_global == true) && _System_state_Is_multiprocessing ) {

      information->global_table =
	(Chain_Control *) _Workspace_Allocate_or_fatal_error(
	  (_Objects_Maximum_nodes + 1) * sizeof(Chain_Control)
	);

      for ( index=1; index <= _Objects_Maximum_nodes ; index++ )
	_Chain_Initialize_empty( &information->global_table[ index ] );
     }
     else
       information->global_table = NULL;
  #endif
}
Пример #18
0
bool _CORE_message_queue_Initialize(
    CORE_message_queue_Control     *the_message_queue,
    CORE_message_queue_Disciplines  discipline,
    uint32_t                        maximum_pending_messages,
    size_t                          maximum_message_size
)
{
    size_t message_buffering_required = 0;
    size_t aligned_message_size;
    size_t align_mask;

    the_message_queue->maximum_pending_messages   = maximum_pending_messages;
    the_message_queue->number_of_pending_messages = 0;
    the_message_queue->maximum_message_size       = maximum_message_size;
    _CORE_message_queue_Set_notify( the_message_queue, NULL );

    /*
     * Align up the maximum message size to be an integral multiple of the
     * pointer size.
     */
    align_mask = sizeof(uintptr_t) - 1;
    aligned_message_size = ( maximum_message_size + align_mask ) & ~align_mask;

    /*
     * Check for an integer overflow.  It can occur while aligning up the maximum
     * message size.
     */
    if (aligned_message_size < maximum_message_size)
        return false;

    /*
     *  Calculate how much total memory is required for message buffering and
     *  check for overflow on the multiplication.
     */
    if ( !size_t_mult32_with_overflow(
                (size_t) maximum_pending_messages,
                aligned_message_size + sizeof(CORE_message_queue_Buffer_control),
                &message_buffering_required ) )
        return false;

    /*
     *  Attempt to allocate the message memory
     */
    the_message_queue->message_buffers = (CORE_message_queue_Buffer *)
                                         _Workspace_Allocate( message_buffering_required );

    if (the_message_queue->message_buffers == 0)
        return false;

    /*
     *  Initialize the pool of inactive messages, pending messages,
     *  and set of waiting threads.
     */
    _Chain_Initialize (
        &the_message_queue->Inactive_messages,
        the_message_queue->message_buffers,
        (size_t) maximum_pending_messages,
        aligned_message_size + sizeof( CORE_message_queue_Buffer_control )
    );

    _Chain_Initialize_empty( &the_message_queue->Pending_messages );

    _Thread_queue_Initialize( &the_message_queue->Wait_queue );

    if ( discipline == CORE_MESSAGE_QUEUE_DISCIPLINES_PRIORITY ) {
        the_message_queue->operations = &_Thread_queue_Operations_priority;
    } else {
        the_message_queue->operations = &_Thread_queue_Operations_FIFO;
    }

    return true;
}
Пример #19
0
bool _CORE_message_queue_Initialize(
  CORE_message_queue_Control    *the_message_queue,
  CORE_message_queue_Attributes *the_message_queue_attributes,
  uint32_t                       maximum_pending_messages,
  size_t                         maximum_message_size
)
{
  size_t message_buffering_required;
  size_t allocated_message_size;

  the_message_queue->maximum_pending_messages   = maximum_pending_messages;
  the_message_queue->number_of_pending_messages = 0;
  the_message_queue->maximum_message_size       = maximum_message_size;
  _CORE_message_queue_Set_notify( the_message_queue, NULL, NULL );

  /*
   *  Round size up to multiple of a pointer for chain init and
   *  check for overflow on adding overhead to each message.
   */
  allocated_message_size = maximum_message_size;
  if (allocated_message_size & (sizeof(uint32_t) - 1)) {
    allocated_message_size += sizeof(uint32_t);
    allocated_message_size &= ~(sizeof(uint32_t) - 1);
  }

  if (allocated_message_size < maximum_message_size)
    return false;

  /*
   *  Calculate how much total memory is required for message buffering and
   *  check for overflow on the multiplication.
   */
  message_buffering_required = (size_t) maximum_pending_messages *
       (allocated_message_size + sizeof(CORE_message_queue_Buffer_control));

  if (message_buffering_required < allocated_message_size)
    return false;

  /*
   *  Attempt to allocate the message memory
   */
  the_message_queue->message_buffers = (CORE_message_queue_Buffer *)
     _Workspace_Allocate( message_buffering_required );

  if (the_message_queue->message_buffers == 0)
    return false;

  /*
   *  Initialize the pool of inactive messages, pending messages,
   *  and set of waiting threads.
   */
  _Chain_Initialize (
    &the_message_queue->Inactive_messages,
    the_message_queue->message_buffers,
    (size_t) maximum_pending_messages,
    allocated_message_size + sizeof( CORE_message_queue_Buffer_control )
  );

  _Chain_Initialize_empty( &the_message_queue->Pending_messages );

  _Thread_queue_Initialize(
    &the_message_queue->Wait_queue,
    _CORE_message_queue_Is_priority( the_message_queue_attributes ) ?
       THREAD_QUEUE_DISCIPLINE_PRIORITY : THREAD_QUEUE_DISCIPLINE_FIFO,
    STATES_WAITING_FOR_MESSAGE,
    CORE_MESSAGE_QUEUE_STATUS_TIMEOUT
  );

  return true;
}
Пример #20
0
/**
 *  @brief Timer server body.
 *
 *  This is the server for task based timers.  This task executes whenever a
 *  task-based timer should fire.  It services both "after" and "when" timers.
 *  It is not created automatically but must be created explicitly by the
 *  application before task-based timers may be initiated.  The parameter
 *  @a arg points to the corresponding timer server control block.
 */
static rtems_task _Timer_server_Body(
  rtems_task_argument arg
)
{
  Timer_server_Control *ts = (Timer_server_Control *) arg;
  Chain_Control insert_chain;
  Chain_Control fire_chain;

  _Chain_Initialize_empty( &insert_chain );
  _Chain_Initialize_empty( &fire_chain );

  while ( true ) {
    _Timer_server_Get_watchdogs_that_fire_now( ts, &insert_chain, &fire_chain );

    if ( !_Chain_Is_empty( &fire_chain ) ) {
      /*
       *  Fire the watchdogs.
       */
      while ( true ) {
        Watchdog_Control *watchdog;
        ISR_Level level;

        /*
         *  It is essential that interrupts are disable here since an interrupt
         *  service routine may remove a watchdog from the chain.
         */
        _ISR_Disable( level );
        watchdog = (Watchdog_Control *) _Chain_Get_unprotected( &fire_chain );
        if ( watchdog != NULL ) {
          watchdog->state = WATCHDOG_INACTIVE;
          _ISR_Enable( level );
        } else {
          _ISR_Enable( level );

          break;
        }

        /*
         *  The timer server may block here and wait for resources or time.
         *  The system watchdogs are inactive and will remain inactive since
         *  the active flag of the timer server is true.
         */
        (*watchdog->routine)( watchdog->id, watchdog->user_data );
      }
    } else {
      ts->active = false;

      /*
       *  Block until there is something to do.
       */
      _Thread_Disable_dispatch();
        _Thread_Set_state( ts->thread, STATES_DELAYING );
        _Timer_server_Reset_interval_system_watchdog( ts );
        _Timer_server_Reset_tod_system_watchdog( ts );
      _Thread_Enable_dispatch();

      ts->active = true;

      /*
       *  Maybe an interrupt did reset the system timers, so we have to stop
       *  them here.  Since we are active now, there will be no more resets
       *  until we are inactive again.
       */
      _Timer_server_Stop_interval_system_watchdog( ts );
      _Timer_server_Stop_tod_system_watchdog( ts );
    }
  }
}
Пример #21
0
bool _CORE_message_queue_Initialize(
  CORE_message_queue_Control    *the_message_queue,
  CORE_message_queue_Attributes *the_message_queue_attributes,
  uint32_t                       maximum_pending_messages,
  size_t                         maximum_message_size
)
{
  size_t message_buffering_required = 0;
  size_t allocated_message_size;

  the_message_queue->maximum_pending_messages   = maximum_pending_messages;
  the_message_queue->number_of_pending_messages = 0;
  the_message_queue->maximum_message_size       = maximum_message_size;
  _CORE_message_queue_Set_notify( the_message_queue, NULL, NULL );

  allocated_message_size = maximum_message_size;

  /* 
   * Check if allocated_message_size is aligned to uintptr-size boundary. 
   * If not, it will increase allocated_message_size to multiplicity of pointer
   * size.
   */
  if (allocated_message_size & (sizeof(uintptr_t) - 1)) {
    allocated_message_size += sizeof(uintptr_t);
    allocated_message_size &= ~(sizeof(uintptr_t) - 1);
  }

  /* 
   * Check for an overflow. It can occur while increasing allocated_message_size
   * to multiplicity of uintptr_t above.
   */
  if (allocated_message_size < maximum_message_size)
    return false;

  /*
   *  Calculate how much total memory is required for message buffering and
   *  check for overflow on the multiplication.
   */
  if ( !size_t_mult32_with_overflow(
        (size_t) maximum_pending_messages,
        allocated_message_size + sizeof(CORE_message_queue_Buffer_control),
        &message_buffering_required ) ) 
    return false;

  /*
   *  Attempt to allocate the message memory
   */
  the_message_queue->message_buffers = (CORE_message_queue_Buffer *)
     _Workspace_Allocate( message_buffering_required );

  if (the_message_queue->message_buffers == 0)
    return false;

  /*
   *  Initialize the pool of inactive messages, pending messages,
   *  and set of waiting threads.
   */
  _Chain_Initialize (
    &the_message_queue->Inactive_messages,
    the_message_queue->message_buffers,
    (size_t) maximum_pending_messages,
    allocated_message_size + sizeof( CORE_message_queue_Buffer_control )
  );

  _Chain_Initialize_empty( &the_message_queue->Pending_messages );

  _Thread_queue_Initialize(
    &the_message_queue->Wait_queue,
    _CORE_message_queue_Is_priority( the_message_queue_attributes ) ?
       THREAD_QUEUE_DISCIPLINE_PRIORITY : THREAD_QUEUE_DISCIPLINE_FIFO,
    STATES_WAITING_FOR_MESSAGE,
    CORE_MESSAGE_QUEUE_STATUS_TIMEOUT
  );

  return true;
}
Пример #22
0
bool _Thread_Initialize(
    Objects_Information                  *information,
    Thread_Control                       *the_thread,
    void                                 *stack_area,
    size_t                                stack_size,
    bool                                  is_fp,
    Priority_Control                      priority,
    bool                                  is_preemptible,
    Thread_CPU_budget_algorithms          budget_algorithm,
    Thread_CPU_budget_algorithm_callout   budget_callout,
    uint32_t                              isr_level,
    Objects_Name                          name
)
{
    size_t               actual_stack_size = 0;
    void                *stack = NULL;
#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
    void              *fp_area;
#endif
    void                *sched = NULL;
    void                *extensions_area;
    bool                 extension_status;
    int                  i;

#if defined( RTEMS_SMP )
    if ( rtems_configuration_is_smp_enabled() && !is_preemptible ) {
        return false;
    }
#endif

    /*
     *  Initialize the Ada self pointer
     */
#if __RTEMS_ADA__
    the_thread->rtems_ada_self = NULL;
#endif

    /*
     *  Zero out all the allocated memory fields
     */
    for ( i=0 ; i <= THREAD_API_LAST ; i++ )
        the_thread->API_Extensions[i] = NULL;

    extensions_area = NULL;
    the_thread->libc_reent = NULL;

#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
    fp_area = NULL;
#endif

    /*
     *  Allocate and Initialize the stack for this thread.
     */
#if !defined(RTEMS_SCORE_THREAD_ENABLE_USER_PROVIDED_STACK_VIA_API)
    actual_stack_size = _Thread_Stack_Allocate( the_thread, stack_size );
    if ( !actual_stack_size || actual_stack_size < stack_size )
        return false;                     /* stack allocation failed */

    stack = the_thread->Start.stack;
#else
    if ( !stack_area ) {
        actual_stack_size = _Thread_Stack_Allocate( the_thread, stack_size );
        if ( !actual_stack_size || actual_stack_size < stack_size )
            return false;                     /* stack allocation failed */

        stack = the_thread->Start.stack;
        the_thread->Start.core_allocated_stack = true;
    } else {
        stack = stack_area;
        actual_stack_size = stack_size;
        the_thread->Start.core_allocated_stack = false;
    }
#endif

    _Stack_Initialize(
        &the_thread->Start.Initial_stack,
        stack,
        actual_stack_size
    );

    /*
     *  Allocate the floating point area for this thread
     */
#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
    if ( is_fp ) {
        fp_area = _Workspace_Allocate( CONTEXT_FP_SIZE );
        if ( !fp_area )
            goto failed;
        fp_area = _Context_Fp_start( fp_area, 0 );
    }
    the_thread->fp_context       = fp_area;
    the_thread->Start.fp_context = fp_area;
#endif

    /*
     *  Initialize the thread timer
     */
    _Watchdog_Initialize( &the_thread->Timer, NULL, 0, NULL );

#ifdef __RTEMS_STRICT_ORDER_MUTEX__
    /* Initialize the head of chain of held mutexes */
    _Chain_Initialize_empty(&the_thread->lock_mutex);
#endif

    /*
     *  Allocate the extensions area for this thread
     */
    if ( _Thread_Maximum_extensions ) {
        extensions_area = _Workspace_Allocate(
                              (_Thread_Maximum_extensions + 1) * sizeof( void * )
                          );
        if ( !extensions_area )
            goto failed;
    }
    the_thread->extensions = (void **) extensions_area;

    /*
     * Clear the extensions area so extension users can determine
     * if they are linked to the thread. An extension user may
     * create the extension long after tasks have been created
     * so they cannot rely on the thread create user extension
     * call.
     */
    if ( the_thread->extensions ) {
        for ( i = 0; i <= _Thread_Maximum_extensions ; i++ )
            the_thread->extensions[i] = NULL;
    }

    /*
     *  General initialization
     */

    the_thread->Start.is_preemptible   = is_preemptible;
    the_thread->Start.budget_algorithm = budget_algorithm;
    the_thread->Start.budget_callout   = budget_callout;

    switch ( budget_algorithm ) {
    case THREAD_CPU_BUDGET_ALGORITHM_NONE:
    case THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE:
        break;
#if defined(RTEMS_SCORE_THREAD_ENABLE_EXHAUST_TIMESLICE)
    case THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE:
        the_thread->cpu_time_budget = _Thread_Ticks_per_timeslice;
        break;
#endif
#if defined(RTEMS_SCORE_THREAD_ENABLE_SCHEDULER_CALLOUT)
    case THREAD_CPU_BUDGET_ALGORITHM_CALLOUT:
        break;
#endif
    }

    the_thread->Start.isr_level         = isr_level;

#if defined(RTEMS_SMP)
    the_thread->is_scheduled            = false;
    the_thread->is_executing            = false;

    /* Initialize the cpu field for the non-SMP schedulers */
    the_thread->cpu                     = _Per_CPU_Get_by_index( 0 );
#endif

    the_thread->current_state           = STATES_DORMANT;
    the_thread->Wait.queue              = NULL;
    the_thread->resource_count          = 0;
    the_thread->real_priority           = priority;
    the_thread->Start.initial_priority  = priority;
    sched =_Scheduler_Allocate( the_thread );
    if ( !sched )
        goto failed;
    _Thread_Set_priority( the_thread, priority );

    /*
     *  Initialize the CPU usage statistics
     */
#ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
    _Timestamp_Set_to_zero( &the_thread->cpu_time_used );
#else
    the_thread->cpu_time_used = 0;
#endif

    /*
     *  Open the object
     */
    _Objects_Open( information, &the_thread->Object, name );

    /*
     *  We assume the Allocator Mutex is locked and dispatching is
     *  enabled when we get here.  We want to be able to run the
     *  user extensions with dispatching enabled.  The Allocator
     *  Mutex provides sufficient protection to let the user extensions
     *  run safely.
     */
    extension_status = _User_extensions_Thread_create( the_thread );
    if ( extension_status )
        return true;

failed:
    _Workspace_Free( the_thread->libc_reent );

    for ( i=0 ; i <= THREAD_API_LAST ; i++ )
        _Workspace_Free( the_thread->API_Extensions[i] );

    _Workspace_Free( extensions_area );

#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
    _Workspace_Free( fp_area );
#endif

    _Workspace_Free( sched );

    _Thread_Stack_Free( the_thread );
    return false;
}
Пример #23
0
/**
 *  @brief rtems_timer_initiate_server
 *
 *  This directive creates and starts the server for task-based timers.
 *  It must be invoked before any task-based timers can be initiated.
 *
 *  @param[in] priority is the timer server priority
 *  @param[in] stack_size is the stack size in bytes
 *  @param[in] attribute_set is the timer server attributes
 *
 *  @return This method returns RTEMS_SUCCESSFUL if successful and an
 *          error code otherwise.
 */
rtems_status_code rtems_timer_initiate_server(
  uint32_t             priority,
  uint32_t             stack_size,
  rtems_attribute      attribute_set
)
{
  rtems_id              id;
  rtems_status_code     status;
  rtems_task_priority   _priority;
  static bool           initialized = false;
  bool                  tmpInitialized;
  Timer_server_Control *ts = &_Timer_server_Default;

  /*
   *  Make sure the requested priority is valid.  The if is
   *  structured so we check it is invalid before looking for
   *  a specific invalid value as the default.
   */
  _priority = priority;
  if ( !_RTEMS_tasks_Priority_is_valid( priority ) ) {
    if ( priority != RTEMS_TIMER_SERVER_DEFAULT_PRIORITY )
      return RTEMS_INVALID_PRIORITY;
    _priority = 0;
  }

  /*
   *  Just to make sure this is only called once.
   */
  _Thread_Disable_dispatch();
    tmpInitialized  = initialized;
    initialized = true;
  _Thread_Enable_dispatch();

  if ( tmpInitialized )
    return RTEMS_INCORRECT_STATE;

  /*
   *  Create the Timer Server with the name the name of "TIME".  The attribute
   *  RTEMS_SYSTEM_TASK allows us to set a priority to 0 which will makes it
   *  higher than any other task in the system.  It can be viewed as a low
   *  priority interrupt.  It is also always NO_PREEMPT so it looks like
   *  an interrupt to other tasks.
   *
   *  We allow the user to override the default priority because the Timer
   *  Server can invoke TSRs which must adhere to language run-time or
   *  other library rules.  For example, if using a TSR written in Ada the
   *  Server should run at the same priority as the priority Ada task.
   *  Otherwise, the priority ceiling for the mutex used to protect the
   *  GNAT run-time is violated.
   */
  status = rtems_task_create(
    _Objects_Build_name('T','I','M','E'),           /* "TIME" */
    _priority,            /* create with priority 1 since 0 is illegal */
    stack_size,           /* let user specify stack size */
    RTEMS_NO_PREEMPT,     /* no preempt is like an interrupt */
                          /* user may want floating point but we need */
                          /*   system task specified for 0 priority */
    attribute_set | RTEMS_SYSTEM_TASK,
    &id                   /* get the id back */
  );
  if (status) {
    initialized = false;
    return status;
  }

  /*
   *  Do all the data structure initialization before starting the
   *  Timer Server so we do not have to have a critical section.
   */

  /*
   *  We work with the TCB pointer, not the ID, so we need to convert
   *  to a TCB pointer from here out.
   */
  ts->thread = (Thread_Control *)_Objects_Get_local_object(
    &_RTEMS_tasks_Information,
    _Objects_Get_index(id)
  );

  /*
   *  Initialize the timer lists that the server will manage.
   */
  _Chain_Initialize_empty( &ts->Interval_watchdogs.Chain );
  _Chain_Initialize_empty( &ts->TOD_watchdogs.Chain );

  /*
   *  Initialize the timers that will be used to control when the
   *  Timer Server wakes up and services the task-based timers.
   */
  _Watchdog_Initialize(
    &ts->Interval_watchdogs.System_watchdog,
    _Thread_Delay_ended,
    id,
    NULL
  );
  _Watchdog_Initialize(
    &ts->TOD_watchdogs.System_watchdog,
    _Thread_Delay_ended,
    id,
    NULL
  );

  /*
   *  Initialize the pointer to the timer schedule method so applications that
   *  do not use the Timer Server do not have to pull it in.
   */
  ts->schedule_operation = _Timer_server_Schedule_operation_method;

  ts->Interval_watchdogs.last_snapshot = _Watchdog_Ticks_since_boot;
  ts->TOD_watchdogs.last_snapshot = (Watchdog_Interval) _TOD_Seconds_since_epoch();

  ts->insert_chain = NULL;
  ts->active = false;

  /*
   * The default timer server is now available.
   */
  _Timer_server = ts;

  /*
   *  Start the timer server
   */
  status = rtems_task_start(
    id,
    _Timer_server_Body,
    (rtems_task_argument) ts
  );

  #if defined(RTEMS_DEBUG)
    /*
     *  One would expect a call to rtems_task_delete() here to clean up
     *  but there is actually no way (in normal circumstances) that the
     *  start can fail.  The id and starting address are known to be
     *  be good.  If this service fails, something is weirdly wrong on the
     *  target such as a stray write in an ISR or incorrect memory layout.
     */
    if (status) {
      initialized = false;
    }
  #endif

  return status;
}
Пример #24
0
Thread_blocking_operation_States _Thread_queue_Enqueue_priority (
    Thread_queue_Control *the_thread_queue,
    Thread_Control       *the_thread,
    ISR_Level            *level_p
)
{
    Priority_Control     search_priority;
    Thread_Control      *search_thread;
    ISR_Level            level;
    Chain_Control       *header;
    uint32_t             header_index;
    Chain_Node          *the_node;
    Chain_Node          *next_node;
    Chain_Node          *previous_node;
    Chain_Node          *search_node;
    Priority_Control     priority;
    States_Control       block_state;

    _Chain_Initialize_empty( &the_thread->Wait.Block2n );

    priority     = the_thread->current_priority;
    header_index = _Thread_queue_Header_number( priority );
    header       = &the_thread_queue->Queues.Priority[ header_index ];
    block_state  = the_thread_queue->state;

    if ( _Thread_queue_Is_reverse_search( priority ) )
        goto restart_reverse_search;

restart_forward_search:
    search_priority = PRIORITY_MINIMUM - 1;
    _ISR_Disable( level );
    search_thread = (Thread_Control *) header->first;
    while ( !_Chain_Is_tail( header, (Chain_Node *)search_thread ) ) {
        search_priority = search_thread->current_priority;
        if ( priority <= search_priority )
            break;

#if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE )
        search_thread = (Thread_Control *) search_thread->Object.Node.next;
        if ( _Chain_Is_tail( header, (Chain_Node *)search_thread ) )
            break;
        search_priority = search_thread->current_priority;
        if ( priority <= search_priority )
            break;
#endif
        _ISR_Flash( level );
        if ( !_States_Are_set( search_thread->current_state, block_state) ) {
            _ISR_Enable( level );
            goto restart_forward_search;
        }
        search_thread =
            (Thread_Control *)search_thread->Object.Node.next;
    }

    if ( the_thread_queue->sync_state !=
            THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED )
        goto synchronize;

    the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;

    if ( priority == search_priority )
        goto equal_priority;

    search_node   = (Chain_Node *) search_thread;
    previous_node = search_node->previous;
    the_node      = (Chain_Node *) the_thread;

    the_node->next         = search_node;
    the_node->previous     = previous_node;
    previous_node->next    = the_node;
    search_node->previous  = the_node;
    the_thread->Wait.queue = the_thread_queue;
    _ISR_Enable( level );
    return THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;

restart_reverse_search:
    search_priority     = PRIORITY_MAXIMUM + 1;

    _ISR_Disable( level );
    search_thread = (Thread_Control *) header->last;
    while ( !_Chain_Is_head( header, (Chain_Node *)search_thread ) ) {
        search_priority = search_thread->current_priority;
        if ( priority >= search_priority )
            break;
#if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE )
        search_thread = (Thread_Control *) search_thread->Object.Node.previous;
        if ( _Chain_Is_head( header, (Chain_Node *)search_thread ) )
            break;
        search_priority = search_thread->current_priority;
        if ( priority >= search_priority )
            break;
#endif
        _ISR_Flash( level );
        if ( !_States_Are_set( search_thread->current_state, block_state) ) {
            _ISR_Enable( level );
            goto restart_reverse_search;
        }
        search_thread = (Thread_Control *)
                        search_thread->Object.Node.previous;
    }

    if ( the_thread_queue->sync_state !=
            THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED )
        goto synchronize;

    the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;

    if ( priority == search_priority )
        goto equal_priority;

    search_node = (Chain_Node *) search_thread;
    next_node   = search_node->next;
    the_node    = (Chain_Node *) the_thread;

    the_node->next          = next_node;
    the_node->previous      = search_node;
    search_node->next       = the_node;
    next_node->previous    = the_node;
    the_thread->Wait.queue = the_thread_queue;
    _ISR_Enable( level );
    return THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;

equal_priority:               /* add at end of priority group */
    search_node   = _Chain_Tail( &search_thread->Wait.Block2n );
    previous_node = search_node->previous;
    the_node      = (Chain_Node *) the_thread;

    the_node->next         = search_node;
    the_node->previous     = previous_node;
    previous_node->next    = the_node;
    search_node->previous  = the_node;
    the_thread->Wait.queue = the_thread_queue;
    _ISR_Enable( level );
    return THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;

synchronize:
    /*
     *  An interrupt completed the thread's blocking request.
     *  For example, the blocking thread could have been given
     *  the mutex by an ISR or timed out.
     *
     *  WARNING! Returning with interrupts disabled!
     */
    *level_p = level;
    return the_thread_queue->sync_state;
}
bool _Thread_Initialize(
  Objects_Information                  *information,
  Thread_Control                       *the_thread,
  const Scheduler_Control              *scheduler,
  void                                 *stack_area,
  size_t                                stack_size,
  bool                                  is_fp,
  Priority_Control                      priority,
  bool                                  is_preemptible,
  Thread_CPU_budget_algorithms          budget_algorithm,
  Thread_CPU_budget_algorithm_callout   budget_callout,
  uint32_t                              isr_level,
  Objects_Name                          name
)
{
  uintptr_t                tls_size = _TLS_Get_size();
  size_t                   actual_stack_size = 0;
  void                    *stack = NULL;
  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
    void                  *fp_area = NULL;
  #endif
  bool                     extension_status;
  size_t                   i;
  bool                     scheduler_node_initialized = false;
  Per_CPU_Control         *cpu = _Per_CPU_Get_by_index( 0 );

#if defined( RTEMS_SMP )
  if ( rtems_configuration_is_smp_enabled() && !is_preemptible ) {
    return false;
  }
#endif

  for ( i = 0 ; i < _Thread_Control_add_on_count ; ++i ) {
    const Thread_Control_add_on *add_on = &_Thread_Control_add_ons[ i ];

    *(void **) ( (char *) the_thread + add_on->destination_offset ) =
      (char *) the_thread + add_on->source_offset;
  }

  /*
   *  Initialize the Ada self pointer
   */
  #if __RTEMS_ADA__
    the_thread->rtems_ada_self = NULL;
  #endif

  the_thread->Start.tls_area = NULL;

  /*
   *  Allocate and Initialize the stack for this thread.
   */
  #if !defined(RTEMS_SCORE_THREAD_ENABLE_USER_PROVIDED_STACK_VIA_API)
    actual_stack_size = _Thread_Stack_Allocate( the_thread, stack_size );
    if ( !actual_stack_size || actual_stack_size < stack_size )
      return false;                     /* stack allocation failed */

    stack = the_thread->Start.stack;
  #else
    if ( !stack_area ) {
      actual_stack_size = _Thread_Stack_Allocate( the_thread, stack_size );
      if ( !actual_stack_size || actual_stack_size < stack_size )
        return false;                     /* stack allocation failed */

      stack = the_thread->Start.stack;
      the_thread->Start.core_allocated_stack = true;
    } else {
      stack = stack_area;
      actual_stack_size = stack_size;
      the_thread->Start.core_allocated_stack = false;
    }
  #endif

  _Stack_Initialize(
     &the_thread->Start.Initial_stack,
     stack,
     actual_stack_size
  );

  /* Thread-local storage (TLS) area allocation */
  if ( tls_size > 0 ) {
    uintptr_t tls_align = _TLS_Heap_align_up( (uintptr_t) _TLS_Alignment );
    uintptr_t tls_alloc = _TLS_Get_allocation_size( tls_size, tls_align );

    the_thread->Start.tls_area =
      _Workspace_Allocate_aligned( tls_alloc, tls_align );

    if ( the_thread->Start.tls_area == NULL ) {
      goto failed;
    }
  }

  /*
   *  Allocate the floating point area for this thread
   */
  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
    if ( is_fp ) {
      fp_area = _Workspace_Allocate( CONTEXT_FP_SIZE );
      if ( !fp_area )
        goto failed;
      fp_area = _Context_Fp_start( fp_area, 0 );
    }
    the_thread->fp_context       = fp_area;
    the_thread->Start.fp_context = fp_area;
  #endif

  /*
   *  Initialize the thread timer
   */
  _Watchdog_Initialize( &the_thread->Timer, NULL, 0, NULL );

  #ifdef __RTEMS_STRICT_ORDER_MUTEX__
    /* Initialize the head of chain of held mutexes */
    _Chain_Initialize_empty(&the_thread->lock_mutex);
  #endif

  /*
   * Clear the extensions area so extension users can determine
   * if they are linked to the thread. An extension user may
   * create the extension long after tasks have been created
   * so they cannot rely on the thread create user extension
   * call.  The object index starts with one, so the first extension context is
   * unused.
   */
  for ( i = 1 ; i <= rtems_configuration_get_maximum_extensions() ; ++i )
    the_thread->extensions[ i ] = NULL;

  /*
   *  General initialization
   */

  the_thread->Start.isr_level        = isr_level;
  the_thread->Start.is_preemptible   = is_preemptible;
  the_thread->Start.budget_algorithm = budget_algorithm;
  the_thread->Start.budget_callout   = budget_callout;

  switch ( budget_algorithm ) {
    case THREAD_CPU_BUDGET_ALGORITHM_NONE:
    case THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE:
      break;
    #if defined(RTEMS_SCORE_THREAD_ENABLE_EXHAUST_TIMESLICE)
      case THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE:
        the_thread->cpu_time_budget =
          rtems_configuration_get_ticks_per_timeslice();
        break;
    #endif
    #if defined(RTEMS_SCORE_THREAD_ENABLE_SCHEDULER_CALLOUT)
      case THREAD_CPU_BUDGET_ALGORITHM_CALLOUT:
	break;
    #endif
  }

#if defined(RTEMS_SMP)
  the_thread->Scheduler.state = THREAD_SCHEDULER_BLOCKED;
  the_thread->Scheduler.own_control = scheduler;
  the_thread->Scheduler.control = scheduler;
  the_thread->Scheduler.own_node = the_thread->Scheduler.node;
  _Resource_Node_initialize( &the_thread->Resource_node );
  _CPU_Context_Set_is_executing( &the_thread->Registers, false );
#endif

  _Thread_Debug_set_real_processor( the_thread, cpu );

  /* Initialize the CPU for the non-SMP schedulers */
  _Thread_Set_CPU( the_thread, cpu );

  the_thread->current_state           = STATES_DORMANT;
  the_thread->Wait.queue              = NULL;
  the_thread->resource_count          = 0;
  the_thread->real_priority           = priority;
  the_thread->Start.initial_priority  = priority;

  _Scheduler_Node_initialize( scheduler, the_thread );
  scheduler_node_initialized = true;

  _Thread_Set_priority( the_thread, priority );

  /*
   *  Initialize the CPU usage statistics
   */
  #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
    _Timestamp_Set_to_zero( &the_thread->cpu_time_used );
  #else
    the_thread->cpu_time_used = 0;
  #endif

  /*
   * initialize thread's key vaule node chain
   */
  _Chain_Initialize_empty( &the_thread->Key_Chain );

  _Thread_Action_control_initialize( &the_thread->Post_switch_actions );

  _Thread_Action_initialize(
    &the_thread->Life.Action,
    _Thread_Life_action_handler
  );
  the_thread->Life.state = THREAD_LIFE_NORMAL;
  the_thread->Life.terminator = NULL;

  /*
   *  Open the object
   */
  _Objects_Open( information, &the_thread->Object, name );

  /*
   *  We assume the Allocator Mutex is locked and dispatching is
   *  enabled when we get here.  We want to be able to run the
   *  user extensions with dispatching enabled.  The Allocator
   *  Mutex provides sufficient protection to let the user extensions
   *  run safely.
   */
  extension_status = _User_extensions_Thread_create( the_thread );
  if ( extension_status )
    return true;

failed:

  if ( scheduler_node_initialized ) {
    _Scheduler_Node_destroy( scheduler, the_thread );
  }

  _Workspace_Free( the_thread->Start.tls_area );

  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
    _Workspace_Free( fp_area );
  #endif

   _Thread_Stack_Free( the_thread );
  return false;
}
Пример #26
0
/* fat_init_volume_info --
 *     Get inforamtion about volume on which filesystem is mounted on
 *
 * PARAMETERS:
 *     mt_entry - mount table entry
 *
 * RETURNS:
 *     RC_OK on success, or -1 if error occured
 *     and errno set appropriately
 */
int
fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry)
{
    int                 rc = RC_OK;
    fat_fs_info_t      *fs_info = mt_entry->fs_info;
    register fat_vol_t *vol = &fs_info->vol;
    uint32_t            data_secs = 0;
    char                boot_rec[FAT_MAX_BPB_SIZE];
    char                fs_info_sector[FAT_USEFUL_INFO_SIZE];
    ssize_t             ret = 0;
    int                 fd;
    struct stat         stat_buf;
    int                 i = 0;

    rc = stat(mt_entry->dev, &stat_buf);
    if (rc == -1)
        return rc;

    /* rtmes feature: no block devices, all are character devices */
    if (!S_ISCHR(stat_buf.st_mode))
        set_errno_and_return_minus_one(ENOTBLK);

    /* check that  device is registred as block device and lock it */
    vol->dd = rtems_disk_lookup(stat_buf.st_dev);
    if (vol->dd == NULL)
        set_errno_and_return_minus_one(ENOTBLK);

    vol->dev = stat_buf.st_dev;

    fd = open(mt_entry->dev, O_RDONLY);
    if (fd == -1)
    {
        rtems_disk_release(vol->dd);
        return -1;
    }

    ret = read(fd, (void *)boot_rec, FAT_MAX_BPB_SIZE);
    if ( ret != FAT_MAX_BPB_SIZE )
    {
        close(fd);
        rtems_disk_release(vol->dd);
        set_errno_and_return_minus_one( EIO );
    }
    close(fd);

    vol->bps = FAT_GET_BR_BYTES_PER_SECTOR(boot_rec);
 
    if ( (vol->bps != 512)  && 
         (vol->bps != 1024) && 
         (vol->bps != 2048) &&
         (vol->bps != 4096))
    {
        rtems_disk_release(vol->dd);
        set_errno_and_return_minus_one( EINVAL );
    }

    for (vol->sec_mul = 0, i = (vol->bps >> FAT_SECTOR512_BITS); (i & 1) == 0;
         i >>= 1, vol->sec_mul++);
    for (vol->sec_log2 = 0, i = vol->bps; (i & 1) == 0;
         i >>= 1, vol->sec_log2++);

    vol->spc = FAT_GET_BR_SECTORS_PER_CLUSTER(boot_rec);
    /*
     * "sectors per cluster" of zero is invalid
     * (and would hang the following loop)
     */
    if (vol->spc == 0)
    {
        rtems_disk_release(vol->dd);
        set_errno_and_return_minus_one(EINVAL);
    }

    for (vol->spc_log2 = 0, i = vol->spc; (i & 1) == 0;
         i >>= 1, vol->spc_log2++);

    /*
     * "bytes per cluster" value greater than 32K is invalid
     */
    if ((vol->bpc = vol->bps << vol->spc_log2) > MS_BYTES_PER_CLUSTER_LIMIT)
    {
        rtems_disk_release(vol->dd);
        set_errno_and_return_minus_one(EINVAL);
    }

    for (vol->bpc_log2 = 0, i = vol->bpc; (i & 1) == 0;
         i >>= 1, vol->bpc_log2++);

    vol->fats = FAT_GET_BR_FAT_NUM(boot_rec);
    vol->fat_loc = FAT_GET_BR_RESERVED_SECTORS_NUM(boot_rec);

    vol->rdir_entrs = FAT_GET_BR_FILES_PER_ROOT_DIR(boot_rec);
    
    /* calculate the count of sectors occupied by the root directory */
    vol->rdir_secs = ((vol->rdir_entrs * FAT_DIRENTRY_SIZE) + (vol->bps - 1)) /
                     vol->bps;

    vol->rdir_size = vol->rdir_secs << vol->sec_log2;

    if ( (FAT_GET_BR_SECTORS_PER_FAT(boot_rec)) != 0)
        vol->fat_length = FAT_GET_BR_SECTORS_PER_FAT(boot_rec);
    else
        vol->fat_length = FAT_GET_BR_SECTORS_PER_FAT32(boot_rec);
  
    vol->data_fsec = vol->fat_loc + vol->fats * vol->fat_length + 
                     vol->rdir_secs;

    /* for  FAT12/16 root dir starts at(sector) */
    vol->rdir_loc = vol->fat_loc + vol->fats * vol->fat_length;
  
    if ( (FAT_GET_BR_TOTAL_SECTORS_NUM16(boot_rec)) != 0)
        vol->tot_secs = FAT_GET_BR_TOTAL_SECTORS_NUM16(boot_rec);
    else
        vol->tot_secs = FAT_GET_BR_TOTAL_SECTORS_NUM32(boot_rec);
  
    data_secs = vol->tot_secs - vol->data_fsec;

    vol->data_cls = data_secs / vol->spc;

    /* determine FAT type at least */
    if ( vol->data_cls < FAT_FAT12_MAX_CLN)
    {
        vol->type = FAT_FAT12;
        vol->mask = FAT_FAT12_MASK;
        vol->eoc_val = FAT_FAT12_EOC;
    }
    else
    {
        if ( vol->data_cls < FAT_FAT16_MAX_CLN)
        {
            vol->type = FAT_FAT16;
            vol->mask = FAT_FAT16_MASK;
            vol->eoc_val = FAT_FAT16_EOC;
        }
        else
        {
            vol->type = FAT_FAT32;
            vol->mask = FAT_FAT32_MASK;
            vol->eoc_val = FAT_FAT32_EOC;
        }
    }

    if (vol->type == FAT_FAT32)
    {
        vol->rdir_cl = FAT_GET_BR_FAT32_ROOT_CLUSTER(boot_rec);
      
        vol->mirror = FAT_GET_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_MIRROR;
        if (vol->mirror)
            vol->afat = FAT_GET_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_FAT_NUM;
        else
            vol->afat = 0;

        vol->info_sec = FAT_GET_BR_FAT32_FS_INFO_SECTOR(boot_rec);
        if( vol->info_sec == 0 )
        {
            rtems_disk_release(vol->dd);
            set_errno_and_return_minus_one( EINVAL );
        }
        else
        {
            ret = _fat_block_read(mt_entry, vol->info_sec , 0,
                                  FAT_FSI_LEADSIG_SIZE, fs_info_sector);
            if ( ret < 0 )
            {
                rtems_disk_release(vol->dd);
                return -1;
            }    
      
            if (FAT_GET_FSINFO_LEAD_SIGNATURE(fs_info_sector) != 
                FAT_FSINFO_LEAD_SIGNATURE_VALUE)
            {
                rtems_disk_release(vol->dd);
                set_errno_and_return_minus_one( EINVAL );
            }
            else
            {
                ret = _fat_block_read(mt_entry, vol->info_sec , FAT_FSI_INFO,
                                      FAT_USEFUL_INFO_SIZE, fs_info_sector);
                if ( ret < 0 )
                {
                    rtems_disk_release(vol->dd);
                    return -1;
                }    
                    
                vol->free_cls = FAT_GET_FSINFO_FREE_CLUSTER_COUNT(fs_info_sector);
                vol->next_cl = FAT_GET_FSINFO_NEXT_FREE_CLUSTER(fs_info_sector);
                rc = fat_fat32_update_fsinfo_sector(mt_entry, 0xFFFFFFFF, 
                                                    0xFFFFFFFF);
                if ( rc != RC_OK )
                {
                    rtems_disk_release(vol->dd);
                    return rc;
                }
            }
        }
    }
    else
    {
        vol->rdir_cl = 0;
        vol->mirror = 0;
        vol->afat = 0;
        vol->free_cls = 0xFFFFFFFF;
        vol->next_cl = 0xFFFFFFFF;
    }
    vol->afat_loc = vol->fat_loc + vol->fat_length * vol->afat;

    /* set up collection of fat-files fd */
    fs_info->vhash = calloc(FAT_HASH_SIZE, sizeof(Chain_Control));
    if ( fs_info->vhash == NULL )
    {
        rtems_disk_release(vol->dd);
        set_errno_and_return_minus_one( ENOMEM );
    }

    for (i = 0; i < FAT_HASH_SIZE; i++)
        _Chain_Initialize_empty(fs_info->vhash + i);

    fs_info->rhash = calloc(FAT_HASH_SIZE, sizeof(Chain_Control));
    if ( fs_info->rhash == NULL )
    {
        rtems_disk_release(vol->dd);
        free(fs_info->vhash);
        set_errno_and_return_minus_one( ENOMEM );
    }
    for (i = 0; i < FAT_HASH_SIZE; i++)
        _Chain_Initialize_empty(fs_info->rhash + i);

    fs_info->uino_pool_size = FAT_UINO_POOL_INIT_SIZE;
    fs_info->uino_base = (vol->tot_secs << vol->sec_mul) << 4;
    fs_info->index = 0;
    fs_info->uino = (char *)calloc(fs_info->uino_pool_size, sizeof(char));
    if ( fs_info->uino == NULL )
    {
        rtems_disk_release(vol->dd);
        free(fs_info->vhash);
        free(fs_info->rhash);
        set_errno_and_return_minus_one( ENOMEM );
    }
    fs_info->sec_buf = (uint8_t *)calloc(vol->bps, sizeof(uint8_t));
    if (fs_info->sec_buf == NULL)
    {
        rtems_disk_release(vol->dd);
        free(fs_info->vhash);
        free(fs_info->rhash);
        free(fs_info->uino);
        set_errno_and_return_minus_one( ENOMEM );
    }

    return RC_OK;
}
Пример #27
0
static int _Condition_Wake( struct _Condition_Control *_condition, int count )
{
  Condition_Control  *condition;
  ISR_lock_Context    lock_context;
  Thread_queue_Heads *heads;
  Chain_Control       unblock;
  Chain_Node         *node;
  Chain_Node         *tail;
  int                 woken;

  condition = _Condition_Get( _condition );
  _ISR_lock_ISR_disable( &lock_context );
  _Condition_Queue_acquire_critical( condition, &lock_context );

  /*
   * In common uses cases of condition variables there are normally no threads
   * on the queue, so check this condition early.
   */
  heads = condition->Queue.Queue.heads;
  if ( __predict_true( heads == NULL ) ) {
    _Condition_Queue_release( condition, &lock_context );

    return 0;
  }

  woken = 0;
  _Chain_Initialize_empty( &unblock );
  while ( count > 0 && heads != NULL ) {
    const Thread_queue_Operations *operations;
    Thread_Control                *first;
    bool                           do_unblock;

    operations = CONDITION_TQ_OPERATIONS;
    first = ( *operations->first )( heads );

    do_unblock = _Thread_queue_Extract_locked(
      &condition->Queue.Queue,
      operations,
      first
    );
    if (do_unblock) {
      _Chain_Append_unprotected( &unblock, &first->Wait.Node.Chain );
    }

    ++woken;
    --count;
    heads = condition->Queue.Queue.heads;
  }

  node = _Chain_First( &unblock );
  tail = _Chain_Tail( &unblock );
  if ( node != tail ) {
    Per_CPU_Control *cpu_self;

    cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
    _Condition_Queue_release( condition, &lock_context );

    do {
      Thread_Control *thread;
      Chain_Node     *next;

      next = _Chain_Next( node );
      thread = THREAD_CHAIN_NODE_TO_THREAD( node );
      _Watchdog_Remove_ticks( &thread->Timer );
      _Thread_Unblock( thread );

      node = next;
    } while ( node != tail );

    _Thread_Dispatch_enable( cpu_self );
  } else {
    _Condition_Queue_release( condition, &lock_context );
  }

  return woken;
}
Пример #28
0
void _API_extensions_Initialization( void )
{
 _Chain_Initialize_empty( &_API_extensions_List );
}
Пример #29
0
static void _Thread_queue_FIFO_do_initialize(
  Thread_queue_Heads *heads
)
{
  _Chain_Initialize_empty( &heads->Heads.Fifo );
}
Пример #30
0
static
#endif
bool _Thread_queue_Path_acquire_critical(
    Thread_queue_Queue   *queue,
    Thread_Control       *the_thread,
    Thread_queue_Context *queue_context
)
{
    Thread_Control     *owner;
#if defined(RTEMS_SMP)
    Thread_queue_Link  *link;
    Thread_queue_Queue *target;

    /*
     * For an overview please look at the non-SMP part below.  We basically do
     * the same on SMP configurations.  The fact that we may have more than one
     * executing thread and each thread queue has its own SMP lock makes the task
     * a bit more difficult.  We have to avoid deadlocks at SMP lock level, since
     * this would result in an unrecoverable deadlock of the overall system.
     */

    _Chain_Initialize_empty( &queue_context->Path.Links );

    owner = queue->owner;

    if ( owner == NULL ) {
        return true;
    }

    if ( owner == the_thread ) {
        return false;
    }

    _Chain_Initialize_node(
        &queue_context->Path.Start.Lock_context.Wait.Gate.Node
    );
    link = &queue_context->Path.Start;
    _RBTree_Initialize_node( &link->Registry_node );
    _Chain_Initialize_node( &link->Path_node );

    do {
        _Chain_Append_unprotected( &queue_context->Path.Links, &link->Path_node );
        link->owner = owner;

        _Thread_Wait_acquire_default_critical(
            owner,
            &link->Lock_context.Lock_context
        );

        target = owner->Wait.queue;
        link->Lock_context.Wait.queue = target;

        if ( target != NULL ) {
            if ( _Thread_queue_Link_add( link, queue, target ) ) {
                _Thread_queue_Gate_add(
                    &owner->Wait.Lock.Pending_requests,
                    &link->Lock_context.Wait.Gate
                );
                _Thread_Wait_release_default_critical(
                    owner,
                    &link->Lock_context.Lock_context
                );
                _Thread_Wait_acquire_queue_critical( target, &link->Lock_context );

                if ( link->Lock_context.Wait.queue == NULL ) {
                    _Thread_queue_Link_remove( link );
                    _Thread_Wait_release_queue_critical( target, &link->Lock_context );
                    _Thread_Wait_acquire_default_critical(
                        owner,
                        &link->Lock_context.Lock_context
                    );
                    _Thread_Wait_remove_request_locked( owner, &link->Lock_context );
                    _Assert( owner->Wait.queue == NULL );
                    return true;
                }
            } else {
                link->Lock_context.Wait.queue = NULL;
                _Thread_queue_Path_append_deadlock_thread( owner, queue_context );
                return false;
            }
        } else {
            return true;
        }

        link = &owner->Wait.Link;
        queue = target;
        owner = queue->owner;
    } while ( owner != NULL );
#else
    do {
        owner = queue->owner;

        if ( owner == NULL ) {
            return true;
        }

        if ( owner == the_thread ) {
            return false;
        }

        queue = owner->Wait.queue;
    } while ( queue != NULL );
#endif

    return true;
}