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_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 ); }
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 ); }
static void _Thread_Finalize_life_change( Thread_Control *the_thread, Priority_Control priority ) { _Thread_queue_Extract_with_proxy( the_thread ); _Thread_Timer_remove( the_thread ); _Thread_Raise_real_priority( the_thread, priority ); _Thread_Remove_life_change_request( the_thread ); }
static void _Thread_Start_life_change( Thread_Control *the_thread, const Scheduler_Control *scheduler, Priority_Control priority ) { the_thread->is_preemptible = the_thread->Start.is_preemptible; the_thread->budget_algorithm = the_thread->Start.budget_algorithm; the_thread->budget_callout = the_thread->Start.budget_callout; the_thread->real_priority = priority; _Thread_Set_state( the_thread, STATES_RESTARTING ); _Thread_queue_Extract_with_proxy( the_thread ); _Watchdog_Remove( &the_thread->Timer ); _Scheduler_Set_priority_if_higher( scheduler, the_thread, priority ); _Thread_Add_post_switch_action( the_thread, &the_thread->Life.Action ); _Thread_Ready( the_thread ); _Thread_Request_dispatch_if_executing( the_thread ); }
static void _Thread_Start_life_change( Thread_Control *the_thread, const Scheduler_Control *scheduler, Priority_Control priority ) { the_thread->is_preemptible = the_thread->Start.is_preemptible; the_thread->budget_algorithm = the_thread->Start.budget_algorithm; the_thread->budget_callout = the_thread->Start.budget_callout; _Thread_Set_state( the_thread, STATES_RESTARTING ); _Thread_queue_Extract_with_proxy( the_thread ); _Watchdog_Remove_ticks( &the_thread->Timer ); _Thread_Change_priority( the_thread, priority, NULL, _Thread_Raise_real_priority_filter, false ); _Thread_Add_life_change_action( the_thread ); _Thread_Ready( the_thread ); }
void _Thread_Close( Objects_Information *information, Thread_Control *the_thread ) { /* * Now we are in a dispatching critical section again and we * can take the thread OUT of the published set. It is invalid * to use this thread's Id after this call. This will prevent * any other task from attempting to initiate a call on this task. */ _Objects_Invalidate_Id( information, &the_thread->Object ); /* * We assume the Allocator Mutex is locked when we get here. * This provides sufficient protection to let the user extensions * run but as soon as we get back, we will make the thread * disappear and set a transient state on it. So we temporarily * unnest dispatching. */ _Thread_Unnest_dispatch(); _User_extensions_Thread_delete( the_thread ); _Thread_Disable_dispatch(); /* * Now we are in a dispatching critical section again and we * can take the thread OUT of the published set. It is invalid * to use this thread's Id OR name after this call. */ _Objects_Close( information, &the_thread->Object ); /* * By setting the dormant state, the thread will not be considered * for scheduling when we remove any blocking states. */ _Thread_Set_state( the_thread, STATES_DORMANT ); if ( !_Thread_queue_Extract_with_proxy( the_thread ) ) { if ( _Watchdog_Is_active( &the_thread->Timer ) ) (void) _Watchdog_Remove( &the_thread->Timer ); } /* * Free the per-thread scheduling information. */ _Scheduler_Free( 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 the_thread->fp_context = NULL; _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 ); the_thread->Start.stack = NULL; _Workspace_Free( the_thread->extensions ); the_thread->extensions = NULL; _Workspace_Free( the_thread->Start.tls_area ); }
/* XXX this routine could probably be cleaned up */ bool _POSIX_signals_Unblock_thread( Thread_Control *the_thread, int signo, siginfo_t *info ) { POSIX_API_Control *api; sigset_t mask; siginfo_t *the_info = NULL; api = the_thread->API_Extensions[ THREAD_API_POSIX ]; mask = signo_to_mask( signo ); /* * Is the thread is specifically waiting for a signal? */ if ( _States_Is_interruptible_signal( the_thread->current_state ) ) { if ( (the_thread->Wait.option & mask) || (~api->signals_blocked & mask) ) { the_thread->Wait.return_code = EINTR; the_info = (siginfo_t *) the_thread->Wait.return_argument; if ( !info ) { the_info->si_signo = signo; the_info->si_code = SI_USER; the_info->si_value.sival_int = 0; } else { *the_info = *info; } _Thread_queue_Extract_with_proxy( the_thread ); return true; } /* * This should only be reached via pthread_kill(). */ return false; } /* * Thread is not waiting due to a sigwait. */ if ( ~api->signals_blocked & mask ) { /* * The thread is interested in this signal. We are going * to post it. We have a few broad cases: * + If it is blocked on an interruptible signal, THEN * we unblock the thread. * + If it is in the ready state AND * we are sending from an ISR AND * it is the interrupted thread AND * it is not blocked, THEN * we need to dispatch at the end of this ISR. * + Any other combination, do nothing. */ the_thread->do_post_task_switch_extension = true; if ( _States_Is_interruptible_by_signal( the_thread->current_state ) ) { the_thread->Wait.return_code = EINTR; /* * In pthread_cond_wait, a thread will be blocking on a thread * queue, but is also interruptible by a POSIX signal. */ if ( _States_Is_waiting_on_thread_queue(the_thread->current_state) ) _Thread_queue_Extract_with_proxy( the_thread ); else if ( _States_Is_delaying(the_thread->current_state) ){ (void) _Watchdog_Remove( &the_thread->Timer ); _Thread_Unblock( the_thread ); } } else if ( the_thread->current_state == STATES_READY ) { if ( _ISR_Is_in_progress() && _Thread_Is_executing( the_thread ) ) _ISR_Signals_to_thread_executing = true; } } return false; }
/* XXX this routine could probably be cleaned up */ boolean _POSIX_signals_Unblock_thread( Thread_Control *the_thread, int signo, siginfo_t *info ) { POSIX_API_Control *api; sigset_t mask; siginfo_t *the_info = NULL; api = the_thread->API_Extensions[ THREAD_API_POSIX ]; mask = signo_to_mask( signo ); /* * Is the thread is specifically waiting for a signal? */ if ( _States_Is_interruptible_signal( the_thread->current_state ) ) { if ( (the_thread->Wait.option & mask) || (~api->signals_blocked & mask) ) { the_thread->Wait.return_code = EINTR; the_info = (siginfo_t *) the_thread->Wait.return_argument; if ( !info ) { the_info->si_signo = signo; the_info->si_code = SI_USER; the_info->si_value.sival_int = 0; } else { *the_info = *info; } _Thread_queue_Extract_with_proxy( the_thread ); return TRUE; } /* * This should only be reached via pthread_kill(). */ return FALSE; } if ( ~api->signals_blocked & mask ) { the_thread->do_post_task_switch_extension = TRUE; if ( the_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL ) { the_thread->Wait.return_code = EINTR; if ( _States_Is_waiting_on_thread_queue(the_thread->current_state) ) _Thread_queue_Extract_with_proxy( the_thread ); else if ( _States_Is_delaying(the_thread->current_state)){ if ( _Watchdog_Is_active( &the_thread->Timer ) ) (void) _Watchdog_Remove( &the_thread->Timer ); _Thread_Unblock( the_thread ); } } } return FALSE; }
bool _POSIX_signals_Unblock_thread( Thread_Control *the_thread, int signo, siginfo_t *info ) { POSIX_API_Control *api; sigset_t mask; siginfo_t *the_info = NULL; api = the_thread->API_Extensions[ THREAD_API_POSIX ]; mask = signo_to_mask( signo ); /* * Is the thread is specifically waiting for a signal? */ if ( _States_Is_interruptible_signal( the_thread->current_state ) ) { if ( (the_thread->Wait.option & mask) || (api->signals_unblocked & mask) ) { the_thread->Wait.return_code = STATUS_INTERRUPTED; the_info = (siginfo_t *) the_thread->Wait.return_argument; if ( !info ) { the_info->si_signo = signo; the_info->si_code = SI_USER; the_info->si_value.sival_int = 0; } else { *the_info = *info; } _Thread_queue_Extract_with_proxy( the_thread ); return _POSIX_signals_Unblock_thread_done( the_thread, api, true ); } /* * This should only be reached via pthread_kill(). */ return _POSIX_signals_Unblock_thread_done( the_thread, api, false ); } /* * Thread is not waiting due to a sigwait. */ if ( api->signals_unblocked & mask ) { /* * The thread is interested in this signal. We are going * to post it. We have a few broad cases: * + If it is blocked on an interruptible signal, THEN * we unblock the thread. * + If it is in the ready state AND * we are sending from an ISR AND * it is the interrupted thread AND * it is not blocked, THEN * we need to dispatch at the end of this ISR. * + Any other combination, do nothing. */ if ( _States_Is_interruptible_by_signal( the_thread->current_state ) ) { the_thread->Wait.return_code = STATUS_INTERRUPTED; _Thread_queue_Extract_with_proxy( the_thread ); } } return _POSIX_signals_Unblock_thread_done( the_thread, api, false ); }