mirror of
https://github.com/apache/nuttx.git
synced 2026-05-30 21:36:28 +08:00
seqlock: Improve seqlock performance on non-SMP platforms.
This commit implemented seqlock for non-SMP platforms, which achieves 1.62x performance improvement. Signed-off-by: ouyangxiangzhen <ouyangxiangzhen@xiaomi.com>
This commit is contained in:
committed by
Alan C. Assis
parent
a8724387e7
commit
d576363fc4
+33
-4
@@ -34,7 +34,11 @@
|
|||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
#define SEQLOCK_INITIALIZER { 1u, 1u }
|
#define SEQLOCK_INITIALIZER { 1u, 1u }
|
||||||
|
#else
|
||||||
|
#define SEQLOCK_INITIALIZER { 0u }
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Data Types
|
* Public Data Types
|
||||||
@@ -46,8 +50,12 @@
|
|||||||
|
|
||||||
typedef struct seqclock
|
typedef struct seqclock
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
atomic_t sequence;
|
atomic_t sequence;
|
||||||
uint32_t next_sequence;
|
uint32_t next_sequence;
|
||||||
|
#else
|
||||||
|
volatile uint32_t sequence;
|
||||||
|
#endif
|
||||||
} seqcount_t;
|
} seqcount_t;
|
||||||
|
|
||||||
#undef EXTERN
|
#undef EXTERN
|
||||||
@@ -79,8 +87,12 @@ 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
|
||||||
atomic_init(&s->sequence, 1u);
|
atomic_init(&s->sequence, 1u);
|
||||||
s->next_sequence = 1u;
|
s->next_sequence = 1u;
|
||||||
|
#else
|
||||||
|
s->sequence = 0u;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -103,6 +115,7 @@ uint32_t read_seqbegin(FAR const seqcount_t *s)
|
|||||||
{
|
{
|
||||||
uint32_t seq;
|
uint32_t seq;
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
/* Ensure no load operation is re-ordered before the acquire load. */
|
/* Ensure no load operation is re-ordered before the acquire load. */
|
||||||
@@ -110,7 +123,10 @@ uint32_t read_seqbegin(FAR const seqcount_t *s)
|
|||||||
seq = atomic_read_acquire(&s->sequence);
|
seq = atomic_read_acquire(&s->sequence);
|
||||||
}
|
}
|
||||||
while (seq == 0u);
|
while (seq == 0u);
|
||||||
|
#else
|
||||||
|
seq = s->sequence;
|
||||||
|
SMP_RMB();
|
||||||
|
#endif
|
||||||
return seq;
|
return seq;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,11 +149,19 @@ uint32_t read_seqbegin(FAR const seqcount_t *s)
|
|||||||
static inline_function
|
static inline_function
|
||||||
uint32_t read_seqretry(FAR const seqcount_t *s, uint32_t start)
|
uint32_t read_seqretry(FAR const seqcount_t *s, uint32_t start)
|
||||||
{
|
{
|
||||||
|
uint32_t seq;
|
||||||
|
|
||||||
/* Ensure all load operations before are completed. */
|
/* Ensure all load operations before are completed. */
|
||||||
|
|
||||||
SMP_RMB();
|
SMP_RMB();
|
||||||
|
|
||||||
return predict_false(atomic_read(&s->sequence) != start);
|
#ifdef CONFIG_SMP
|
||||||
|
seq = atomic_read(&s->sequence);
|
||||||
|
#else
|
||||||
|
seq = s->sequence;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return predict_false(seq != start);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -158,12 +182,12 @@ uint32_t read_seqretry(FAR const seqcount_t *s, uint32_t start)
|
|||||||
static inline_function
|
static inline_function
|
||||||
irqstate_t write_seqlock_irqsave(FAR seqcount_t *s)
|
irqstate_t write_seqlock_irqsave(FAR seqcount_t *s)
|
||||||
{
|
{
|
||||||
uint32_t sequence;
|
|
||||||
irqstate_t flags = up_irq_save();
|
irqstate_t flags = up_irq_save();
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
for (; ; )
|
for (; ; )
|
||||||
{
|
{
|
||||||
sequence = atomic_read(&s->sequence);
|
uint32_t sequence = atomic_read(&s->sequence);
|
||||||
|
|
||||||
if (predict_true(sequence != 0u))
|
if (predict_true(sequence != 0u))
|
||||||
{
|
{
|
||||||
@@ -177,6 +201,9 @@ irqstate_t write_seqlock_irqsave(FAR seqcount_t *s)
|
|||||||
|
|
||||||
/* CPU Relax and retry. */
|
/* CPU Relax and retry. */
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
s->sequence++;
|
||||||
|
#endif
|
||||||
|
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
@@ -200,9 +227,11 @@ irqstate_t write_seqlock_irqsave(FAR seqcount_t *s)
|
|||||||
static inline_function
|
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
|
||||||
uint32_t next = s->next_sequence + 2;
|
uint32_t next = s->next_sequence + 2;
|
||||||
s->next_sequence = next;
|
s->next_sequence = next;
|
||||||
atomic_set_release(&s->sequence, next);
|
atomic_set_release(&s->sequence, next);
|
||||||
|
#endif
|
||||||
up_irq_restore(flags);
|
up_irq_restore(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user