예제 #1
0
파일: threadstart.c 프로젝트: gedare/rtems
bool _Thread_Start(
  Thread_Control                 *the_thread,
  const Thread_Entry_information *entry,
  ISR_lock_Context               *lock_context
)
{
  Per_CPU_Control *cpu_self;

  _Thread_State_acquire_critical( the_thread, lock_context );

  if ( !_States_Is_dormant( the_thread->current_state ) ) {
    _Thread_State_release( the_thread, lock_context );
    return false;
  }

  the_thread->Start.Entry = *entry;
  _Thread_Load_environment( the_thread );
  _Thread_Clear_state_locked( the_thread, STATES_ALL_SET );

  cpu_self = _Thread_Dispatch_disable_critical( lock_context );
  _Thread_State_release( the_thread, lock_context );

  _User_extensions_Thread_start( the_thread );

  _Thread_Dispatch_enable( cpu_self );
  return true;
}
예제 #2
0
static int _POSIX_Threads_Join( pthread_t thread, void **value_ptr )
{
  Thread_Control       *the_thread;
  Thread_queue_Context  queue_context;
  Per_CPU_Control      *cpu_self;
  Thread_Control       *executing;
  void                 *value;

  _Thread_queue_Context_initialize( &queue_context );
  _Thread_queue_Context_set_expected_level( &queue_context, 1 );
  the_thread = _Thread_Get( thread, &queue_context.Lock_context );

  if ( the_thread == NULL ) {
    return ESRCH;
  }

  cpu_self = _Per_CPU_Get();
  executing = _Per_CPU_Get_executing( cpu_self );

  if ( executing == the_thread ) {
    _ISR_lock_ISR_enable( &queue_context.Lock_context );
    return EDEADLK;
  }

  _Thread_State_acquire_critical( the_thread, &queue_context.Lock_context );

  if ( !_Thread_Is_joinable( the_thread ) ) {
    _Thread_State_release( the_thread, &queue_context.Lock_context );
    return EINVAL;
  }

  if ( _States_Is_waiting_for_join_at_exit( the_thread->current_state ) ) {
    value = the_thread->Life.exit_value;
    _Thread_Clear_state_locked( the_thread, STATES_WAITING_FOR_JOIN_AT_EXIT );
    _Thread_Dispatch_disable_with_CPU( cpu_self, &queue_context.Lock_context );
    _Thread_State_release( the_thread, &queue_context.Lock_context );
    _Thread_Dispatch_enable( cpu_self );
  } else {
    _Thread_Join(
      the_thread,
      STATES_INTERRUPTIBLE_BY_SIGNAL | STATES_WAITING_FOR_JOIN,
      executing,
      &queue_context
    );

    if ( _POSIX_Get_error_after_wait( executing ) != 0 ) {
      _Assert( _POSIX_Get_error_after_wait( executing ) == EINTR );
      return EINTR;
    }

    value = executing->Wait.return_argument;
  }

  if ( value_ptr != NULL ) {
    *value_ptr = value;
  }

  return 0;
}
rtems_status_code rtems_task_set_priority(
  rtems_id             id,
  rtems_task_priority  new_priority,
  rtems_task_priority *old_priority_p
)
{
  Thread_Control          *the_thread;
  ISR_lock_Context         lock_context;
  const Scheduler_Control *scheduler;
  Priority_Control         old_priority;
  rtems_status_code        status;

  if ( old_priority_p == NULL ) {
    return RTEMS_INVALID_ADDRESS;
  }

  the_thread = _Thread_Get( id, &lock_context );

  if ( the_thread == NULL ) {
#if defined(RTEMS_MULTIPROCESSING)
    return _RTEMS_tasks_MP_Set_priority( id, new_priority, old_priority_p );
#else
    return RTEMS_INVALID_ID;
#endif
  }

  if ( new_priority != RTEMS_CURRENT_PRIORITY ) {
    RTEMS_tasks_Set_priority_context  context;
    Per_CPU_Control                  *cpu_self;

    cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
    _ISR_lock_ISR_enable( &lock_context );

    context.new_priority = new_priority;
    _Thread_Change_priority(
      the_thread,
      0,
      &context,
      _RTEMS_tasks_Set_priority_filter,
      false
    );

    _Thread_Dispatch_enable( cpu_self );
    scheduler = context.scheduler;
    old_priority = context.old_priority;
    status = context.status;
  } else {
    _Thread_State_acquire_critical( the_thread, &lock_context );
    scheduler = _Scheduler_Get_own( the_thread );
    old_priority = _Thread_Get_priority( the_thread );
    _Thread_State_release( the_thread, &lock_context );
    status = RTEMS_SUCCESSFUL;
  }

  *old_priority_p = _RTEMS_Priority_From_core( scheduler, old_priority );
  return status;
}
예제 #4
0
rtems_status_code rtems_task_set_scheduler(
  rtems_id            task_id,
  rtems_id            scheduler_id,
  rtems_task_priority priority
)
{
  const Scheduler_Control *scheduler;
  Thread_Control          *the_thread;
  Thread_queue_Context     queue_context;
  ISR_lock_Context         state_context;
  Per_CPU_Control         *cpu_self;
  bool                     valid;
  Priority_Control         core_priority;
  Status_Control           status;

  if ( !_Scheduler_Get_by_id( scheduler_id, &scheduler ) ) {
    return RTEMS_INVALID_ID;
  }

  core_priority = _RTEMS_Priority_To_core( scheduler, priority, &valid );
  if ( !valid ) {
    return RTEMS_INVALID_PRIORITY;
  }

  _Thread_queue_Context_initialize( &queue_context );
  the_thread = _Thread_Get( task_id, &queue_context.Lock_context.Lock_context );

  if ( the_thread == NULL ) {
#if defined(RTEMS_MULTIPROCESSING)
    if ( _Thread_MP_Is_remote( task_id ) ) {
      return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
    }
#endif

    return RTEMS_INVALID_ID;
  }

  cpu_self = _Thread_Dispatch_disable_critical(
    &queue_context.Lock_context.Lock_context
  );

  _Thread_Wait_acquire_critical( the_thread, &queue_context );
  _Thread_State_acquire_critical( the_thread, &state_context );

  status = _Scheduler_Set( scheduler, the_thread, core_priority );

  _Thread_State_release_critical( the_thread, &state_context );
  _Thread_Wait_release( the_thread, &queue_context );
  _Thread_Dispatch_enable( cpu_self );
  return _Status_Get( status );
}
예제 #5
0
void _Thread_Restart_self(
  Thread_Control                 *executing,
  const Thread_Entry_information *entry,
  ISR_lock_Context               *lock_context
)
{
  Per_CPU_Control      *cpu_self;
  Thread_queue_Context  queue_context;

  _Assert(
    _Watchdog_Get_state( &executing->Timer.Watchdog ) == WATCHDOG_INACTIVE
  );
  _Assert(
    executing->current_state == STATES_READY
      || executing->current_state == STATES_SUSPENDED
  );

  _Thread_queue_Context_initialize( &queue_context );
  _Thread_queue_Context_clear_priority_updates( &queue_context );
  _Thread_State_acquire_critical( executing, lock_context );

  executing->Start.Entry = *entry;
  _Thread_Change_life_locked(
    executing,
    0,
    THREAD_LIFE_RESTARTING,
    THREAD_LIFE_PROTECTED | THREAD_LIFE_CHANGE_DEFERRED
  );

  cpu_self = _Thread_Dispatch_disable_critical( lock_context );
  _Thread_State_release( executing, lock_context );

  _Thread_Wait_acquire_default( executing, lock_context );
  _Thread_Priority_change(
    executing,
    &executing->Real_priority,
    executing->Start.initial_priority,
    false,
    &queue_context
  );
  _Thread_Wait_release_default( executing, lock_context );

  _Thread_Priority_update( &queue_context );
  _Thread_Dispatch_enable( cpu_self );
  RTEMS_UNREACHABLE();
}
예제 #6
0
bool _Thread_Restart_other(
  Thread_Control                 *the_thread,
  const Thread_Entry_information *entry,
  ISR_lock_Context               *lock_context
)
{
  Thread_Life_state  previous;
  Per_CPU_Control   *cpu_self;

  _Thread_State_acquire_critical( the_thread, lock_context );

  if ( _States_Is_dormant( the_thread->current_state ) ) {
    _Thread_State_release( the_thread, lock_context );
    return false;
  }

  the_thread->Start.Entry = *entry;
  previous = _Thread_Change_life_locked(
    the_thread,
    0,
    THREAD_LIFE_RESTARTING,
    0
  );

  cpu_self = _Thread_Dispatch_disable_critical( lock_context );

  if ( _Thread_Is_life_change_allowed( previous ) ) {
    _Thread_Add_life_change_request( the_thread );
    _Thread_State_release( the_thread, lock_context );

    _Thread_Finalize_life_change(
      the_thread,
      the_thread->Start.initial_priority
    );
  } else {
    _Thread_Clear_state_locked( the_thread, STATES_SUSPENDED );
    _Thread_State_release( the_thread, lock_context );
  }

  _Thread_Dispatch_enable( cpu_self );
  return true;
}
예제 #7
0
void _Thread_Restart_self(
  Thread_Control                 *executing,
  const Thread_Entry_information *entry,
  ISR_lock_Context               *lock_context
)
{
  Per_CPU_Control  *cpu_self;
  Priority_Control  unused;

  _Assert(
    _Watchdog_Get_state( &executing->Timer.Watchdog ) == WATCHDOG_INACTIVE
  );
  _Assert(
    executing->current_state == STATES_READY
      || executing->current_state == STATES_SUSPENDED
  );

  _Thread_State_acquire_critical( executing, lock_context );

  executing->Start.Entry = *entry;
  _Thread_Change_life_locked(
    executing,
    0,
    THREAD_LIFE_RESTARTING,
    THREAD_LIFE_PROTECTED | THREAD_LIFE_CHANGE_DEFERRED
  );

  cpu_self = _Thread_Dispatch_disable_critical( lock_context );
  _Thread_State_release( executing, lock_context );

  _Thread_Set_priority(
    executing,
    executing->Start.initial_priority,
    &unused,
    true
  );

  _Thread_Dispatch_enable( cpu_self );
  RTEMS_UNREACHABLE();
}
예제 #8
0
void _Thread_Close(
  Thread_Control       *the_thread,
  Thread_Control       *executing,
  Thread_Close_context *context
)
{
  context->cancel = the_thread;
  _Thread_queue_Context_set_enqueue_callout(
    &context->Base,
    _Thread_Close_enqueue_callout
  );
  _Thread_queue_Context_set_no_timeout( &context->Base );
  _Thread_State_acquire_critical(
    the_thread,
    &context->Base.Lock_context.Lock_context
  );
  _Thread_Join(
    the_thread,
    STATES_WAITING_FOR_JOIN,
    executing,
    &context->Base
  );
}
예제 #9
0
int pthread_setschedparam(
  pthread_t           thread,
  int                 policy,
  struct sched_param *param
)
{
  Thread_Control                      *the_thread;
  Per_CPU_Control                     *cpu_self;
  POSIX_API_Control                   *api;
  Thread_CPU_budget_algorithms         budget_algorithm;
  Thread_CPU_budget_algorithm_callout  budget_callout;
  int                                  eno;
  Priority_Control                     unused;
  ISR_lock_Context                     lock_context;
  Priority_Control                     new_priority;

  /*
   *  Check all the parameters
   */

  if ( param == NULL ) {
    return EINVAL;
  }

  eno = _POSIX_Thread_Translate_sched_param(
    policy,
    param,
    &budget_algorithm,
    &budget_callout
  );
  if ( eno != 0 ) {
    return eno;
  }

  the_thread = _Thread_Get_interrupt_disable( thread, &lock_context );

  if ( the_thread == NULL ) {
    return ESRCH;
  }

  /*
   *  Actually change the scheduling policy and parameters
   */

  cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
  _Thread_State_acquire_critical( the_thread, &lock_context );

  api = the_thread->API_Extensions[ THREAD_API_POSIX ];

  if ( api->schedpolicy == SCHED_SPORADIC ) {
    _Watchdog_Per_CPU_remove_relative( &api->Sporadic_timer );
  }

  api->schedpolicy = policy;
  api->schedparam  = *param;
  api->Attributes.schedpolicy = policy;
  api->Attributes.schedparam  = *param;

  the_thread->budget_algorithm = budget_algorithm;
  the_thread->budget_callout   = budget_callout;

  switch ( policy ) {
    case SCHED_OTHER:
    case SCHED_FIFO:
    case SCHED_RR:
      the_thread->cpu_time_budget =
        rtems_configuration_get_ticks_per_timeslice();
      new_priority = _POSIX_Priority_To_core( api->schedparam.sched_priority );
      break;

    case SCHED_SPORADIC:
      api->ss_high_priority = api->schedparam.sched_priority;
      break;
  }

  _Thread_State_release( the_thread, &lock_context );

  switch ( policy ) {
    case SCHED_OTHER:
    case SCHED_FIFO:
    case SCHED_RR:
      _Thread_Set_priority( the_thread, new_priority, &unused, true );
      break;

    case SCHED_SPORADIC:
      _POSIX_Threads_Sporadic_budget_TSR( &api->Sporadic_timer );
      break;
  }

  _Thread_Dispatch_enable( cpu_self );
  return 0;
}