[a6500136] | 1 | /** |
---|
| 2 | * @file |
---|
[c4d69e2] | 3 | * |
---|
[a6500136] | 4 | * @brief RTEMS Task Mode |
---|
| 5 | * @ingroup ClassicTasks |
---|
| 6 | */ |
---|
| 7 | |
---|
| 8 | /* |
---|
[6b998fee] | 9 | * COPYRIGHT (c) 1989-2014. |
---|
[c4d69e2] | 10 | * On-Line Applications Research Corporation (OAR). |
---|
| 11 | * |
---|
| 12 | * The license and distribution terms for this file may be |
---|
| 13 | * found in the file LICENSE in this distribution or at |
---|
[c499856] | 14 | * http://www.rtems.org/license/LICENSE. |
---|
[c4d69e2] | 15 | */ |
---|
| 16 | |
---|
[1095ec1] | 17 | #if HAVE_CONFIG_H |
---|
| 18 | #include "config.h" |
---|
| 19 | #endif |
---|
| 20 | |
---|
[5618c37a] | 21 | #include <rtems/rtems/tasks.h> |
---|
[f4d9ab3e] | 22 | #include <rtems/rtems/asrimpl.h> |
---|
[b79953cf] | 23 | #include <rtems/rtems/modesimpl.h> |
---|
[df55d07f] | 24 | #include <rtems/rtems/signalimpl.h> |
---|
[b8a5abf] | 25 | #include <rtems/score/schedulerimpl.h> |
---|
[5618c37a] | 26 | #include <rtems/score/threadimpl.h> |
---|
| 27 | #include <rtems/config.h> |
---|
[c4d69e2] | 28 | |
---|
| 29 | rtems_status_code rtems_task_mode( |
---|
| 30 | rtems_mode mode_set, |
---|
| 31 | rtems_mode mask, |
---|
| 32 | rtems_mode *previous_mode_set |
---|
| 33 | ) |
---|
| 34 | { |
---|
[6e4f929] | 35 | ISR_lock_Context lock_context; |
---|
[c4d69e2] | 36 | Thread_Control *executing; |
---|
| 37 | RTEMS_API_Control *api; |
---|
| 38 | ASR_Information *asr; |
---|
[b8a5abf] | 39 | bool preempt_enabled; |
---|
[7a34ca37] | 40 | bool needs_asr_dispatching; |
---|
[c4d69e2] | 41 | rtems_mode old_mode; |
---|
| 42 | |
---|
[e980b219] | 43 | if ( !previous_mode_set ) |
---|
| 44 | return RTEMS_INVALID_ADDRESS; |
---|
| 45 | |
---|
[d2711c37] | 46 | #if defined( RTEMS_SMP ) |
---|
| 47 | /* |
---|
| 48 | * When in SMP, you cannot disable preemption for a thread or |
---|
| 49 | * alter its interrupt level. It must be fully preemptible with |
---|
| 50 | * all interrupts enabled. |
---|
| 51 | */ |
---|
| 52 | if ( rtems_configuration_is_smp_enabled() ) { |
---|
| 53 | if ( mask & RTEMS_PREEMPT_MASK ) { |
---|
| 54 | if ( !_Modes_Is_preempt( mode_set ) ) { |
---|
| 55 | return RTEMS_NOT_IMPLEMENTED; |
---|
| 56 | } |
---|
| 57 | } |
---|
| 58 | |
---|
| 59 | if ( mask & RTEMS_INTERRUPT_MASK ) { |
---|
| 60 | return RTEMS_NOT_IMPLEMENTED; |
---|
| 61 | } |
---|
| 62 | } |
---|
| 63 | #endif |
---|
| 64 | |
---|
| 65 | /* |
---|
| 66 | * Complete all error checking before doing any operations which |
---|
| 67 | * impact the executing thread. There should be no errors returned |
---|
| 68 | * past this point. |
---|
| 69 | */ |
---|
| 70 | |
---|
[3b8d2fa4] | 71 | executing = _Thread_Get_executing(); |
---|
[c4d69e2] | 72 | api = executing->API_Extensions[ THREAD_API_RTEMS ]; |
---|
| 73 | asr = &api->Signal; |
---|
| 74 | |
---|
| 75 | old_mode = (executing->is_preemptible) ? RTEMS_PREEMPT : RTEMS_NO_PREEMPT; |
---|
| 76 | |
---|
| 77 | if ( executing->budget_algorithm == THREAD_CPU_BUDGET_ALGORITHM_NONE ) |
---|
| 78 | old_mode |= RTEMS_NO_TIMESLICE; |
---|
| 79 | else |
---|
| 80 | old_mode |= RTEMS_TIMESLICE; |
---|
| 81 | |
---|
| 82 | old_mode |= (asr->is_enabled) ? RTEMS_ASR : RTEMS_NO_ASR; |
---|
| 83 | old_mode |= _ISR_Get_level(); |
---|
| 84 | |
---|
| 85 | *previous_mode_set = old_mode; |
---|
| 86 | |
---|
| 87 | /* |
---|
| 88 | * These are generic thread scheduling characteristics. |
---|
| 89 | */ |
---|
[b8a5abf] | 90 | preempt_enabled = false; |
---|
[05e82bd7] | 91 | if ( mask & RTEMS_PREEMPT_MASK ) { |
---|
[b8a5abf] | 92 | bool is_preempt_enabled = _Modes_Is_preempt( mode_set ); |
---|
[05e82bd7] | 93 | |
---|
[b8a5abf] | 94 | preempt_enabled = !executing->is_preemptible && is_preempt_enabled; |
---|
| 95 | executing->is_preemptible = is_preempt_enabled; |
---|
[05e82bd7] | 96 | } |
---|
[c4d69e2] | 97 | |
---|
| 98 | if ( mask & RTEMS_TIMESLICE_MASK ) { |
---|
[c0f4682] | 99 | if ( _Modes_Is_timeslice(mode_set) ) { |
---|
[c4d69e2] | 100 | executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE; |
---|
[e785fbaa] | 101 | executing->cpu_time_budget = |
---|
| 102 | rtems_configuration_get_ticks_per_timeslice(); |
---|
[c0f4682] | 103 | } else |
---|
[c4d69e2] | 104 | executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE; |
---|
| 105 | } |
---|
| 106 | |
---|
| 107 | /* |
---|
| 108 | * Set the new interrupt level |
---|
| 109 | */ |
---|
[d2711c37] | 110 | if ( mask & RTEMS_INTERRUPT_MASK ) { |
---|
[c4d69e2] | 111 | _Modes_Set_interrupt_level( mode_set ); |
---|
[d2711c37] | 112 | } |
---|
[c4d69e2] | 113 | |
---|
| 114 | /* |
---|
| 115 | * This is specific to the RTEMS API |
---|
| 116 | */ |
---|
[eaef4657] | 117 | needs_asr_dispatching = false; |
---|
[c4d69e2] | 118 | if ( mask & RTEMS_ASR_MASK ) { |
---|
[7a34ca37] | 119 | bool is_asr_enabled = !_Modes_Is_asr_disabled( mode_set ); |
---|
| 120 | |
---|
[105b4e6] | 121 | _Thread_State_acquire( executing, &lock_context ); |
---|
| 122 | |
---|
[c4d69e2] | 123 | if ( is_asr_enabled != asr->is_enabled ) { |
---|
| 124 | asr->is_enabled = is_asr_enabled; |
---|
[bb2ad039] | 125 | |
---|
| 126 | if ( _ASR_Swap_signals( asr ) != 0 ) { |
---|
[484a769] | 127 | needs_asr_dispatching = true; |
---|
[6fd1bdb7] | 128 | _Thread_Add_post_switch_action( |
---|
| 129 | executing, |
---|
[df55d07f] | 130 | &api->Signal_action, |
---|
| 131 | _Signal_Action_handler |
---|
[6fd1bdb7] | 132 | ); |
---|
[c4d69e2] | 133 | } |
---|
| 134 | } |
---|
[105b4e6] | 135 | |
---|
| 136 | _Thread_State_release( executing, &lock_context ); |
---|
[c4d69e2] | 137 | } |
---|
| 138 | |
---|
[b8a5abf] | 139 | if ( preempt_enabled || needs_asr_dispatching ) { |
---|
[f5bb2991] | 140 | Per_CPU_Control *cpu_self; |
---|
[b8a5abf] | 141 | |
---|
[f5bb2991] | 142 | cpu_self = _Thread_Dispatch_disable(); |
---|
[bd12dda] | 143 | _Thread_State_acquire( executing, &lock_context ); |
---|
[b8a5abf] | 144 | _Scheduler_Schedule( executing ); |
---|
[bd12dda] | 145 | _Thread_State_release( executing, &lock_context ); |
---|
[ed24ed4e] | 146 | _Thread_Dispatch_direct( cpu_self ); |
---|
[b8a5abf] | 147 | } |
---|
[c4d69e2] | 148 | |
---|
| 149 | return RTEMS_SUCCESSFUL; |
---|
| 150 | } |
---|