[4fc370e] | 1 | /** |
---|
| 2 | * @brief Constants and Structures Related with Thread Dispatch |
---|
| 3 | */ |
---|
| 4 | |
---|
| 5 | /* |
---|
| 6 | * COPYRIGHT (c) 1989-2009. |
---|
| 7 | * On-Line Applications Research Corporation (OAR). |
---|
| 8 | * |
---|
| 9 | * The license and distribution terms for this file may be |
---|
| 10 | * found in the file LICENSE in this distribution or at |
---|
[c499856] | 11 | * http://www.rtems.org/license/LICENSE. |
---|
[4fc370e] | 12 | */ |
---|
| 13 | |
---|
| 14 | #ifndef _RTEMS_SCORE_THREADDISPATCH_H |
---|
| 15 | #define _RTEMS_SCORE_THREADDISPATCH_H |
---|
| 16 | |
---|
[d19cce29] | 17 | #include <rtems/score/percpu.h> |
---|
[d5423295] | 18 | #include <rtems/score/isrlock.h> |
---|
[f980561] | 19 | #include <rtems/score/profiling.h> |
---|
[4fc370e] | 20 | |
---|
| 21 | #ifdef __cplusplus |
---|
| 22 | extern "C" { |
---|
| 23 | #endif /* __cplusplus */ |
---|
| 24 | |
---|
| 25 | /** |
---|
| 26 | * @addtogroup ScoreThread |
---|
| 27 | * |
---|
| 28 | * @{ |
---|
| 29 | */ |
---|
| 30 | |
---|
[84e6f15] | 31 | #if defined(RTEMS_SMP) || ( CPU_ENABLE_ROBUST_THREAD_DISPATCH == TRUE ) |
---|
| 32 | /** |
---|
| 33 | * @brief Enables a robust thread dispatch. |
---|
| 34 | * |
---|
| 35 | * On each change of the thread dispatch disable level from one to zero the |
---|
| 36 | * interrupt status is checked. In case interrupts are disabled and SMP is |
---|
| 37 | * enabled or the CPU port needs it, then the system terminates with the fatal |
---|
| 38 | * internal error INTERNAL_ERROR_BAD_THREAD_DISPATCH_ENVIRONMENT. |
---|
| 39 | */ |
---|
| 40 | #define RTEMS_SCORE_ROBUST_THREAD_DISPATCH |
---|
| 41 | #endif |
---|
| 42 | |
---|
[49cdf40] | 43 | /** |
---|
| 44 | * @brief Indicates if the executing thread is inside a thread dispatch |
---|
| 45 | * critical section. |
---|
| 46 | * |
---|
| 47 | * @retval true Thread dispatching is enabled. |
---|
| 48 | * @retval false The executing thread is inside a thread dispatch critical |
---|
| 49 | * section and dispatching is not allowed. |
---|
| 50 | */ |
---|
| 51 | RTEMS_INLINE_ROUTINE bool _Thread_Dispatch_is_enabled(void) |
---|
| 52 | { |
---|
[d19cce29] | 53 | bool enabled; |
---|
[49cdf40] | 54 | |
---|
[4fc370e] | 55 | #if defined(RTEMS_SMP) |
---|
[d19cce29] | 56 | ISR_Level level; |
---|
[4fc370e] | 57 | |
---|
[4b04cb61] | 58 | _ISR_Local_disable( level ); |
---|
[d19cce29] | 59 | #endif |
---|
| 60 | |
---|
| 61 | enabled = _Thread_Dispatch_disable_level == 0; |
---|
| 62 | |
---|
| 63 | #if defined(RTEMS_SMP) |
---|
[4b04cb61] | 64 | _ISR_Local_enable( level ); |
---|
[d19cce29] | 65 | #endif |
---|
| 66 | |
---|
| 67 | return enabled; |
---|
| 68 | } |
---|
| 69 | |
---|
| 70 | /** |
---|
[cc69334f] | 71 | * @brief Gets thread dispatch disable level. |
---|
[d19cce29] | 72 | * |
---|
| 73 | * @return The value of the thread dispatch level. |
---|
| 74 | */ |
---|
| 75 | RTEMS_INLINE_ROUTINE uint32_t _Thread_Dispatch_get_disable_level(void) |
---|
| 76 | { |
---|
| 77 | return _Thread_Dispatch_disable_level; |
---|
| 78 | } |
---|
| 79 | |
---|
| 80 | /** |
---|
| 81 | * @brief Thread dispatch initialization. |
---|
| 82 | * |
---|
| 83 | * This routine initializes the thread dispatching subsystem. |
---|
| 84 | */ |
---|
| 85 | RTEMS_INLINE_ROUTINE void _Thread_Dispatch_initialization( void ) |
---|
| 86 | { |
---|
| 87 | _Thread_Dispatch_disable_level = 1; |
---|
| 88 | } |
---|
[4fc370e] | 89 | |
---|
| 90 | /** |
---|
[222dc775] | 91 | * @brief Performs a thread dispatch if necessary. |
---|
[4fc370e] | 92 | * |
---|
[222dc775] | 93 | * This routine is responsible for transferring control of the processor from |
---|
| 94 | * the executing thread to the heir thread. Once the heir is running an |
---|
| 95 | * attempt is made to run the pending post-switch thread actions. |
---|
[4fc370e] | 96 | * |
---|
[222dc775] | 97 | * As part of this process, it is responsible for the following actions |
---|
| 98 | * - update timing information of the executing thread, |
---|
| 99 | * - save the context of the executing thread, |
---|
| 100 | * - invokation of the thread switch user extensions, |
---|
| 101 | * - restore the context of the heir thread, and |
---|
| 102 | * - run of pending post-switch thread actions of the resulting executing |
---|
| 103 | * thread. |
---|
| 104 | * |
---|
| 105 | * On entry the thread dispatch level must be equal to zero. |
---|
[4fc370e] | 106 | */ |
---|
| 107 | void _Thread_Dispatch( void ); |
---|
| 108 | |
---|
[d78d529] | 109 | /** |
---|
| 110 | * @brief Directly do a thread dispatch. |
---|
| 111 | * |
---|
| 112 | * Must be called with a thread dispatch disable level of one, otherwise the |
---|
| 113 | * INTERNAL_ERROR_BAD_THREAD_DISPATCH_DISABLE_LEVEL will occur. This function |
---|
| 114 | * is useful for operations which synchronously block, e.g. self restart, self |
---|
| 115 | * deletion, yield, sleep. |
---|
| 116 | * |
---|
| 117 | * @param[in] cpu_self The current processor. |
---|
| 118 | * |
---|
| 119 | * @see _Thread_Dispatch(). |
---|
| 120 | */ |
---|
| 121 | void _Thread_Dispatch_direct( Per_CPU_Control *cpu_self ); |
---|
| 122 | |
---|
[222dc775] | 123 | /** |
---|
| 124 | * @brief Performs a thread dispatch on the current processor. |
---|
| 125 | * |
---|
| 126 | * On entry the thread dispatch disable level must be equal to one and |
---|
| 127 | * interrupts must be disabled. |
---|
| 128 | * |
---|
| 129 | * This function assumes that a thread dispatch is necessary. |
---|
| 130 | * |
---|
| 131 | * @param[in] cpu_self The current processor. |
---|
| 132 | * @param[in] level The previous interrupt level. |
---|
| 133 | * |
---|
| 134 | * @see _Thread_Dispatch(). |
---|
| 135 | */ |
---|
| 136 | void _Thread_Do_dispatch( Per_CPU_Control *cpu_self, ISR_Level level ); |
---|
| 137 | |
---|
[4fc370e] | 138 | /** |
---|
[1512761] | 139 | * @brief Disables thread dispatching inside a critical section (interrupts |
---|
[0475cca] | 140 | * disabled) with the current processor. |
---|
[1512761] | 141 | * |
---|
[0475cca] | 142 | * @param[in] cpu_self The current processor. |
---|
[d5423295] | 143 | * @param[in] lock_context The lock context of the corresponding |
---|
| 144 | * _ISR_lock_ISR_disable() that started the critical section. |
---|
| 145 | * |
---|
[413b9e28] | 146 | * @return The current processor. |
---|
[4fc370e] | 147 | */ |
---|
[0475cca] | 148 | RTEMS_INLINE_ROUTINE Per_CPU_Control *_Thread_Dispatch_disable_with_CPU( |
---|
| 149 | Per_CPU_Control *cpu_self, |
---|
[d5423295] | 150 | const ISR_lock_Context *lock_context |
---|
| 151 | ) |
---|
[4fc370e] | 152 | { |
---|
[0475cca] | 153 | uint32_t disable_level; |
---|
[1512761] | 154 | |
---|
[413b9e28] | 155 | disable_level = cpu_self->thread_dispatch_disable_level; |
---|
[d5423295] | 156 | _Profiling_Thread_dispatch_disable_critical( |
---|
| 157 | cpu_self, |
---|
| 158 | disable_level, |
---|
| 159 | lock_context |
---|
| 160 | ); |
---|
[1512761] | 161 | cpu_self->thread_dispatch_disable_level = disable_level + 1; |
---|
[413b9e28] | 162 | |
---|
| 163 | return cpu_self; |
---|
[4fc370e] | 164 | } |
---|
| 165 | |
---|
[0475cca] | 166 | /** |
---|
| 167 | * @brief Disables thread dispatching inside a critical section (interrupts |
---|
| 168 | * disabled). |
---|
| 169 | * |
---|
| 170 | * @param[in] lock_context The lock context of the corresponding |
---|
| 171 | * _ISR_lock_ISR_disable() that started the critical section. |
---|
| 172 | * |
---|
| 173 | * @return The current processor. |
---|
| 174 | */ |
---|
| 175 | RTEMS_INLINE_ROUTINE Per_CPU_Control *_Thread_Dispatch_disable_critical( |
---|
| 176 | const ISR_lock_Context *lock_context |
---|
| 177 | ) |
---|
| 178 | { |
---|
| 179 | return _Thread_Dispatch_disable_with_CPU( _Per_CPU_Get(), lock_context ); |
---|
| 180 | } |
---|
| 181 | |
---|
[1512761] | 182 | /** |
---|
| 183 | * @brief Disables thread dispatching. |
---|
| 184 | * |
---|
| 185 | * @return The current processor. |
---|
| 186 | */ |
---|
| 187 | RTEMS_INLINE_ROUTINE Per_CPU_Control *_Thread_Dispatch_disable( void ) |
---|
[d2ffb7dc] | 188 | { |
---|
[d5423295] | 189 | Per_CPU_Control *cpu_self; |
---|
| 190 | ISR_lock_Context lock_context; |
---|
[1512761] | 191 | |
---|
| 192 | #if defined( RTEMS_SMP ) || defined( RTEMS_PROFILING ) |
---|
[d5423295] | 193 | _ISR_lock_ISR_disable( &lock_context ); |
---|
[1512761] | 194 | #endif |
---|
[222dc775] | 195 | |
---|
[d5423295] | 196 | cpu_self = _Thread_Dispatch_disable_critical( &lock_context ); |
---|
[222dc775] | 197 | |
---|
[1512761] | 198 | #if defined( RTEMS_SMP ) || defined( RTEMS_PROFILING ) |
---|
[d5423295] | 199 | _ISR_lock_ISR_enable( &lock_context ); |
---|
[222dc775] | 200 | #endif |
---|
| 201 | |
---|
[1512761] | 202 | return cpu_self; |
---|
| 203 | } |
---|
| 204 | |
---|
| 205 | /** |
---|
| 206 | * @brief Enables thread dispatching. |
---|
| 207 | * |
---|
[ba0e9631] | 208 | * May perform a thread dispatch if necessary as a side-effect. |
---|
[1512761] | 209 | * |
---|
| 210 | * @param[in] cpu_self The current processor. |
---|
| 211 | */ |
---|
[ba0e9631] | 212 | void _Thread_Dispatch_enable( Per_CPU_Control *cpu_self ); |
---|
[d2ffb7dc] | 213 | |
---|
[d2bacb6c] | 214 | /** |
---|
| 215 | * @brief Unnests thread dispatching. |
---|
| 216 | * |
---|
| 217 | * @param[in] cpu_self The current processor. |
---|
| 218 | */ |
---|
| 219 | RTEMS_INLINE_ROUTINE void _Thread_Dispatch_unnest( Per_CPU_Control *cpu_self ) |
---|
| 220 | { |
---|
[fe7012a0] | 221 | _Assert( cpu_self->thread_dispatch_disable_level > 0 ); |
---|
[d2bacb6c] | 222 | --cpu_self->thread_dispatch_disable_level; |
---|
| 223 | } |
---|
| 224 | |
---|
[9bb3ce39] | 225 | /** |
---|
| 226 | * @brief Requests a thread dispatch on the target processor. |
---|
| 227 | * |
---|
| 228 | * @param[in] cpu_self The current processor. |
---|
| 229 | * @param[in] cpu_target The target processor to request a thread dispatch. |
---|
| 230 | */ |
---|
| 231 | RTEMS_INLINE_ROUTINE void _Thread_Dispatch_request( |
---|
| 232 | Per_CPU_Control *cpu_self, |
---|
| 233 | Per_CPU_Control *cpu_target |
---|
| 234 | ) |
---|
| 235 | { |
---|
| 236 | #if defined( RTEMS_SMP ) |
---|
| 237 | if ( cpu_self == cpu_target ) { |
---|
| 238 | cpu_self->dispatch_necessary = true; |
---|
| 239 | } else { |
---|
| 240 | _Atomic_Fetch_or_ulong( &cpu_target->message, 0, ATOMIC_ORDER_RELEASE ); |
---|
| 241 | _CPU_SMP_Send_interrupt( _Per_CPU_Get_index( cpu_target ) ); |
---|
| 242 | } |
---|
| 243 | #else |
---|
| 244 | cpu_self->dispatch_necessary = true; |
---|
| 245 | (void) cpu_target; |
---|
| 246 | #endif |
---|
| 247 | } |
---|
| 248 | |
---|
[4fc370e] | 249 | /** @} */ |
---|
| 250 | |
---|
| 251 | #ifdef __cplusplus |
---|
| 252 | } |
---|
| 253 | #endif /* __cplusplus */ |
---|
| 254 | |
---|
| 255 | #endif /* _RTEMS_SCORE_THREADDISPATCH_H */ |
---|