This source file includes following definitions.
- opal_fifo_head
- opal_fifo_tail
- opal_fifo_is_empty
- opal_fifo_push_atomic
- opal_fifo_pop_atomic
- opal_fifo_push_atomic
- opal_fifo_pop_atomic
- opal_fifo_push_st
- opal_fifo_pop_st
- opal_fifo_push
- opal_fifo_pop
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 #ifndef OPAL_FIFO_H_HAS_BEEN_INCLUDED
25 #define OPAL_FIFO_H_HAS_BEEN_INCLUDED
26
27 #include "opal_config.h"
28 #include "opal/class/opal_lifo.h"
29
30 #include "opal/sys/atomic.h"
31 #include "opal/threads/mutex.h"
32
33 BEGIN_C_DECLS
34
35
36
37
38
39
40
41
42
43
44 struct opal_fifo_t {
45 opal_object_t super;
46
47
48 volatile opal_counted_pointer_t opal_fifo_head;
49
50 volatile opal_counted_pointer_t opal_fifo_tail;
51
52
53 opal_list_item_t opal_fifo_ghost;
54 };
55
56 typedef struct opal_fifo_t opal_fifo_t;
57
58 OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_fifo_t);
59
60 static inline opal_list_item_t *opal_fifo_head (opal_fifo_t* fifo)
61 {
62 return (opal_list_item_t *) fifo->opal_fifo_head.data.item;
63 }
64
65 static inline opal_list_item_t *opal_fifo_tail (opal_fifo_t* fifo)
66 {
67 return (opal_list_item_t *) fifo->opal_fifo_tail.data.item;
68 }
69
70
71
72
73
74 static inline bool opal_fifo_is_empty( opal_fifo_t* fifo )
75 {
76 return opal_fifo_head (fifo) == &fifo->opal_fifo_ghost;
77 }
78
79 #if OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_128
80
81
82
83
84
85 static inline opal_list_item_t *opal_fifo_push_atomic (opal_fifo_t *fifo,
86 opal_list_item_t *item)
87 {
88 opal_counted_pointer_t tail = {.value = fifo->opal_fifo_tail.value};
89 const opal_list_item_t * const ghost = &fifo->opal_fifo_ghost;
90
91 item->opal_list_next = (opal_list_item_t *) ghost;
92
93 opal_atomic_wmb ();
94
95 do {
96 if (opal_update_counted_pointer (&fifo->opal_fifo_tail, &tail, item)) {
97 break;
98 }
99 } while (1);
100
101 opal_atomic_wmb ();
102
103 if ((intptr_t) ghost == tail.data.item) {
104
105 opal_counted_pointer_t head = {.value = fifo->opal_fifo_head.value};
106 opal_update_counted_pointer (&fifo->opal_fifo_head, &head, item);
107 } else {
108
109 ((opal_list_item_t *) tail.data.item)->opal_list_next = item;
110 }
111
112 return (opal_list_item_t *) tail.data.item;
113 }
114
115
116
117
118 static inline opal_list_item_t *opal_fifo_pop_atomic (opal_fifo_t *fifo)
119 {
120 opal_list_item_t *item, *next, *ghost = &fifo->opal_fifo_ghost;
121 opal_counted_pointer_t head, tail;
122
123 opal_read_counted_pointer (&fifo->opal_fifo_head, &head);
124
125 do {
126 tail.value = fifo->opal_fifo_tail.value;
127 opal_atomic_rmb ();
128
129 item = (opal_list_item_t *) head.data.item;
130 next = (opal_list_item_t *) item->opal_list_next;
131
132 if ((intptr_t) ghost == tail.data.item && ghost == item) {
133 return NULL;
134 }
135
136
137 if (tail.data.item != (intptr_t) item && (intptr_t) ghost != tail.data.item && ghost == next) {
138 opal_read_counted_pointer (&fifo->opal_fifo_head, &head);
139 continue;
140 }
141
142
143 if (opal_update_counted_pointer (&fifo->opal_fifo_head, &head, next)) {
144 break;
145 }
146 } while (1);
147
148 opal_atomic_wmb ();
149
150
151 if (ghost == next) {
152
153 if (!opal_update_counted_pointer (&fifo->opal_fifo_tail, &tail, ghost)) {
154
155
156
157
158 do {
159 opal_atomic_rmb ();
160 } while (ghost == item->opal_list_next);
161
162
163
164
165
166 fifo->opal_fifo_head.data.item = (intptr_t) item->opal_list_next;
167 opal_atomic_wmb ();
168 }
169 }
170
171 item->opal_list_next = NULL;
172
173 return item;
174 }
175
176 #else
177
178
179
180
181 static inline opal_list_item_t *opal_fifo_push_atomic (opal_fifo_t *fifo,
182 opal_list_item_t *item)
183 {
184 const opal_list_item_t * const ghost = &fifo->opal_fifo_ghost;
185 opal_list_item_t *tail_item;
186
187 item->opal_list_next = (opal_list_item_t *) ghost;
188
189 opal_atomic_wmb ();
190
191
192 tail_item = (opal_list_item_t *) opal_atomic_swap_ptr (&fifo->opal_fifo_tail.data.item, (intptr_t) item);
193
194 opal_atomic_wmb ();
195
196 if (ghost == tail_item) {
197
198 fifo->opal_fifo_head.data.item = (intptr_t) item;
199 } else {
200
201 tail_item->opal_list_next = item;
202 }
203
204 opal_atomic_wmb ();
205
206 return (opal_list_item_t *) tail_item;
207 }
208
209
210
211
212 static inline opal_list_item_t *opal_fifo_pop_atomic (opal_fifo_t *fifo)
213 {
214 const opal_list_item_t * const ghost = &fifo->opal_fifo_ghost;
215
216 #if OPAL_HAVE_ATOMIC_LLSC_PTR
217 register opal_list_item_t *item, *next;
218 int attempt = 0, ret = 0;
219
220
221 do {
222 if (++attempt == 5) {
223
224
225 _opal_lifo_release_cpu ();
226 attempt = 0;
227 }
228
229 opal_atomic_ll_ptr(&fifo->opal_fifo_head.data.item, item);
230 if (ghost == item) {
231 if ((intptr_t) ghost == fifo->opal_fifo_tail.data.item) {
232 return NULL;
233 }
234
235
236
237 continue;
238 }
239
240 next = (opal_list_item_t *) item->opal_list_next;
241 opal_atomic_sc_ptr(&fifo->opal_fifo_head.data.item, next, ret);
242 } while (!ret);
243
244 #else
245 opal_list_item_t *item, *next;
246
247
248 do {
249 if (!opal_atomic_swap_32 ((opal_atomic_int32_t *) &fifo->opal_fifo_head.data.counter, 1)) {
250 break;
251 }
252
253 opal_atomic_wmb ();
254 } while (1);
255
256 opal_atomic_wmb();
257
258 item = opal_fifo_head (fifo);
259 if (ghost == item) {
260 fifo->opal_fifo_head.data.counter = 0;
261 return NULL;
262 }
263
264 next = (opal_list_item_t *) item->opal_list_next;
265 fifo->opal_fifo_head.data.item = (uintptr_t) next;
266 #endif
267
268 if (ghost == next) {
269 void *tmp = item;
270
271 if (!opal_atomic_compare_exchange_strong_ptr (&fifo->opal_fifo_tail.data.item, (intptr_t *) &tmp, (intptr_t) ghost)) {
272 do {
273 opal_atomic_rmb ();
274 } while (ghost == item->opal_list_next);
275
276 fifo->opal_fifo_head.data.item = (intptr_t) item->opal_list_next;
277 }
278 }
279
280 opal_atomic_wmb ();
281
282
283 fifo->opal_fifo_head.data.counter = 0;
284
285 item->opal_list_next = NULL;
286
287 return item;
288 }
289
290 #endif
291
292
293 static inline opal_list_item_t *opal_fifo_push_st (opal_fifo_t *fifo,
294 opal_list_item_t *item)
295 {
296 opal_list_item_t *prev = opal_fifo_tail (fifo);
297
298 item->opal_list_next = &fifo->opal_fifo_ghost;
299
300 fifo->opal_fifo_tail.data.item = (intptr_t) item;
301 if (&fifo->opal_fifo_ghost == opal_fifo_head (fifo)) {
302 fifo->opal_fifo_head.data.item = (intptr_t) item;
303 } else {
304 prev->opal_list_next = item;
305 }
306
307 return (opal_list_item_t *) item->opal_list_next;
308 }
309
310 static inline opal_list_item_t *opal_fifo_pop_st (opal_fifo_t *fifo)
311 {
312 opal_list_item_t *item = opal_fifo_head (fifo);
313
314 if (item == &fifo->opal_fifo_ghost) {
315 return NULL;
316 }
317
318 fifo->opal_fifo_head.data.item = (intptr_t) item->opal_list_next;
319 if (&fifo->opal_fifo_ghost == opal_fifo_head (fifo)) {
320 fifo->opal_fifo_tail.data.item = (intptr_t) &fifo->opal_fifo_ghost;
321 }
322
323 item->opal_list_next = NULL;
324 return item;
325 }
326
327
328 static inline opal_list_item_t *opal_fifo_push (opal_fifo_t *fifo,
329 opal_list_item_t *item)
330 {
331 if (opal_using_threads ()) {
332 return opal_fifo_push_atomic (fifo, item);
333 }
334
335 return opal_fifo_push_st (fifo, item);
336 }
337
338 static inline opal_list_item_t *opal_fifo_pop (opal_fifo_t *fifo)
339 {
340 if (opal_using_threads ()) {
341 return opal_fifo_pop_atomic (fifo);
342 }
343
344 return opal_fifo_pop_st (fifo);
345 }
346
347 END_C_DECLS
348
349 #endif