Skip to content

Commit f70d624

Browse files
committed
opal/class: use new compare-and-swap functions
Signed-off-by: Nathan Hjelm <[email protected]>
1 parent f00b07a commit f70d624

File tree

2 files changed

+50
-44
lines changed

2 files changed

+50
-44
lines changed

opal/class/opal_fifo.h

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
* All rights reserved.
1313
* Copyright (c) 2007 Voltaire All rights reserved.
1414
* Copyright (c) 2010 IBM Corporation. All rights reserved.
15-
* Copyright (c) 2014-2016 Los Alamos National Security, LLC. All rights
15+
* Copyright (c) 2014-2017 Los Alamos National Security, LLC. All rights
1616
* reseved.
1717
* $COPYRIGHT$
1818
*
@@ -85,14 +85,12 @@ static inline bool opal_fifo_is_empty( opal_fifo_t* fifo )
8585
static inline opal_list_item_t *opal_fifo_push_atomic (opal_fifo_t *fifo,
8686
opal_list_item_t *item)
8787
{
88-
opal_counted_pointer_t tail;
88+
opal_counted_pointer_t tail = {.value = fifo->opal_fifo_tail.value};
8989

9090
item->opal_list_next = &fifo->opal_fifo_ghost;
9191

9292
do {
93-
tail.value = fifo->opal_fifo_tail.value;
94-
95-
if (opal_update_counted_pointer (&fifo->opal_fifo_tail, tail, item)) {
93+
if (opal_update_counted_pointer (&fifo->opal_fifo_tail, &tail, item)) {
9694
break;
9795
}
9896
} while (1);
@@ -102,7 +100,7 @@ static inline opal_list_item_t *opal_fifo_push_atomic (opal_fifo_t *fifo,
102100
if (&fifo->opal_fifo_ghost == tail.data.item) {
103101
/* update the head */
104102
opal_counted_pointer_t head = {.value = fifo->opal_fifo_head.value};
105-
opal_update_counted_pointer (&fifo->opal_fifo_head, head, item);
103+
opal_update_counted_pointer (&fifo->opal_fifo_head, &head, item);
106104
} else {
107105
/* update previous item */
108106
tail.data.item->opal_list_next = item;
@@ -116,44 +114,43 @@ static inline opal_list_item_t *opal_fifo_push_atomic (opal_fifo_t *fifo,
116114
*/
117115
static inline opal_list_item_t *opal_fifo_pop_atomic (opal_fifo_t *fifo)
118116
{
119-
opal_list_item_t *item, *next;
120-
opal_counted_pointer_t head, tail;
117+
opal_list_item_t *item, *next, *ghost = &fifo->opal_fifo_ghost;
118+
opal_counted_pointer_t head = {.value = fifo->opal_fifo_head.value}, tail;
121119

122120
do {
123-
head.value = fifo->opal_fifo_head.value;
124121
tail.value = fifo->opal_fifo_tail.value;
125122
opal_atomic_rmb ();
126123

127124
item = (opal_list_item_t *) head.data.item;
128125
next = (opal_list_item_t *) item->opal_list_next;
129126

130-
if (&fifo->opal_fifo_ghost == tail.data.item && &fifo->opal_fifo_ghost == item) {
127+
if (ghost == tail.data.item && ghost == item) {
131128
return NULL;
132129
}
133130

134131
/* the head or next pointer are in an inconsistent state. keep looping. */
135-
if (tail.data.item != item && &fifo->opal_fifo_ghost != tail.data.item &&
136-
&fifo->opal_fifo_ghost == next) {
132+
if (tail.data.item != item && ghost != tail.data.item && ghost == next) {
133+
head.value = fifo->opal_fifo_head.value;
137134
continue;
138135
}
139136

140137
/* try popping the head */
141-
if (opal_update_counted_pointer (&fifo->opal_fifo_head, head, next)) {
138+
if (opal_update_counted_pointer (&fifo->opal_fifo_head, &head, next)) {
142139
break;
143140
}
144141
} while (1);
145142

146143
opal_atomic_wmb ();
147144

148145
/* check for tail and head consistency */
149-
if (&fifo->opal_fifo_ghost == next) {
146+
if (ghost == next) {
150147
/* the head was just set to &fifo->opal_fifo_ghost. try to update the tail as well */
151-
if (!opal_update_counted_pointer (&fifo->opal_fifo_tail, tail, &fifo->opal_fifo_ghost)) {
148+
if (!opal_update_counted_pointer (&fifo->opal_fifo_tail, &tail, ghost)) {
152149
/* tail was changed by a push operation. wait for the item's next pointer to be se then
153150
* update the head */
154151

155152
/* wait for next pointer to be updated by push */
156-
while (&fifo->opal_fifo_ghost == item->opal_list_next) {
153+
while (ghost == item->opal_list_next) {
157154
opal_atomic_rmb ();
158155
}
159156

@@ -166,7 +163,7 @@ static inline opal_list_item_t *opal_fifo_pop_atomic (opal_fifo_t *fifo)
166163
head.value = fifo->opal_fifo_head.value;
167164
next = (opal_list_item_t *) item->opal_list_next;
168165

169-
assert (&fifo->opal_fifo_ghost == head.data.item);
166+
assert (ghost == head.data.item);
170167

171168
fifo->opal_fifo_head.data.item = next;
172169
opal_atomic_wmb ();
@@ -215,14 +212,14 @@ static inline opal_list_item_t *opal_fifo_push_atomic (opal_fifo_t *fifo,
215212
*/
216213
static inline opal_list_item_t *opal_fifo_pop_atomic (opal_fifo_t *fifo)
217214
{
218-
opal_list_item_t *item, *next;
215+
opal_list_item_t *item, *next, *ghost = &fifo->opal_fifo_ghost;
219216

220217
#if OPAL_HAVE_ATOMIC_LLSC_PTR
221218
/* use load-linked store-conditional to avoid ABA issues */
222219
do {
223220
item = opal_atomic_ll_ptr (&fifo->opal_fifo_head.data.item);
224-
if (&fifo->opal_fifo_ghost == item) {
225-
if (&fifo->opal_fifo_ghost == fifo->opal_fifo_tail.data.item) {
221+
if (ghost == item) {
222+
if (ghost == fifo->opal_fifo_tail.data.item) {
226223
return NULL;
227224
}
228225

@@ -239,7 +236,7 @@ static inline opal_list_item_t *opal_fifo_pop_atomic (opal_fifo_t *fifo)
239236
#else
240237
/* protect against ABA issues by "locking" the head */
241238
do {
242-
if (opal_atomic_bool_cmpset_32 ((int32_t *) &fifo->opal_fifo_head.data.counter, 0, 1)) {
239+
if (!opal_atomic_swap_32 ((volatile int32_t *) &fifo->opal_fifo_head.data.counter, 1)) {
243240
break;
244241
}
245242

@@ -249,7 +246,7 @@ static inline opal_list_item_t *opal_fifo_pop_atomic (opal_fifo_t *fifo)
249246
opal_atomic_wmb();
250247

251248
item = opal_fifo_head (fifo);
252-
if (&fifo->opal_fifo_ghost == item) {
249+
if (ghost == item) {
253250
fifo->opal_fifo_head.data.counter = 0;
254251
return NULL;
255252
}
@@ -258,9 +255,11 @@ static inline opal_list_item_t *opal_fifo_pop_atomic (opal_fifo_t *fifo)
258255
fifo->opal_fifo_head.data.item = next;
259256
#endif
260257

261-
if (&fifo->opal_fifo_ghost == next) {
262-
if (!opal_atomic_bool_cmpset_ptr (&fifo->opal_fifo_tail.data.item, item, &fifo->opal_fifo_ghost)) {
263-
while (&fifo->opal_fifo_ghost == item->opal_list_next) {
258+
if (ghost == next) {
259+
void *tmp = item;
260+
261+
if (!opal_atomic_compare_exchange_strong_ptr (&fifo->opal_fifo_tail.data.item, &tmp, ghost)) {
262+
while (ghost == item->opal_list_next) {
264263
opal_atomic_rmb ();
265264
}
266265

opal/class/opal_lifo.h

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
* All rights reserved.
1313
* Copyright (c) 2007 Voltaire All rights reserved.
1414
* Copyright (c) 2010 IBM Corporation. All rights reserved.
15-
* Copyright (c) 2014-2015 Los Alamos National Security, LLC. All rights
15+
* Copyright (c) 2014-2017 Los Alamos National Security, LLC. All rights
1616
* reseved.
1717
* Copyright (c) 2016 Research Organization for Information Science
1818
* and Technology (RIST). All rights reserved.
@@ -65,13 +65,13 @@ typedef union opal_counted_pointer_t opal_counted_pointer_t;
6565
* to allow the upper level to detect if this element is the first one in the
6666
* list (if the list was empty before this operation).
6767
*/
68-
static inline bool opal_update_counted_pointer (volatile opal_counted_pointer_t *addr, opal_counted_pointer_t old,
68+
static inline bool opal_update_counted_pointer (volatile opal_counted_pointer_t *addr, opal_counted_pointer_t *old,
6969
opal_list_item_t *item)
7070
{
7171
opal_counted_pointer_t new_p;
7272
new_p.data.item = item;
73-
new_p.data.counter = old.data.counter + 1;
74-
return opal_atomic_bool_cmpset_128 (&addr->value, old.value, new_p.value);
73+
new_p.data.counter = old->data.counter + 1;
74+
return opal_atomic_compare_exchange_strong_128 (&addr->value, &old->value, new_p.value);
7575
}
7676

7777
#endif
@@ -119,14 +119,14 @@ static inline bool opal_lifo_is_empty( opal_lifo_t* lifo )
119119
static inline opal_list_item_t *opal_lifo_push_atomic (opal_lifo_t *lifo,
120120
opal_list_item_t *item)
121121
{
122-
do {
123-
opal_list_item_t *next = (opal_list_item_t *) lifo->opal_lifo_head.data.item;
122+
opal_list_item_t *next = (opal_list_item_t *) lifo->opal_lifo_head.data.item;
124123

124+
do {
125125
item->opal_list_next = next;
126126
opal_atomic_wmb ();
127127

128128
/* to protect against ABA issues it is sufficient to only update the counter in pop */
129-
if (opal_atomic_bool_cmpset_ptr (&lifo->opal_lifo_head.data.item, next, item)) {
129+
if (opal_atomic_compare_exchange_strong_ptr (&lifo->opal_lifo_head.data.item, &next, item)) {
130130
return next;
131131
}
132132
/* DO some kind of pause to release the bus */
@@ -141,17 +141,17 @@ static inline opal_list_item_t *opal_lifo_pop_atomic (opal_lifo_t* lifo)
141141
opal_counted_pointer_t old_head;
142142
opal_list_item_t *item;
143143

144-
do {
145-
146-
old_head.data.counter = lifo->opal_lifo_head.data.counter;
147-
opal_atomic_rmb ();
148-
old_head.data.item = item = (opal_list_item_t*)lifo->opal_lifo_head.data.item;
144+
old_head.data.counter = lifo->opal_lifo_head.data.counter;
145+
opal_atomic_rmb ();
146+
old_head.data.item = (opal_list_item_t *) lifo->opal_lifo_head.data.item;
149147

148+
do {
149+
item = old_head.data.item;
150150
if (item == &lifo->opal_lifo_ghost) {
151151
return NULL;
152152
}
153153

154-
if (opal_update_counted_pointer (&lifo->opal_lifo_head, old_head,
154+
if (opal_update_counted_pointer (&lifo->opal_lifo_head, &old_head,
155155
(opal_list_item_t *) item->opal_list_next)) {
156156
opal_atomic_wmb ();
157157
item->opal_list_next = NULL;
@@ -169,13 +169,15 @@ static inline opal_list_item_t *opal_lifo_pop_atomic (opal_lifo_t* lifo)
169169
static inline opal_list_item_t *opal_lifo_push_atomic (opal_lifo_t *lifo,
170170
opal_list_item_t *item)
171171
{
172+
opal_list_item_t *next = (opal_list_item_t *) lifo->opal_lifo_head.data.item;
173+
172174
/* item free acts as a mini lock to avoid ABA problems */
173175
item->item_free = 1;
176+
174177
do {
175-
opal_list_item_t *next = (opal_list_item_t *) lifo->opal_lifo_head.data.item;
176178
item->opal_list_next = next;
177179
opal_atomic_wmb();
178-
if (opal_atomic_bool_cmpset_ptr (&lifo->opal_lifo_head.data.item, next, item)) {
180+
if (opal_atomic_compare_exchange_strong_ptr (&lifo->opal_lifo_head.data.item, &next, item)) {
179181
opal_atomic_wmb ();
180182
/* now safe to pop this item */
181183
item->item_free = 0;
@@ -236,23 +238,28 @@ static inline opal_list_item_t *opal_lifo_pop_atomic (opal_lifo_t* lifo)
236238
*/
237239
static inline opal_list_item_t *opal_lifo_pop_atomic (opal_lifo_t* lifo)
238240
{
239-
opal_list_item_t *item;
240-
while ((item = (opal_list_item_t *) lifo->opal_lifo_head.data.item) != &lifo->opal_lifo_ghost) {
241+
opal_list_item_t *item, *head, *ghost = &lifo->opal_lifo_ghost;
242+
243+
item = (opal_list_item_t *) lifo->opal_lifo_head.data.item;
244+
245+
while (item != ghost) {
241246
/* ensure it is safe to pop the head */
242247
if (opal_atomic_swap_32((volatile int32_t *) &item->item_free, 1)) {
243248
continue;
244249
}
245250

246251
opal_atomic_wmb ();
247252

253+
head = item;
248254
/* try to swap out the head pointer */
249-
if (opal_atomic_bool_cmpset_ptr (&lifo->opal_lifo_head.data.item, item,
250-
(void *) item->opal_list_next)) {
255+
if (opal_atomic_compare_exchange_strong_ptr (&lifo->opal_lifo_head.data.item, &head,
256+
(void *) item->opal_list_next)) {
251257
break;
252258
}
253259

254260
/* NTH: don't need another atomic here */
255261
item->item_free = 0;
262+
item = head;
256263

257264
/* Do some kind of pause to release the bus */
258265
}

0 commit comments

Comments
 (0)