score: Replace the single use of a sequence lock

In SMP configurations, on 64-bit architectures use plain atomic
operations to set/get the priority value of a scheduler node.  On 32-bit
architectures use an ISR lock.  Using a sequence lock has no real
benefit since it uses atomic read-modify-write operations for both the
read and the write lock.  Simply use a ticket lock instead so that only
one SMP synchronization primitive is used for everything.
This commit is contained in:
Sebastian Huber
2021-08-10 16:28:24 +02:00
parent a5aaf20a2d
commit a0ec14ca22
3 changed files with 65 additions and 30 deletions

View File

@@ -28,7 +28,7 @@
#include <rtems/score/basedefs.h> #include <rtems/score/basedefs.h>
#include <rtems/score/chain.h> #include <rtems/score/chain.h>
#include <rtems/score/priority.h> #include <rtems/score/priority.h>
#include <rtems/score/smplockseq.h> #include <rtems/score/isrlock.h>
/** /**
* @addtogroup RTEMSScoreScheduler * @addtogroup RTEMSScoreScheduler
@@ -197,14 +197,20 @@ struct Scheduler_Node {
* least-significant bit which indicates if the thread should be appended * least-significant bit which indicates if the thread should be appended
* (bit set) or prepended (bit cleared) to its priority group, see * (bit set) or prepended (bit cleared) to its priority group, see
* SCHEDULER_PRIORITY_APPEND(). * SCHEDULER_PRIORITY_APPEND().
*
* @see _Scheduler_Node_get_priority() and _Scheduler_Node_set_priority().
*/ */
#if defined(RTEMS_SMP) && CPU_SIZEOF_POINTER == 8
Atomic_Ulong value;
#else
Priority_Control value; Priority_Control value;
#endif
#if defined(RTEMS_SMP) #if defined(RTEMS_SMP) && CPU_SIZEOF_POINTER != 8
/** /**
* @brief Sequence lock to synchronize priority value updates. * @brief The lock protects the priority value.
*/ */
SMP_sequence_lock_Control Lock; ISR_lock_Control Lock;
#endif #endif
} Priority; } Priority;
}; };

View File

@@ -77,12 +77,15 @@ extern "C" {
( ( ( priority ) & ( (Priority_Control) PRIORITY_GROUP_LAST ) ) != 0 ) ( ( ( priority ) & ( (Priority_Control) PRIORITY_GROUP_LAST ) ) != 0 )
/** /**
* @brief Initializes a node. * @brief Initializes the node.
* *
* @param scheduler The scheduler for the initialization of @a node. * @param scheduler is the scheduler of the node.
* @param[out] node The node to initialize. *
* @param the_thread The thread for the initialization of @a node. * @param[out] node is the node to initialize.
* @param priority The priority value for @a node. *
* @param[in, out] the_thread is the thread of the node.
*
* @param priority is the initial priority of the node.
*/ */
RTEMS_INLINE_ROUTINE void _Scheduler_Node_do_initialize( RTEMS_INLINE_ROUTINE void _Scheduler_Node_do_initialize(
const struct _Scheduler_Control *scheduler, const struct _Scheduler_Control *scheduler,
@@ -100,13 +103,36 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Node_do_initialize(
node->Wait.Priority.scheduler = scheduler; node->Wait.Priority.scheduler = scheduler;
node->user = the_thread; node->user = the_thread;
node->idle = NULL; node->idle = NULL;
_SMP_sequence_lock_Initialize( &node->Priority.Lock ); #if CPU_SIZEOF_POINTER != 8
_ISR_lock_Initialize( &node->Priority.Lock, "Scheduler Node Priority" );
#endif
#else #else
(void) scheduler; (void) scheduler;
(void) the_thread; (void) the_thread;
#endif #endif
} }
/**
* @brief Destroys the node.
*
* @param scheduler is the scheduler of the node.
*
* @param[in, out] node is the node to destroy.
*/
RTEMS_INLINE_ROUTINE void _Scheduler_Node_do_destroy(
const struct _Scheduler_Control *scheduler,
Scheduler_Node *node
)
{
(void) scheduler;
#if defined(RTEMS_SMP) && CPU_SIZEOF_POINTER != 8
_ISR_lock_Destroy( &node->Priority.Lock );
#else
(void) node;
#endif
}
/** /**
* @brief Gets the scheduler of the node. * @brief Gets the scheduler of the node.
* *
@@ -148,17 +174,18 @@ RTEMS_INLINE_ROUTINE Priority_Control _Scheduler_Node_get_priority(
{ {
Priority_Control priority; Priority_Control priority;
#if defined(RTEMS_SMP) #if defined(RTEMS_SMP) && CPU_SIZEOF_POINTER == 8
unsigned int seq; priority = _Atomic_Fetch_add_ulong(
&node->Priority.value,
do { 0,
seq = _SMP_sequence_lock_Read_begin( &node->Priority.Lock ); ATOMIC_ORDER_RELAXED
#endif );
#else
ISR_lock_Context lock_context;
_ISR_lock_Acquire( &node->Priority.Lock, &lock_context );
priority = node->Priority.value; priority = node->Priority.value;
_ISR_lock_Release( &node->Priority.Lock, &lock_context );
#if defined(RTEMS_SMP)
} while ( _SMP_sequence_lock_Read_retry( &node->Priority.Lock, seq ) );
#endif #endif
return priority; return priority;
@@ -180,16 +207,18 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Node_set_priority(
Priority_Group_order group_order Priority_Group_order group_order
) )
{ {
#if defined(RTEMS_SMP) #if defined(RTEMS_SMP) && CPU_SIZEOF_POINTER == 8
unsigned int seq; _Atomic_Store_ulong(
&node->Priority.value,
seq = _SMP_sequence_lock_Write_begin( &node->Priority.Lock ); new_priority | (Priority_Control) group_order,
#endif ATOMIC_ORDER_RELAXED
);
#else
ISR_lock_Context lock_context;
_ISR_lock_Acquire( &node->Priority.Lock, &lock_context );
node->Priority.value = new_priority | ( (Priority_Control) group_order ); node->Priority.value = new_priority | ( (Priority_Control) group_order );
_ISR_lock_Release( &node->Priority.Lock, &lock_context );
#if defined(RTEMS_SMP)
_SMP_sequence_lock_Write_end( &node->Priority.Lock, seq );
#endif #endif
} }

View File

@@ -21,12 +21,12 @@
#endif #endif
#include <rtems/score/scheduler.h> #include <rtems/score/scheduler.h>
#include <rtems/score/schedulernodeimpl.h>
void _Scheduler_default_Node_destroy( void _Scheduler_default_Node_destroy(
const Scheduler_Control *scheduler, const Scheduler_Control *scheduler,
Scheduler_Node *node Scheduler_Node *node
) )
{ {
(void) scheduler; _Scheduler_Node_do_destroy( scheduler, node );
(void) node;
} }