static void _Thread_Make_zombie( Thread_Control *the_thread ) { if ( _Thread_Owns_resources( the_thread ) ) { _Terminate( INTERNAL_ERROR_CORE, false, INTERNAL_ERROR_RESOURCE_IN_USE ); } _Objects_Close( _Objects_Get_information_id( the_thread->Object.id ), &the_thread->Object ); _Thread_Set_state( the_thread, STATES_ZOMBIE ); _Thread_queue_Extract_with_proxy( the_thread ); _Thread_Timer_remove( the_thread ); /* * Add the thread to the thread zombie chain before we wake up joining * threads, so that they are able to clean up the thread immediately. This * matters for SMP configurations. */ _Thread_Add_to_zombie_chain( the_thread ); _Thread_Wake_up_joining_threads( the_thread ); }
/* * This method will set the object name based upon the user string. * If the object class uses 32-bit names, then only the first 4 bytes * of the string will be used. */ rtems_status_code rtems_object_set_name( rtems_id id, const char *name ) { Objects_Information *information; Objects_Control *the_object; Objects_Id tmpId; if ( !name ) return RTEMS_INVALID_ADDRESS; tmpId = (id == OBJECTS_ID_OF_SELF) ? rtems_task_self() : id; information = _Objects_Get_information_id( tmpId ); if ( !information ) return RTEMS_INVALID_ID; _Objects_Allocator_lock(); the_object = _Objects_Get_no_protection( tmpId, information ); if ( the_object == NULL ) { _Objects_Allocator_unlock(); return RTEMS_INVALID_ID; } _Objects_Set_name( information, the_object, name ); _Objects_Allocator_unlock(); return RTEMS_SUCCESSFUL; }
bool _Thread_queue_Extract_with_proxy( Thread_Control *the_thread ) { States_Control state; state = the_thread->current_state; if ( _States_Is_waiting_on_thread_queue( state ) ) { #if defined(RTEMS_MULTIPROCESSING) if ( _States_Is_waiting_for_rpc_reply( state ) && _States_Is_locally_blocked( state ) ) { Objects_Information *the_information; Objects_Thread_queue_Extract_callout proxy_extract_callout; the_information = _Objects_Get_information_id( the_thread->Wait.id ); proxy_extract_callout = (Objects_Thread_queue_Extract_callout) the_information->extract; if ( proxy_extract_callout ) (*proxy_extract_callout)( the_thread ); } #endif _Thread_queue_Extract( the_thread->Wait.queue, the_thread ); return true; } return false; }
static void _Thread_Make_zombie( Thread_Control *the_thread ) { ISR_lock_Context lock_context; Thread_Zombie_control *zombies = &_Thread_Zombies; if ( _Thread_Owns_resources( the_thread ) ) { _Terminate( INTERNAL_ERROR_CORE, false, INTERNAL_ERROR_RESOURCE_IN_USE ); } _Objects_Close( _Objects_Get_information_id( the_thread->Object.id ), &the_thread->Object ); _Thread_Set_state( the_thread, STATES_ZOMBIE ); _Thread_queue_Extract_with_proxy( the_thread ); _Watchdog_Remove_ticks( &the_thread->Timer ); _ISR_lock_ISR_disable_and_acquire( &zombies->Lock, &lock_context ); _Chain_Append_unprotected( &zombies->Chain, &the_thread->Object.Node ); _ISR_lock_Release_and_ISR_enable( &zombies->Lock, &lock_context ); }
static void _Thread_Free( Thread_Control *the_thread ) { _User_extensions_Thread_delete( the_thread ); /* * Free the per-thread scheduling information. */ _Scheduler_Node_destroy( _Scheduler_Get( the_thread ), the_thread ); /* * 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 /* * 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 ); _Objects_Free( _Objects_Get_information_id( the_thread->Object.id ), &the_thread->Object ); }
void _Thread_Close( Thread_Control *the_thread, Thread_Control *executing ) { _Assert( _Thread_Is_life_protected( executing->Life.state ) ); _Objects_Close( _Objects_Get_information_id( the_thread->Object.id ), &the_thread->Object ); 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_Make_zombie( Thread_Control *the_thread ) { #if defined(RTEMS_SCORE_THREAD_ENABLE_RESOURCE_COUNT) if ( _Thread_Owns_resources( the_thread ) ) { _Internal_error( INTERNAL_ERROR_RESOURCE_IN_USE ); } #endif _Objects_Close( _Objects_Get_information_id( the_thread->Object.id ), &the_thread->Object ); _Thread_Set_state( the_thread, STATES_ZOMBIE ); _Thread_queue_Extract_with_proxy( the_thread ); _Thread_Timer_remove( the_thread ); /* * Add the thread to the thread zombie chain before we wake up joining * threads, so that they are able to clean up the thread immediately. This * matters for SMP configurations. */ _Thread_Add_to_zombie_chain( the_thread ); _Thread_Wake_up_joining_threads( the_thread ); }
/** * @brief RTEMS_tasks_Free * * This routine frees a task control block to the * inactive chain of free task control blocks. */ RTEMS_INLINE_ROUTINE void _RTEMS_tasks_Free ( Thread_Control *the_task ) { _Objects_Free( _Objects_Get_information_id( the_task->Object.id ), &the_task->Object ); }
rtems_status_code rtems_task_delete( rtems_id id ) { register Thread_Control *the_thread; Objects_Locations location; Objects_Information *the_information; _RTEMS_Lock_allocator(); the_thread = _Thread_Get( id, &location ); switch ( location ) { case OBJECTS_LOCAL: the_information = _Objects_Get_information_id( the_thread->Object.id ); #if defined(RTEMS_DEBUG) if ( !the_information ) { _Thread_Enable_dispatch(); return RTEMS_INVALID_ID; /* This should never happen if _Thread_Get() works right */ } #endif #if defined(RTEMS_MULTIPROCESSING) if ( the_thread->is_global ) { _Objects_MP_Close( &_RTEMS_tasks_Information, the_thread->Object.id ); _RTEMS_tasks_MP_Send_process_packet( RTEMS_TASKS_MP_ANNOUNCE_DELETE, the_thread->Object.id, 0 /* Not used */ ); } #endif _Thread_Close( the_information, the_thread ); _RTEMS_tasks_Free( the_thread ); _RTEMS_Unlock_allocator(); _Thread_Enable_dispatch(); return RTEMS_SUCCESSFUL; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: _RTEMS_Unlock_allocator(); _Thread_Dispatch(); return RTEMS_ILLEGAL_ON_REMOTE_OBJECT; #endif case OBJECTS_ERROR: break; } _RTEMS_Unlock_allocator(); return RTEMS_INVALID_ID; }
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 ); }
/* * This method will set the object name based upon the user string. * If the object class uses 32-bit names, then only the first 4 bytes * of the string will be used. */ rtems_status_code rtems_object_set_name( rtems_id id, const char *name ) { Objects_Information *information; Objects_Locations location; Objects_Control *the_object; Objects_Id tmpId; if ( !name ) return RTEMS_INVALID_ADDRESS; tmpId = (id == OBJECTS_ID_OF_SELF) ? _Thread_Get_executing()->Object.id : id; information = _Objects_Get_information_id( tmpId ); if ( !information ) return RTEMS_INVALID_ID; the_object = _Objects_Get( information, tmpId, &location ); switch ( location ) { case OBJECTS_LOCAL: _Objects_Set_name( information, the_object, name ); _Objects_Put( the_object ); return RTEMS_SUCCESSFUL; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: #endif case OBJECTS_ERROR: break; } return RTEMS_INVALID_ID; }
void _POSIX_Thread_Exit( Thread_Control *the_thread, void *value_ptr ) { Objects_Information *the_information; Thread_Control *unblocked; POSIX_API_Control *api; the_information = _Objects_Get_information_id( the_thread->Object.id ); api = the_thread->API_Extensions[ THREAD_API_POSIX ]; /* * The_information has to be non-NULL. Otherwise, we couldn't be * running in a thread of this API and class. * * NOTE: Lock and unlock in different order so we do not throw a * fatal error when locking the allocator mutex. And after * we unlock, we want to defer the context switch until we * are ready to be switched out. Otherwise, an ISR could * occur and preempt us out while we still hold the * allocator mutex. */ _RTEMS_Lock_allocator(); _Thread_Disable_dispatch(); the_thread->Wait.return_argument = value_ptr; /* * Process join */ if ( api->detachstate == PTHREAD_CREATE_JOINABLE ) { unblocked = _Thread_queue_Dequeue( &api->Join_List ); if ( unblocked ) { do { *(void **)unblocked->Wait.return_argument = value_ptr; } while ( (unblocked = _Thread_queue_Dequeue( &api->Join_List )) ); } else { _Thread_Set_state( the_thread, STATES_WAITING_FOR_JOIN_AT_EXIT | STATES_TRANSIENT ); _RTEMS_Unlock_allocator(); _Thread_Enable_dispatch(); /* now waiting for thread to arrive */ _RTEMS_Lock_allocator(); _Thread_Disable_dispatch(); } } /* * Now shut down the thread */ _Thread_Close( the_information, the_thread ); _POSIX_Threads_Free( the_thread ); _RTEMS_Unlock_allocator(); _Thread_Enable_dispatch(); }