seqlock: Improve seqlock performance on SMP platforms.

The optimization reduces one judgment in read operations, improving write performance by 3% and read performance by 10%.

Signed-off-by: hujun5 <hujun5@xiaomi.com>
This commit is contained in:
hujun5
2025-10-10 13:29:31 +08:00
committed by Alan C. Assis
parent d576363fc4
commit 5df2072876
+6 -19
View File
@@ -29,16 +29,13 @@
#include <nuttx/atomic.h> #include <nuttx/atomic.h>
#include <nuttx/irq.h> #include <nuttx/irq.h>
#include <nuttx/arch.h>
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
#ifdef CONFIG_SMP
#define SEQLOCK_INITIALIZER { 1u, 1u }
#else
#define SEQLOCK_INITIALIZER { 0u } #define SEQLOCK_INITIALIZER { 0u }
#endif
/**************************************************************************** /****************************************************************************
* Public Data Types * Public Data Types
@@ -52,7 +49,6 @@ typedef struct seqclock
{ {
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
atomic_t sequence; atomic_t sequence;
uint32_t next_sequence;
#else #else
volatile uint32_t sequence; volatile uint32_t sequence;
#endif #endif
@@ -88,8 +84,7 @@ extern "C"
static inline_function void seqlock_init(FAR seqcount_t *s) static inline_function void seqlock_init(FAR seqcount_t *s)
{ {
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
atomic_init(&s->sequence, 1u); atomic_init(&s->sequence, 0u);
s->next_sequence = 1u;
#else #else
s->sequence = 0u; s->sequence = 0u;
#endif #endif
@@ -116,13 +111,7 @@ uint32_t read_seqbegin(FAR const seqcount_t *s)
uint32_t seq; uint32_t seq;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
do seq = atomic_read_acquire(&s->sequence) & ~1;
{
/* Ensure no load operation is re-ordered before the acquire load. */
seq = atomic_read_acquire(&s->sequence);
}
while (seq == 0u);
#else #else
seq = s->sequence; seq = s->sequence;
SMP_RMB(); SMP_RMB();
@@ -189,11 +178,11 @@ irqstate_t write_seqlock_irqsave(FAR seqcount_t *s)
{ {
uint32_t sequence = atomic_read(&s->sequence); uint32_t sequence = atomic_read(&s->sequence);
if (predict_true(sequence != 0u)) if (predict_true((sequence & 1u) == 0u))
{ {
/* Try to acquire the lock ownership. */ /* Try to acquire the lock ownership. */
if (atomic_cmpxchg_acquire(&s->sequence, &sequence, 0u)) if (atomic_cmpxchg_acquire(&s->sequence, &sequence, sequence + 1u))
{ {
break; break;
} }
@@ -228,9 +217,7 @@ static inline_function
void write_sequnlock_irqrestore(seqcount_t *s, irqstate_t flags) void write_sequnlock_irqrestore(seqcount_t *s, irqstate_t flags)
{ {
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
uint32_t next = s->next_sequence + 2; atomic_set_release(&s->sequence, s->sequence + 1u);
s->next_sequence = next;
atomic_set_release(&s->sequence, next);
#endif #endif
up_irq_restore(flags); up_irq_restore(flags);
} }