static void _Thread_Free( Thread_Control *the_thread ) { Thread_Information *information = (Thread_Information *) _Objects_Get_information_id( the_thread->Object.id ); _User_extensions_Thread_delete( the_thread ); _User_extensions_Destroy_iterators( the_thread ); _ISR_lock_Destroy( &the_thread->Keys.Lock ); _Scheduler_Node_destroy( _Thread_Scheduler_get_home( the_thread ), _Thread_Scheduler_get_home_node( the_thread ) ); _ISR_lock_Destroy( &the_thread->Timer.Lock ); /* * The thread might have been FP. So deal with that. */ #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE ) #if ( CPU_USE_DEFERRED_FP_SWITCH == TRUE ) if ( _Thread_Is_allocated_fp( the_thread ) ) _Thread_Deallocate_fp(); #endif _Workspace_Free( the_thread->Start.fp_context ); #endif _Freechain_Put( &information->Free_thread_queue_heads, the_thread->Wait.spare_heads ); /* * Free the rest of the memory associated with this task * and set the associated pointers to NULL for safety. */ _Thread_Stack_Free( the_thread ); _Workspace_Free( the_thread->Start.tls_area ); #if defined(RTEMS_SMP) _ISR_lock_Destroy( &the_thread->Scheduler.Lock ); _ISR_lock_Destroy( &the_thread->Wait.Lock.Default ); _SMP_lock_Stats_destroy( &the_thread->Potpourri_stats ); #endif _Thread_queue_Destroy( &the_thread->Join_queue ); _Objects_Free( &information->Objects, &the_thread->Object ); }
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(); }