Skip to content

Commit 538923c

Browse files
committed
Add more operation analysis, combine with deletes and inserts variables.
And Using the preprocessor to decide the analysis being set or not. The following are the new varialbes to record the opreations: rtry is the number of retries in the __list_find function. cons is the number of wait-free contains in the __list_find function that curr pointer pointed. trav is the number of list element traversal in the __list_find function. fail is the number of CAS() failures. del is the number of list_delete operation failed and restart again. ins is the number of list_insert operation failed and restart again.
1 parent 9fa5bf8 commit 538923c

File tree

2 files changed

+113
-16
lines changed

2 files changed

+113
-16
lines changed

hp_list/Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1+
CFLAG=-D ANALYSIS_OPS
2+
13
all:
24
$(CC) -Wall -o list main.c -lpthread -g -fsanitize=thread
35

6+
analysis:
7+
$(CC) -Wall $(CFLAG) -o list main.c -lpthread -g -fsanitize=thread
8+
49
indent:
510
clang-format -i *.[ch]
611

hp_list/main.c

Lines changed: 108 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,93 @@
1414
#include <string.h>
1515
#include <threads.h>
1616

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+
17104
#define HP_MAX_THREADS 128
18105
#define HP_MAX_HPS 5 /* This is named 'K' in the HP paper */
19106
#define CLPAD (128 / sizeof(uintptr_t))
@@ -162,8 +249,6 @@ void list_hp_retire(list_hp_t *hp, uintptr_t ptr)
162249
#define N_THREADS (128 / 2)
163250
#define MAX_THREADS 128
164251

165-
static atomic_uint_fast32_t deletes = 0, inserts = 0;
166-
167252
enum { HP_NEXT = 0, HP_CURR = 1, HP_PREV };
168253

169254
#define is_marked(p) (bool) ((uintptr_t)(p) &0x01)
@@ -195,7 +280,7 @@ list_node_t *list_node_new(list_key_t key)
195280
list_node_t *node = aligned_alloc(128, sizeof(*node));
196281
assert(node);
197282
*node = (list_node_t){.magic = LIST_MAGIC, .key = key};
198-
(void) atomic_fetch_add(&inserts, 1);
283+
inserts_inc;
199284
return node;
200285
}
201286

@@ -205,7 +290,7 @@ void list_node_destroy(list_node_t *node)
205290
return;
206291
assert(node->magic == LIST_MAGIC);
207292
free(node);
208-
(void) atomic_fetch_add(&deletes, 1);
293+
deletes_inc;
209294
}
210295

211296
static void __list_node_delete(void *arg)
@@ -228,18 +313,22 @@ static bool __list_find(list_t *list,
228313
curr = (list_node_t *) atomic_load(prev);
229314
(void) list_hp_protect_ptr(list->hp, HP_CURR, (uintptr_t) curr);
230315
if (atomic_load(prev) != get_unmarked(curr))
231-
goto try_again;
316+
goto_try_again;
232317
while (true) {
318+
#ifdef ANALYSIS_OPS
319+
if (is_marked(curr))
320+
cons_inc;
321+
#endif
233322
next = (list_node_t *) atomic_load(&get_unmarked_node(curr)->next);
234323
(void) list_hp_protect_ptr(list->hp, HP_NEXT, get_unmarked(next));
235324
/* On a CAS failure, the search function, "__list_find," will simply
236325
* have to go backwards in the list until an unmarked element is found
237326
* from which the search in increasing key order can be started.
238327
*/
239328
if (atomic_load(&get_unmarked_node(curr)->next) != (uintptr_t) next)
240-
goto try_again;
329+
goto_try_again;
241330
if (atomic_load(prev) != get_unmarked(curr))
242-
goto try_again;
331+
goto_try_again;
243332
if (get_unmarked_node(next) == next) {
244333
if (!(get_unmarked_node(curr)->key < *key)) {
245334
*par_curr = curr;
@@ -252,12 +341,13 @@ static bool __list_find(list_t *list,
252341
get_unmarked(curr));
253342
} else {
254343
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;
257346
list_hp_retire(list->hp, get_unmarked(curr));
258347
}
259348
curr = next;
260349
(void) list_hp_protect_release(list->hp, HP_CURR, get_unmarked(next));
350+
trav_inc;
261351
}
262352
}
263353

@@ -277,10 +367,11 @@ bool list_insert(list_t *list, list_key_t key)
277367
atomic_store_explicit(&node->next, (uintptr_t) curr,
278368
memory_order_relaxed);
279369
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)) {
281371
list_hp_clear(list->hp);
282372
return true;
283373
}
374+
ins_inc;
284375
}
285376
}
286377

@@ -296,12 +387,13 @@ bool list_delete(list_t *list, list_key_t key)
296387

297388
uintptr_t tmp = get_unmarked(next);
298389

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;
301392
continue;
393+
}
302394

303395
tmp = get_unmarked(curr);
304-
if (atomic_compare_exchange_strong(prev, &tmp, get_unmarked(next))) {
396+
if (CAS(prev, &tmp, get_unmarked(next))) {
305397
list_hp_clear(list->hp);
306398
list_hp_retire(list->hp, get_unmarked(curr));
307399
} else {
@@ -382,8 +474,8 @@ int main(void)
382474

383475
list_destroy(list);
384476

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
388480
return 0;
389481
}

0 commit comments

Comments
 (0)