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/chain.h>
#include <rtems/score/priority.h>
#include <rtems/score/smplockseq.h>
#include <rtems/score/isrlock.h>
/**
* @addtogroup RTEMSScoreScheduler
@@ -197,14 +197,20 @@ struct Scheduler_Node {
* least-significant bit which indicates if the thread should be appended
* (bit set) or prepended (bit cleared) to its priority group, see
* 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;
#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
} Priority;
};

View File

@@ -77,12 +77,15 @@ extern "C" {
( ( ( 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[out] node The node to initialize.
* @param the_thread The thread for the initialization of @a node.
* @param priority The priority value for @a node.
* @param scheduler is the scheduler of the node.
*
* @param[out] node is the node to initialize.
*
* @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(
const struct _Scheduler_Control *scheduler,
@@ -100,13 +103,36 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Node_do_initialize(
node->Wait.Priority.scheduler = scheduler;
node->user = the_thread;
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
(void) scheduler;
(void) the_thread;
#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.
*
@@ -148,17 +174,18 @@ RTEMS_INLINE_ROUTINE Priority_Control _Scheduler_Node_get_priority(
{
Priority_Control priority;
#if defined(RTEMS_SMP)
unsigned int seq;
#if defined(RTEMS_SMP) && CPU_SIZEOF_POINTER == 8
priority = _Atomic_Fetch_add_ulong(
&node->Priority.value,
0,
ATOMIC_ORDER_RELAXED
);
#else
ISR_lock_Context lock_context;
do {
seq = _SMP_sequence_lock_Read_begin( &node->Priority.Lock );
#endif
priority = node->Priority.value;
#if defined(RTEMS_SMP)
} while ( _SMP_sequence_lock_Read_retry( &node->Priority.Lock, seq ) );
_ISR_lock_Acquire( &node->Priority.Lock, &lock_context );
priority = node->Priority.value;
_ISR_lock_Release( &node->Priority.Lock, &lock_context );
#endif
return priority;
@@ -180,16 +207,18 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Node_set_priority(
Priority_Group_order group_order
)
{
#if defined(RTEMS_SMP)
unsigned int seq;
seq = _SMP_sequence_lock_Write_begin( &node->Priority.Lock );
#endif
#if defined(RTEMS_SMP) && CPU_SIZEOF_POINTER == 8
_Atomic_Store_ulong(
&node->Priority.value,
new_priority | (Priority_Control) group_order,
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 );
#if defined(RTEMS_SMP)
_SMP_sequence_lock_Write_end( &node->Priority.Lock, seq );
_ISR_lock_Release( &node->Priority.Lock, &lock_context );
#endif
}

View File

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