diff options
Diffstat (limited to 'include/rtems/score/threaddispatch.h')
-rw-r--r-- | include/rtems/score/threaddispatch.h | 380 |
1 files changed, 380 insertions, 0 deletions
diff --git a/include/rtems/score/threaddispatch.h b/include/rtems/score/threaddispatch.h new file mode 100644 index 0000000000..4ef5538f7e --- /dev/null +++ b/include/rtems/score/threaddispatch.h @@ -0,0 +1,380 @@ +/** + * @brief Constants and Structures Related with Thread Dispatch + */ + +/* + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifndef _RTEMS_SCORE_THREADDISPATCH_H +#define _RTEMS_SCORE_THREADDISPATCH_H + +#include <rtems/score/percpu.h> +#include <rtems/score/isrlock.h> +#include <rtems/score/profiling.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if defined(RTEMS_HEAVY_STACK_DEBUG) || \ + defined(RTEMS_HEAVY_MALLOC_DEBUG) + #define __THREAD_DO_NOT_INLINE_DISABLE_DISPATCH__ +#endif + +#if defined(RTEMS_SMP) || \ + (CPU_INLINE_ENABLE_DISPATCH == FALSE) || \ + (__RTEMS_DO_NOT_INLINE_THREAD_ENABLE_DISPATCH__ == 1) + #define __THREAD_DO_NOT_INLINE_ENABLE_DISPATCH__ +#endif + +/** + * @addtogroup ScoreThread + * + * @{ + */ + +/** + * @brief Indicates if the executing thread is inside a thread dispatch + * critical section. + * + * @retval true Thread dispatching is enabled. + * @retval false The executing thread is inside a thread dispatch critical + * section and dispatching is not allowed. + */ +RTEMS_INLINE_ROUTINE bool _Thread_Dispatch_is_enabled(void) +{ + bool enabled; + +#if defined(RTEMS_SMP) + ISR_Level level; + + _ISR_Disable_without_giant( level ); +#endif + + enabled = _Thread_Dispatch_disable_level == 0; + +#if defined(RTEMS_SMP) + _ISR_Enable_without_giant( level ); +#endif + + return enabled; +} + +/** + * @brief Gets thread dispatch disable level. + * + * @return The value of the thread dispatch level. + */ +RTEMS_INLINE_ROUTINE uint32_t _Thread_Dispatch_get_disable_level(void) +{ + return _Thread_Dispatch_disable_level; +} + +/** + * @brief Thread dispatch initialization. + * + * This routine initializes the thread dispatching subsystem. + */ +RTEMS_INLINE_ROUTINE void _Thread_Dispatch_initialization( void ) +{ + _Thread_Dispatch_disable_level = 1; +} + +#if defined(RTEMS_SMP) + /** + * @brief Acquires the giant lock. + * + * The giant lock is a recursive SMP lock protecting nearly all operating + * system services. + * + * This lock is implicitly acquired in + * _Thread_Dispatch_increment_disable_level(). + * + * Thread dispatching must be disabled before the Giant lock can be acquired + * and must no be enabled while owning the Giant lock. The thread dispatch + * disable level is not altered by this function. + * + * @param[in] cpu_self The current processor. + */ + void _Giant_Acquire( Per_CPU_Control *cpu_self ); + + /** + * @brief Releases the giant lock. + * + * This lock is implicitly released in + * _Thread_Dispatch_decrement_disable_level(). + * + * The thread dispatch disable level is not altered by this function. + * + * @param[in] cpu_self The current processor. + */ + void _Giant_Release( Per_CPU_Control *cpu_self ); + + /** + * @brief Releases the giant lock completely if held by the executing processor. + * + * The thread dispatch disable level is not altered by this function. + * + * The only use case for this operation is in _SMP_Request_shutdown(). + * + * @param[in] cpu_self The current processor. + */ + void _Giant_Drop( Per_CPU_Control *cpu_self ); + + /** + * @brief Increments the thread dispatch level. + * + * This rountine increments the thread dispatch level + */ + uint32_t _Thread_Dispatch_increment_disable_level(void); + + /** + * @brief Decrements the thread dispatch level. + * + * This routine decrements the thread dispatch level. + */ + uint32_t _Thread_Dispatch_decrement_disable_level(void); +#else /* RTEMS_SMP */ + /** + * @brief Increase thread dispatch disable level. + * + * This rountine increments the thread dispatch level + */ + RTEMS_INLINE_ROUTINE uint32_t _Thread_Dispatch_increment_disable_level(void) + { + uint32_t disable_level = _Thread_Dispatch_disable_level; +#if defined( RTEMS_PROFILING ) + ISR_Level level; + + _ISR_Disable( level ); + _Profiling_Thread_dispatch_disable( _Per_CPU_Get(), disable_level ); +#endif + + ++disable_level; + _Thread_Dispatch_disable_level = disable_level; + +#if defined( RTEMS_PROFILING ) + _ISR_Enable( level ); +#endif + + return disable_level; + } + + /** + * @brief Decrease thread dispatch disable level. + * + * This routine decrements the thread dispatch level. + */ + RTEMS_INLINE_ROUTINE uint32_t _Thread_Dispatch_decrement_disable_level(void) + { + uint32_t disable_level = _Thread_Dispatch_disable_level; +#if defined( RTEMS_PROFILING ) + ISR_Level level; + + _ISR_Disable( level ); +#endif + + --disable_level; + _Thread_Dispatch_disable_level = disable_level; + +#if defined( RTEMS_PROFILING ) + _Profiling_Thread_dispatch_enable( _Per_CPU_Get(), disable_level ); + _ISR_Enable( level ); +#endif + + return disable_level; + } + + RTEMS_INLINE_ROUTINE void _Giant_Acquire( Per_CPU_Control *cpu_self ) + { + (void) cpu_self; + } + + RTEMS_INLINE_ROUTINE void _Giant_Release( Per_CPU_Control *cpu_self ) + { + (void) cpu_self; + } +#endif /* RTEMS_SMP */ + +/** + * @brief Performs a thread dispatch if necessary. + * + * This routine is responsible for transferring control of the processor from + * the executing thread to the heir thread. Once the heir is running an + * attempt is made to run the pending post-switch thread actions. + * + * As part of this process, it is responsible for the following actions + * - update timing information of the executing thread, + * - save the context of the executing thread, + * - invokation of the thread switch user extensions, + * - restore the context of the heir thread, and + * - run of pending post-switch thread actions of the resulting executing + * thread. + * + * On entry the thread dispatch level must be equal to zero. + */ +void _Thread_Dispatch( void ); + +/** + * @brief Performs a thread dispatch on the current processor. + * + * On entry the thread dispatch disable level must be equal to one and + * interrupts must be disabled. + * + * This function assumes that a thread dispatch is necessary. + * + * @param[in] cpu_self The current processor. + * @param[in] level The previous interrupt level. + * + * @see _Thread_Dispatch(). + */ +void _Thread_Do_dispatch( Per_CPU_Control *cpu_self, ISR_Level level ); + +/** + * @brief Disables thread dispatching inside a critical section (interrupts + * disabled). + * + * This function does not acquire the Giant lock. + * + * @param[in] lock_context The lock context of the corresponding + * _ISR_lock_ISR_disable() that started the critical section. + * + * @return The current processor. + */ +RTEMS_INLINE_ROUTINE Per_CPU_Control *_Thread_Dispatch_disable_critical( + const ISR_lock_Context *lock_context +) +{ + Per_CPU_Control *cpu_self; + uint32_t disable_level; + + cpu_self = _Per_CPU_Get(); + disable_level = cpu_self->thread_dispatch_disable_level; + _Profiling_Thread_dispatch_disable_critical( + cpu_self, + disable_level, + lock_context + ); + cpu_self->thread_dispatch_disable_level = disable_level + 1; + + return cpu_self; +} + +/** + * @brief Disables thread dispatching. + * + * This function does not acquire the Giant lock. + * + * @return The current processor. + */ +RTEMS_INLINE_ROUTINE Per_CPU_Control *_Thread_Dispatch_disable( void ) +{ + Per_CPU_Control *cpu_self; + ISR_lock_Context lock_context; + +#if defined( RTEMS_SMP ) || defined( RTEMS_PROFILING ) + _ISR_lock_ISR_disable( &lock_context ); +#endif + + cpu_self = _Thread_Dispatch_disable_critical( &lock_context ); + +#if defined( RTEMS_SMP ) || defined( RTEMS_PROFILING ) + _ISR_lock_ISR_enable( &lock_context ); +#endif + + return cpu_self; +} + +/** + * @brief Enables thread dispatching. + * + * May perfrom a thread dispatch if necessary as a side-effect. + * + * This function does not release the Giant lock. + * + * @param[in] cpu_self The current processor. + */ +RTEMS_INLINE_ROUTINE void _Thread_Dispatch_enable( Per_CPU_Control *cpu_self ) +{ + uint32_t disable_level = cpu_self->thread_dispatch_disable_level; + + if ( disable_level == 1 ) { + ISR_Level level; + + _ISR_Disable_without_giant( level ); + + if ( cpu_self->dispatch_necessary ) { + _Thread_Do_dispatch( cpu_self, level ); + } else { + cpu_self->thread_dispatch_disable_level = 0; + _Profiling_Thread_dispatch_enable( cpu_self, 0 ); + } + + _ISR_Enable_without_giant( level ); + } else { + cpu_self->thread_dispatch_disable_level = disable_level - 1; + } +} + +/** + * @brief Disables thread dispatching and acquires the Giant lock. + */ +#if defined ( __THREAD_DO_NOT_INLINE_DISABLE_DISPATCH__ ) +void _Thread_Disable_dispatch( void ); +#else +RTEMS_INLINE_ROUTINE void _Thread_Disable_dispatch( void ) +{ + _Thread_Dispatch_increment_disable_level(); + RTEMS_COMPILER_MEMORY_BARRIER(); +} +#endif + +RTEMS_INLINE_ROUTINE void _Thread_Enable_dispatch_body( void ) +{ + Per_CPU_Control *cpu_self = _Per_CPU_Get(); + + _Giant_Release( cpu_self ); + _Thread_Dispatch_enable( cpu_self ); +} + +/** + * @brief Enables thread dispatching and releases the Giant lock. + * + * May perfrom a thread dispatch if necessary as a side-effect. + */ +#if defined ( __THREAD_DO_NOT_INLINE_ENABLE_DISPATCH__ ) + void _Thread_Enable_dispatch( void ); +#else + /* inlining of enable dispatching must be true */ + RTEMS_INLINE_ROUTINE void _Thread_Enable_dispatch( void ) + { + RTEMS_COMPILER_MEMORY_BARRIER(); + _Thread_Enable_dispatch_body(); + } +#endif + +/** + * @brief Enables thread dispatching and releases the Giant lock. + * + * @warning A thread dispatch is not performed as a side-effect. Use this + * function with + */ +RTEMS_INLINE_ROUTINE void _Thread_Unnest_dispatch( void ) +{ + RTEMS_COMPILER_MEMORY_BARRIER(); + _Thread_Dispatch_decrement_disable_level(); +} + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _RTEMS_SCORE_THREADDISPATCH_H */ |