static Thread_Life_state _Thread_Change_life_locked( Thread_Control *the_thread, Thread_Life_state clear, Thread_Life_state set, Thread_Life_state ignore ) { Thread_Life_state previous; Thread_Life_state state; previous = the_thread->Life.state; state = previous; state &= ~clear; state |= set; the_thread->Life.state = state; state &= ~ignore; if ( _Thread_Is_life_change_allowed( state ) && _Thread_Is_life_changing( state ) ) { 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_Add_post_switch_action( the_thread, &the_thread->Life.Action, _Thread_Life_action_handler ); } return previous; }
static void _Thread_Add_life_change_action( Thread_Control *the_thread ) { _Thread_Add_post_switch_action( the_thread, &the_thread->Life.Action, _Thread_Life_action_handler ); }
static void _Thread_Start_life_change_for_executing( Thread_Control *executing ) { _Assert( executing->Timer.state == WATCHDOG_INACTIVE ); _Assert( executing->current_state == STATES_READY || executing->current_state == STATES_SUSPENDED ); _Thread_Add_post_switch_action( executing, &executing->Life.Action ); }
static bool _POSIX_signals_Unblock_thread_done( Thread_Control *the_thread, POSIX_API_Control *api, bool status ) { ISR_lock_Context lock_context; _Thread_State_acquire( the_thread, &lock_context ); _Thread_Add_post_switch_action( the_thread, &api->Signal_action, _POSIX_signals_Action_handler ); _Thread_State_release( the_thread, &lock_context ); return status; }
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_post_switch_action( the_thread, &the_thread->Life.Action ); _Thread_Ready( the_thread ); }
rtems_status_code rtems_task_mode( rtems_mode mode_set, rtems_mode mask, rtems_mode *previous_mode_set ) { Thread_Control *executing; RTEMS_API_Control *api; ASR_Information *asr; bool preempt_enabled; bool needs_asr_dispatching; rtems_mode old_mode; if ( !previous_mode_set ) return RTEMS_INVALID_ADDRESS; executing = _Thread_Get_executing(); api = executing->API_Extensions[ THREAD_API_RTEMS ]; asr = &api->Signal; old_mode = (executing->is_preemptible) ? RTEMS_PREEMPT : RTEMS_NO_PREEMPT; if ( executing->budget_algorithm == THREAD_CPU_BUDGET_ALGORITHM_NONE ) old_mode |= RTEMS_NO_TIMESLICE; else old_mode |= RTEMS_TIMESLICE; old_mode |= (asr->is_enabled) ? RTEMS_ASR : RTEMS_NO_ASR; old_mode |= _ISR_Get_level(); *previous_mode_set = old_mode; /* * These are generic thread scheduling characteristics. */ preempt_enabled = false; if ( mask & RTEMS_PREEMPT_MASK ) { #if defined( RTEMS_SMP ) if ( rtems_configuration_is_smp_enabled() && !_Modes_Is_preempt( mode_set ) ) { return RTEMS_NOT_IMPLEMENTED; } #endif bool is_preempt_enabled = _Modes_Is_preempt( mode_set ); preempt_enabled = !executing->is_preemptible && is_preempt_enabled; executing->is_preemptible = is_preempt_enabled; } if ( mask & RTEMS_TIMESLICE_MASK ) { if ( _Modes_Is_timeslice(mode_set) ) { executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE; executing->cpu_time_budget = rtems_configuration_get_ticks_per_timeslice(); } else executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE; } /* * Set the new interrupt level */ if ( mask & RTEMS_INTERRUPT_MASK ) _Modes_Set_interrupt_level( mode_set ); /* * This is specific to the RTEMS API */ needs_asr_dispatching = false; if ( mask & RTEMS_ASR_MASK ) { bool is_asr_enabled = !_Modes_Is_asr_disabled( mode_set ); if ( is_asr_enabled != asr->is_enabled ) { asr->is_enabled = is_asr_enabled; _ASR_Swap_signals( asr ); if ( _ASR_Are_signals_pending( asr ) ) { needs_asr_dispatching = true; _Thread_Add_post_switch_action( executing, &api->Signal_action, _Signal_Action_handler ); } } } if ( preempt_enabled || needs_asr_dispatching ) { Per_CPU_Control *cpu_self; ISR_lock_Context lock_context; cpu_self = _Thread_Dispatch_disable(); _Scheduler_Acquire( executing, &lock_context ); _Scheduler_Schedule( executing ); _Scheduler_Release( executing, &lock_context ); _Thread_Dispatch_enable( cpu_self ); } return RTEMS_SUCCESSFUL; }