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; }
rtems_status_code rtems_task_delete( rtems_id id ) { Thread_Control *the_thread; Objects_Locations location; bool previous_life_protection; previous_life_protection = _Thread_Set_life_protection( true ); the_thread = _Thread_Get( id, &location ); switch ( location ) { case OBJECTS_LOCAL: #if defined(RTEMS_MULTIPROCESSING) if ( the_thread->is_global ) { _Objects_MP_Close( &_RTEMS_tasks_Information.Objects, 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_thread, _Thread_Executing ); _Objects_Put( &the_thread->Object ); _Thread_Set_life_protection( previous_life_protection ); return RTEMS_SUCCESSFUL; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: _Thread_Dispatch(); _Thread_Set_life_protection( previous_life_protection ); return RTEMS_ILLEGAL_ON_REMOTE_OBJECT; #endif case OBJECTS_ERROR: break; } _Thread_Set_life_protection( previous_life_protection ); return RTEMS_INVALID_ID; }
rtems_status_code rtems_task_delete( rtems_id id ) { Thread_Control *the_thread; ISR_lock_Context lock_context; Thread_Control *executing; Per_CPU_Control *cpu_self; the_thread = _Thread_Get( id, &lock_context ); if ( the_thread == NULL ) { #if defined(RTEMS_MULTIPROCESSING) if ( _Thread_MP_Is_remote( id ) ) { return RTEMS_ILLEGAL_ON_REMOTE_OBJECT; } #endif return RTEMS_INVALID_ID; } cpu_self = _Thread_Dispatch_disable_critical( &lock_context ); _ISR_lock_ISR_enable( &lock_context ); executing = _Per_CPU_Get_executing( cpu_self ); if ( the_thread == executing ) { /* * The Classic tasks are neither detached nor joinable. In case of * self deletion, they are detached, otherwise joinable by default. */ _Thread_Exit( executing, THREAD_LIFE_TERMINATING | THREAD_LIFE_DETACHED, NULL ); } else { _Thread_Close( the_thread, executing ); } _Thread_Dispatch_enable( cpu_self ); return RTEMS_SUCCESSFUL; }
void _POSIX_Thread_Exit( Thread_Control *the_thread, void *value_ptr ) { Thread_Control *unblocked; POSIX_API_Control *api; bool previous_life_protection; api = the_thread->API_Extensions[ THREAD_API_POSIX ]; _Assert( _Debug_Is_thread_dispatching_allowed() ); previous_life_protection = _Thread_Set_life_protection( true ); _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 ); _Thread_Enable_dispatch(); /* now waiting for thread to arrive */ _Thread_Disable_dispatch(); } } /* * Now shut down the thread */ _Thread_Close( the_thread, _Thread_Executing ); _Thread_Enable_dispatch(); _Thread_Set_life_protection( previous_life_protection ); }
void pthread_exit( void *value_ptr ) { Objects_Information *the_information; the_information = _Objects_Get_information( _Thread_Executing->Object.id ); /* This should never happen if _Thread_Get() works right */ assert( the_information ); _Thread_Disable_dispatch(); _Thread_Executing->Wait.return_argument = value_ptr; _Thread_Close( the_information, _Thread_Executing ); _POSIX_Threads_Free( _Thread_Executing ); _Thread_Enable_dispatch(); }
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(); }