void _Thread_Close( Thread_Control *the_thread, Thread_Control *executing ) { _Assert( _Thread_Is_life_protected( executing->Life.state ) ); if ( _States_Is_dormant( the_thread->current_state ) ) { _Thread_Make_zombie( the_thread ); } else { if ( the_thread != executing && !_Thread_Is_life_terminating( executing->Life.state ) ) { /* * Wait for termination of victim thread. If the executing thread is * also terminated, then do not wait. This avoids potential cyclic * dependencies and thus dead lock. */ the_thread->Life.terminator = executing; _Thread_Set_state( executing, STATES_WAITING_FOR_TERMINATION ); } _Thread_Request_life_change( the_thread, executing, executing->current_priority, THREAD_LIFE_TERMINATING ); } }
static void _Thread_Request_life_change( Thread_Control *the_thread, Thread_Control *executing, Priority_Control priority, Thread_Life_state additional_life_state ) { Thread_Life_state previous_life_state; Per_CPU_Control *cpu; ISR_Level level; const Scheduler_Control *scheduler; cpu = _Thread_Action_ISR_disable_and_acquire( the_thread, &level ); previous_life_state = the_thread->Life.state; the_thread->Life.state = previous_life_state | additional_life_state; _Thread_Action_release_and_ISR_enable( cpu, level ); scheduler = _Scheduler_Get( the_thread ); if ( the_thread == executing ) { executing->real_priority = priority; _Scheduler_Set_priority_if_higher( scheduler, the_thread, priority ); _Thread_Start_life_change_for_executing( executing ); } else if ( previous_life_state == THREAD_LIFE_NORMAL ) { _Thread_Start_life_change( the_thread, scheduler, priority ); } else { _Thread_Clear_state( the_thread, STATES_SUSPENDED ); if ( _Thread_Is_life_terminating( additional_life_state ) ) { the_thread->real_priority = _Scheduler_Highest_priority_of_two( scheduler, the_thread->real_priority, priority ); _Scheduler_Change_priority_if_higher( scheduler, the_thread, priority, false ); } } }
void _Thread_Life_action_handler( Thread_Control *executing, Thread_Action *action, ISR_lock_Context *lock_context ) { Thread_Life_state previous_life_state; Per_CPU_Control *cpu_self; (void) action; previous_life_state = executing->Life.state; executing->Life.state = previous_life_state | THREAD_LIFE_PROTECTED; _Thread_State_release( executing, lock_context ); if ( _Thread_Is_life_terminating( previous_life_state ) ) { _User_extensions_Thread_terminate( executing ); } else { _Assert( _Thread_Is_life_restarting( previous_life_state ) ); _User_extensions_Thread_restart( executing ); } cpu_self = _Thread_Dispatch_disable(); if ( _Thread_Is_life_terminating( previous_life_state ) ) { cpu_self = _Thread_Wait_for_join( executing, cpu_self ); _Thread_Make_zombie( executing ); /* FIXME: Workaround for https://devel.rtems.org/ticket/2751 */ cpu_self->dispatch_necessary = true; _Assert( cpu_self->heir != executing ); _Thread_Dispatch_enable( cpu_self ); RTEMS_UNREACHABLE(); } _Assert( _Thread_Is_life_restarting( previous_life_state ) ); _Thread_State_acquire( executing, lock_context ); _Thread_Change_life_locked( executing, THREAD_LIFE_PROTECTED | THREAD_LIFE_RESTARTING, 0, 0 ); _Thread_State_release( executing, lock_context ); _Assert( _Watchdog_Get_state( &executing->Timer.Watchdog ) == WATCHDOG_INACTIVE ); _Assert( executing->current_state == STATES_READY || executing->current_state == STATES_SUSPENDED ); _User_extensions_Destroy_iterators( executing ); _Thread_Load_environment( executing ); #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE ) if ( executing->fp_context != NULL ) { _Context_Restore_fp( &executing->fp_context ); } #endif _Context_Restart_self( &executing->Registers ); RTEMS_UNREACHABLE(); }
void _Thread_Life_action_handler( Thread_Control *executing, Thread_Action *action, Per_CPU_Control *cpu, ISR_Level level ) { Thread_Life_state previous_life_state; (void) action; previous_life_state = executing->Life.state; executing->Life.state = THREAD_LIFE_PROTECTED; _Thread_Action_release_and_ISR_enable( cpu, level ); if ( _Thread_Is_life_terminating( previous_life_state ) ) { _User_extensions_Thread_terminate( executing ); } else { _Assert( _Thread_Is_life_restarting( previous_life_state ) ); _User_extensions_Thread_restart( executing ); } _Thread_Disable_dispatch(); if ( _Thread_Is_life_terminating( previous_life_state ) ) { _Thread_Make_zombie( executing ); if ( executing->Life.terminator != NULL ) { _Thread_Clear_state( executing->Life.terminator, STATES_WAITING_FOR_TERMINATION ); } _Thread_Enable_dispatch(); _Assert_Not_reached(); } else { _Assert( _Thread_Is_life_restarting( previous_life_state ) ); if ( _Thread_Is_life_terminating( executing->Life.state ) ) { /* Someone deleted us in the mean-time */ _Thread_Start_life_change_for_executing( executing ); } else { _Assert( executing->Timer.state == WATCHDOG_INACTIVE ); _Assert( executing->current_state == STATES_READY || executing->current_state == STATES_SUSPENDED ); executing->Life.state = THREAD_LIFE_NORMAL; _Thread_Load_environment( executing ); _Thread_Restart_self( executing ); _Assert_Not_reached(); } } }