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; }
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; }
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 ); }
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(); }
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; }
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(); }
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 ); }
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; }