14
14
#include <string.h>
15
15
#include <threads.h>
16
16
17
+ #ifdef ANALYSIS_OPS
18
+ /*
19
+ * rtry - the number of retries in the __list_find function.
20
+ * cons - the number of wait-free contains in the __list_find function that curr
21
+ * pointer pointed. trav - the number of list element traversal in the
22
+ * __list_find function. fail - the number of CAS() failures. del - the number
23
+ * of list_delete operation failed and restart again. ins - the number of
24
+ * list_insert operation failed and restart again.
25
+ */
26
+ static atomic_uint_fast64_t rtry = 0 , cons = 0 , trav = 0 , fail = 0 ;
27
+ static atomic_uint_fast64_t del = 0 , ins = 0 ;
28
+ static atomic_uint_fast64_t deletes = 0 , inserts = 0 ;
29
+
30
+ #define goto_try_again \
31
+ do { \
32
+ atomic_fetch_add(&rtry, 1); \
33
+ goto try_again; \
34
+ } while (0)
35
+ #define cons_inc \
36
+ do { \
37
+ atomic_fetch_add(&cons, 1); \
38
+ } while (0)
39
+ #define trav_inc \
40
+ do { \
41
+ atomic_fetch_add(&trav, 1); \
42
+ } while (0)
43
+ #define CAS (obj , expected , desired ) \
44
+ ({ \
45
+ atomic_fetch_add(&fail, 1); \
46
+ atomic_compare_exchange_strong(obj, expected, desired); \
47
+ })
48
+ #define del_inc \
49
+ do { \
50
+ atomic_fetch_add(&del, 1); \
51
+ } while (0)
52
+ #define ins_inc \
53
+ do { \
54
+ atomic_fetch_add(&ins, 1); \
55
+ } while (0)
56
+ #define deletes_inc \
57
+ do { \
58
+ atomic_fetch_add(&deletes, 1); \
59
+ } while (0)
60
+ #define inserts_inc \
61
+ do { \
62
+ atomic_fetch_add(&inserts, 1); \
63
+ } while (0)
64
+
65
+ void analysis_func (void )
66
+ {
67
+ printf ("%10s %10s %10s %10s %10s %10s %10s %10s\n" , "rtry" , "cons" , "trav" ,
68
+ "fail" , "del" , "ins" , "deletes" , "inserts" );
69
+ for (int i = 0 ; i < 87 ; i ++ )
70
+ printf ("-" );
71
+ printf ("\n%10ld %10ld %10ld %10ld %10ld %10ld %10ld %10ld\n" , rtry , cons ,
72
+ trav , fail , del , ins , deletes , inserts );
73
+ }
74
+
75
+ #else
76
+
77
+ #define goto_try_again \
78
+ do { \
79
+ goto try_again; \
80
+ } while (0)
81
+ #define cons_inc \
82
+ do { \
83
+ } while (0)
84
+ #define trav_inc \
85
+ do { \
86
+ } while (0)
87
+ #define CAS (obj , expected , desired ) \
88
+ ({ atomic_compare_exchange_strong(obj, expected, desired); })
89
+ #define del_inc \
90
+ do { \
91
+ } while (0)
92
+ #define ins_inc \
93
+ do { \
94
+ } while (0)
95
+ #define deletes_inc \
96
+ do { \
97
+ } while (0)
98
+ #define inserts_inc \
99
+ do { \
100
+ } while (0)
101
+
102
+ #endif
103
+
17
104
#define HP_MAX_THREADS 128
18
105
#define HP_MAX_HPS 5 /* This is named 'K' in the HP paper */
19
106
#define CLPAD (128 / sizeof(uintptr_t))
@@ -162,8 +249,6 @@ void list_hp_retire(list_hp_t *hp, uintptr_t ptr)
162
249
#define N_THREADS (128 / 2)
163
250
#define MAX_THREADS 128
164
251
165
- static atomic_uint_fast32_t deletes = 0 , inserts = 0 ;
166
-
167
252
enum { HP_NEXT = 0 , HP_CURR = 1 , HP_PREV };
168
253
169
254
#define is_marked (p ) (bool) ((uintptr_t)(p) &0x01)
@@ -195,7 +280,7 @@ list_node_t *list_node_new(list_key_t key)
195
280
list_node_t * node = aligned_alloc (128 , sizeof (* node ));
196
281
assert (node );
197
282
* node = (list_node_t ){.magic = LIST_MAGIC , .key = key };
198
- ( void ) atomic_fetch_add ( & inserts , 1 ) ;
283
+ inserts_inc ;
199
284
return node ;
200
285
}
201
286
@@ -205,7 +290,7 @@ void list_node_destroy(list_node_t *node)
205
290
return ;
206
291
assert (node -> magic == LIST_MAGIC );
207
292
free (node );
208
- ( void ) atomic_fetch_add ( & deletes , 1 ) ;
293
+ deletes_inc ;
209
294
}
210
295
211
296
static void __list_node_delete (void * arg )
@@ -228,18 +313,22 @@ static bool __list_find(list_t *list,
228
313
curr = (list_node_t * ) atomic_load (prev );
229
314
(void ) list_hp_protect_ptr (list -> hp , HP_CURR , (uintptr_t ) curr );
230
315
if (atomic_load (prev ) != get_unmarked (curr ))
231
- goto try_again ;
316
+ goto_try_again ;
232
317
while (true) {
318
+ #ifdef ANALYSIS_OPS
319
+ if (is_marked (curr ))
320
+ cons_inc ;
321
+ #endif
233
322
next = (list_node_t * ) atomic_load (& get_unmarked_node (curr )-> next );
234
323
(void ) list_hp_protect_ptr (list -> hp , HP_NEXT , get_unmarked (next ));
235
324
/* On a CAS failure, the search function, "__list_find," will simply
236
325
* have to go backwards in the list until an unmarked element is found
237
326
* from which the search in increasing key order can be started.
238
327
*/
239
328
if (atomic_load (& get_unmarked_node (curr )-> next ) != (uintptr_t ) next )
240
- goto try_again ;
329
+ goto_try_again ;
241
330
if (atomic_load (prev ) != get_unmarked (curr ))
242
- goto try_again ;
331
+ goto_try_again ;
243
332
if (get_unmarked_node (next ) == next ) {
244
333
if (!(get_unmarked_node (curr )-> key < * key )) {
245
334
* par_curr = curr ;
@@ -252,12 +341,13 @@ static bool __list_find(list_t *list,
252
341
get_unmarked (curr ));
253
342
} else {
254
343
uintptr_t tmp = get_unmarked (curr );
255
- if (!atomic_compare_exchange_strong (prev , & tmp , get_unmarked (next )))
256
- goto try_again ;
344
+ if (!CAS (prev , & tmp , get_unmarked (next )))
345
+ goto_try_again ;
257
346
list_hp_retire (list -> hp , get_unmarked (curr ));
258
347
}
259
348
curr = next ;
260
349
(void ) list_hp_protect_release (list -> hp , HP_CURR , get_unmarked (next ));
350
+ trav_inc ;
261
351
}
262
352
}
263
353
@@ -277,10 +367,11 @@ bool list_insert(list_t *list, list_key_t key)
277
367
atomic_store_explicit (& node -> next , (uintptr_t ) curr ,
278
368
memory_order_relaxed );
279
369
uintptr_t tmp = get_unmarked (curr );
280
- if (atomic_compare_exchange_strong (prev , & tmp , (uintptr_t ) node )) {
370
+ if (CAS (prev , & tmp , (uintptr_t ) node )) {
281
371
list_hp_clear (list -> hp );
282
372
return true;
283
373
}
374
+ ins_inc ;
284
375
}
285
376
}
286
377
@@ -296,12 +387,13 @@ bool list_delete(list_t *list, list_key_t key)
296
387
297
388
uintptr_t tmp = get_unmarked (next );
298
389
299
- if (!atomic_compare_exchange_strong (& curr -> next , & tmp ,
300
- get_marked ( next )))
390
+ if (!CAS (& curr -> next , & tmp , get_marked ( next ))) {
391
+ del_inc ;
301
392
continue ;
393
+ }
302
394
303
395
tmp = get_unmarked (curr );
304
- if (atomic_compare_exchange_strong (prev , & tmp , get_unmarked (next ))) {
396
+ if (CAS (prev , & tmp , get_unmarked (next ))) {
305
397
list_hp_clear (list -> hp );
306
398
list_hp_retire (list -> hp , get_unmarked (curr ));
307
399
} else {
@@ -382,8 +474,8 @@ int main(void)
382
474
383
475
list_destroy (list );
384
476
385
- fprintf ( stderr , "inserts = %zu, deletes = %zu\n" , atomic_load ( & inserts ),
386
- atomic_load ( & deletes ) );
387
-
477
+ #ifdef ANALYSIS_OPS
478
+ analysis_func ( );
479
+ #endif
388
480
return 0 ;
389
481
}
0 commit comments