Skip to content
This repository was archived by the owner on Jan 15, 2021. It is now read-only.

Commit 7750b9b

Browse files
committed
Fix a corner case in the atomic queue
Add a new atomic op to protect the atomic dequeue operation
1 parent e84648f commit 7750b9b

File tree

1 file changed

+30
-23
lines changed

1 file changed

+30
-23
lines changed

source/atomic-queue.c

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,23 @@
2020
#include <stddef.h>
2121
#include "cmsis.h"
2222

23+
int atomic_cas_deref_uint32( uint32_t * volatile *ptr, uint32_t ** currentValue, uint32_t expectedValue, uint32_t *newValue, uintptr_t offset) {
24+
uint32_t *current;
25+
current = (uint32_t *)__LDREXW((volatile uint32_t *)ptr);
26+
if (currentValue != NULL) {
27+
*currentValue = current;
28+
}
29+
if (current == NULL) {
30+
return -1;
31+
} else if ( *(uint32_t *)((uintptr_t)current + offset) != expectedValue) {
32+
return 1;
33+
} else if(!__STREXW((uint32_t)newValue, (volatile uint32_t *)ptr)) {
34+
return 0;
35+
} else {
36+
return -1;
37+
}
38+
}
39+
2340
void lfq_push_tail(struct lockfree_queue * q, struct lockfree_queue_element * e)
2441
{
2542
CORE_UTIL_ASSERT_MSG(q != NULL, "null queue used");
@@ -31,43 +48,33 @@ void lfq_push_tail(struct lockfree_queue * q, struct lockfree_queue_element * e)
3148
} while (!__sync_bool_compare_and_swap(&q->tail, e->next, e));
3249
}
3350

34-
volatile int trip = 0;
35-
36-
int tripped() {
37-
return trip;
38-
}
39-
4051
struct lockfree_queue_element * lfq_pop_head(struct lockfree_queue * q)
4152
{
42-
struct lockfree_queue_element * rx;
4353
CORE_UTIL_ASSERT_MSG(q != NULL, "null queue used");
4454
if (q == NULL) {
4555
return NULL;
4656
}
47-
while (1) {
57+
struct lockfree_queue_element * current;
58+
int fail = 1;
59+
while (fail) {
4860
// Set the element reference pointer to the tail pointer
4961
struct lockfree_queue_element * volatile * px = &q->tail;
5062
if (*px == NULL) {
5163
return NULL;
5264
}
53-
while (1) {
54-
rx = *px;
55-
if (rx == NULL) {
56-
break;
57-
}
58-
if (rx->next == NULL) {
59-
break;
65+
fail = 1;
66+
while (fail > 0) {
67+
fail = atomic_cas_deref_uint32((uint32_t * volatile *)px,
68+
(uint32_t **)&current,
69+
(uint32_t) NULL,
70+
NULL,
71+
offsetof(struct lockfree_queue_element, next));
72+
if (fail == 1) {
73+
px = &current->next;
6074
}
61-
px = &rx->next;
62-
}
63-
if (rx == NULL) {
64-
continue;
65-
}
66-
if(__sync_bool_compare_and_swap(px, rx, NULL)){
67-
break;
6875
}
6976
}
70-
return rx;
77+
return current;
7178
}
7279

7380

0 commit comments

Comments
 (0)