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