From 4c8a0acc3dd536b3a5684ced8df663931081ba09 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Wed, 4 Mar 2015 08:02:09 +0100 Subject: score: Add thread wait flags Update #2273. --- cpukit/score/include/rtems/score/thread.h | 30 +++++ cpukit/score/include/rtems/score/threadimpl.h | 161 ++++++++++++++++++++++++++ cpukit/score/src/threadinitialize.c | 2 + 3 files changed, 193 insertions(+) diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h index 299bac6df5..4984949377 100644 --- a/cpukit/score/include/rtems/score/thread.h +++ b/cpukit/score/include/rtems/score/thread.h @@ -21,6 +21,7 @@ #ifndef _RTEMS_SCORE_THREAD_H #define _RTEMS_SCORE_THREAD_H +#include #include #if defined(RTEMS_MULTIPROCESSING) #include @@ -261,6 +262,25 @@ typedef union { const void *immutable_object; } Thread_Wait_information_Object_argument_type; +/** + * @brief This type is able to contain several flags used to control the wait + * class and state of a thread. + * + * The mutually exclusive wait class flags are + * - @ref THREAD_WAIT_CLASS_EVENT, + * - @ref THREAD_WAIT_CLASS_SYSTEM_EVENT, and + * - @ref THREAD_WAIT_CLASS_OBJECT. + * + * The mutually exclusive wait state flags are + * - @ref THREAD_WAIT_STATE_INTEND_TO_BLOCK, + * - @ref THREAD_WAIT_STATE_BLOCKED, + * - @ref THREAD_WAIT_STATE_SATISFIED, + * - @ref THREAD_WAIT_STATE_TIMEOUT, + * - @ref THREAD_WAIT_STATE_INTERRUPT_SATISFIED, and + * - @ref THREAD_WAIT_STATE_INTERRUPT_TIMEOUT, + */ +typedef unsigned int Thread_Wait_flags; + /** * @brief Information required to manage a thread while it is blocked. * @@ -288,6 +308,16 @@ typedef struct { /** This field points to the thread queue on which this thread is blocked. */ Thread_queue_Control *queue; + + /** + * @brief This field contains several flags used to control the wait class + * and state of a thread in case fine-grained locking is used. + */ +#if defined(RTEMS_SMP) + Atomic_Uint flags; +#else + Thread_Wait_flags flags; +#endif } Thread_Wait_information; /** diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h index 19c22bcc46..84c22f94ed 100644 --- a/cpukit/score/include/rtems/score/threadimpl.h +++ b/cpukit/score/include/rtems/score/threadimpl.h @@ -923,6 +923,167 @@ RTEMS_INLINE_ROUTINE bool _Thread_Owns_resources( return owns_resources; } +/** + * @brief The initial thread wait flags value set by _Thread_Initialize(). + */ +#define THREAD_WAIT_FLAGS_INITIAL 0x0U + +/** + * @brief Mask to get the thread wait state flags. + */ +#define THREAD_WAIT_STATE_MASK 0xffU + +/** + * @brief Indicates that the thread begins with the blocking operation. + * + * A blocking operation consists of an optional watchdog initialization and the + * setting of the appropriate thread blocking state with the corresponding + * scheduler block operation. + */ +#define THREAD_WAIT_STATE_INTEND_TO_BLOCK 0x1U + +/** + * @brief Indicates that the thread completed the blocking operation. + */ +#define THREAD_WAIT_STATE_BLOCKED 0x2U + +/** + * @brief Indicates that the thread progress condition is satisfied and it is + * ready to resume execution. + */ +#define THREAD_WAIT_STATE_SATISFIED 0x4U + +/** + * @brief Indicates that a timeout occurred and the thread is ready to resume + * execution. + */ +#define THREAD_WAIT_STATE_TIMEOUT 0x8U + +/** + * @brief Indicates that the thread progress condition was satisfied during the + * blocking operation and it is ready to resume execution. + */ +#define THREAD_WAIT_STATE_INTERRUPT_SATISFIED 0x10U + +/** + * @brief Indicates that a timeout occurred during the blocking operation and + * the thread is ready to resume execution. + */ +#define THREAD_WAIT_STATE_INTERRUPT_TIMEOUT 0x20U + +/** + * @brief Mask to get the thread wait class flags. + */ +#define THREAD_WAIT_CLASS_MASK 0xff00U + +/** + * @brief Indicates that the thread waits for an event. + */ +#define THREAD_WAIT_CLASS_EVENT 0x100U + +/** + * @brief Indicates that the thread waits for a system event. + */ +#define THREAD_WAIT_CLASS_SYSTEM_EVENT 0x200U + +/** + * @brief Indicates that the thread waits for a object. + */ +#define THREAD_WAIT_CLASS_OBJECT 0x400U + +RTEMS_INLINE_ROUTINE void _Thread_Wait_flags_set( + Thread_Control *the_thread, + Thread_Wait_flags flags +) +{ +#if defined(RTEMS_SMP) + _Atomic_Store_uint( &the_thread->Wait.flags, flags, ATOMIC_ORDER_RELAXED ); +#else + the_thread->Wait.flags = flags; +#endif +} + +RTEMS_INLINE_ROUTINE Thread_Wait_flags _Thread_Wait_flags_get( + const Thread_Control *the_thread +) +{ +#if defined(RTEMS_SMP) + return _Atomic_Load_uint( &the_thread->Wait.flags, ATOMIC_ORDER_RELAXED ); +#else + return the_thread->Wait.flags; +#endif +} + +/** + * @brief Tries to change the thread wait flags inside a critical section + * (interrupts disabled). + * + * In case the wait flags are equal to the expected wait flags, then the wait + * flags are set to the desired wait flags. + * + * @param[in] the_thread The thread. + * @param[in] expected_flags The expected wait flags. + * @param[in] desired_flags The desired wait flags. + * + * @retval true The wait flags were equal to the expected wait flags. + * @retval false Otherwise. + */ +RTEMS_INLINE_ROUTINE bool _Thread_Wait_flags_try_change_critical( + Thread_Control *the_thread, + Thread_Wait_flags expected_flags, + Thread_Wait_flags desired_flags +) +{ +#if defined(RTEMS_SMP) + return _Atomic_Compare_exchange_uint( + &the_thread->Wait.flags, + &expected_flags, + desired_flags, + ATOMIC_ORDER_RELAXED, + ATOMIC_ORDER_RELAXED + ); +#else + bool success = the_thread->Wait.flags == expected_flags; + + if ( success ) { + the_thread->Wait.flags = desired_flags; + } + + return success; +#endif +} + +/** + * @brief Tries to change the thread wait flags. + * + * @see _Thread_Wait_flags_try_change_critical(). + */ +RTEMS_INLINE_ROUTINE bool _Thread_Wait_flags_try_change( + Thread_Control *the_thread, + Thread_Wait_flags expected_flags, + Thread_Wait_flags desired_flags +) +{ + bool success; +#if !defined(RTEMS_SMP) + ISR_Level level; + + _ISR_Disable_without_giant( level ); +#endif + + success = _Thread_Wait_flags_try_change_critical( + the_thread, + expected_flags, + desired_flags + ); + +#if !defined(RTEMS_SMP) + _ISR_Enable_without_giant( level ); +#endif + + return success; +} + RTEMS_INLINE_ROUTINE void _Thread_Debug_set_real_processor( Thread_Control *the_thread, Per_CPU_Control *cpu diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c index 508636fa51..934fea9085 100644 --- a/cpukit/score/src/threadinitialize.c +++ b/cpukit/score/src/threadinitialize.c @@ -200,6 +200,8 @@ bool _Thread_Initialize( the_thread->real_priority = priority; the_thread->Start.initial_priority = priority; + _Thread_Wait_flags_set( the_thread, THREAD_WAIT_FLAGS_INITIAL ); + _Scheduler_Node_initialize( scheduler, the_thread ); scheduler_node_initialized = true; -- cgit v1.2.3