Skip to content

Commit 63f489f

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 63f489f

File tree

2 files changed

+130
-16
lines changed

2 files changed

+130
-16
lines changed

hp_list/Makefile

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

4+
# The RUNTIME_STAT allow to show the runtime operation state,
5+
# such as "rtry" is the number of retries in the __list_find function.
6+
analysis:
7+
$(CC) -Wall -D RUNTIME_STAT -o list main.c -lpthread -g -fsanitize=thread
8+
49
indent:
510
clang-format -i *.[ch]
611

hp_list/main.c

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

17+
#ifdef RUNTIME_STAT
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.
22+
* "trav" the number of list element traversal in the __list_find function.
23+
* "fail" the number of CAS() failures.
24+
* "del" the number of list_delete operation failed and restart again.
25+
* "ins" the number of list_insert operation failed and restart again.
26+
*/
27+
static atomic_uint_fast64_t rtry = 0, cons = 0, trav = 0, fail = 0;
28+
static atomic_uint_fast64_t del = 0, ins = 0;
29+
static atomic_uint_fast64_t deletes = 0, inserts = 0;
30+
31+
#define TRACE_GOTO_TRY_AGAIN \
32+
do { \
33+
atomic_fetch_add(&rtry, 1); \
34+
goto try_again; \
35+
} while (0)
36+
#define TRACE_WAIT_FREE_CONS \
37+
do { \
38+
atomic_fetch_add(&cons, 1); \
39+
} while (0)
40+
#define TRACE_TRAVERSAL \
41+
do { \
42+
atomic_fetch_add(&trav, 1); \
43+
} while (0)
44+
#define CAS(obj, expected, desired) \
45+
({ \
46+
atomic_fetch_add(&fail, 1); \
47+
atomic_compare_exchange_strong(obj, expected, desired); \
48+
})
49+
#define TRACE_DEL \
50+
do { \
51+
atomic_fetch_add(&del, 1); \
52+
} while (0)
53+
#define TRACE_INS \
54+
do { \
55+
atomic_fetch_add(&ins, 1); \
56+
} while (0)
57+
#define TRACE_DELETES \
58+
do { \
59+
atomic_fetch_add(&deletes, 1); \
60+
} while (0)
61+
#define TRACE_INSERTS \
62+
do { \
63+
atomic_fetch_add(&inserts, 1); \
64+
} while (0)
65+
66+
void analysis_func(void)
67+
{
68+
printf("\"rtry\" is the number of retries in the __list_find function.\n");
69+
printf(
70+
"\"cons\" is the number of wait-free contains in the __list_find "
71+
"function that curr pointer pointed.\n");
72+
printf(
73+
"\"trav\" is the number of list element traversal in the __list_find "
74+
"function.\n");
75+
printf("\"fail\" is the number of CAS() failures.\n");
76+
printf(
77+
"\"del\" is the number of list_delete operation failed and restart "
78+
"again.\n");
79+
printf(
80+
"\"ins\" is the number of list_insert operation failed and restart "
81+
"again.\n");
82+
printf("\"deletes\" is the number of linked list elements deleted.\n");
83+
printf("\"inserts\" is the number of linked list elements created.\n");
84+
printf("\n%10s %10s %10s %10s %10s %10s %10s %10s\n", "rtry", "cons",
85+
"trav", "fail", "del", "ins", "deletes", "inserts");
86+
for (int i = 0; i < 87; i++)
87+
printf("-");
88+
printf("\n%10ld %10ld %10ld %10ld %10ld %10ld %10ld %10ld\n", rtry, cons,
89+
trav, fail, del, ins, deletes, inserts);
90+
}
91+
92+
#else
93+
94+
#define TRACE_GOTO_TRY_AGAIN \
95+
do { \
96+
goto try_again; \
97+
} while (0)
98+
#define TRACE_WAIT_FREE_CONS \
99+
do { \
100+
} while (0)
101+
#define TRACE_TRAVERSAL \
102+
do { \
103+
} while (0)
104+
#define CAS(obj, expected, desired) \
105+
({ atomic_compare_exchange_strong(obj, expected, desired); })
106+
#define TRACE_DEL \
107+
do { \
108+
} while (0)
109+
#define TRACE_INS \
110+
do { \
111+
} while (0)
112+
#define TRACE_DELETES \
113+
do { \
114+
} while (0)
115+
#define TRACE_INSERTS \
116+
do { \
117+
} while (0)
118+
119+
#endif
120+
17121
#define HP_MAX_THREADS 128
18122
#define HP_MAX_HPS 5 /* This is named 'K' in the HP paper */
19123
#define CLPAD (128 / sizeof(uintptr_t))
@@ -162,8 +266,6 @@ void list_hp_retire(list_hp_t *hp, uintptr_t ptr)
162266
#define N_THREADS (128 / 2)
163267
#define MAX_THREADS 128
164268

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

169271
#define is_marked(p) (bool) ((uintptr_t)(p) &0x01)
@@ -195,7 +297,7 @@ list_node_t *list_node_new(list_key_t key)
195297
list_node_t *node = aligned_alloc(128, sizeof(*node));
196298
assert(node);
197299
*node = (list_node_t){.magic = LIST_MAGIC, .key = key};
198-
(void) atomic_fetch_add(&inserts, 1);
300+
TRACE_INSERTS;
199301
return node;
200302
}
201303

@@ -205,7 +307,7 @@ void list_node_destroy(list_node_t *node)
205307
return;
206308
assert(node->magic == LIST_MAGIC);
207309
free(node);
208-
(void) atomic_fetch_add(&deletes, 1);
310+
TRACE_DELETES;
209311
}
210312

211313
static void __list_node_delete(void *arg)
@@ -228,18 +330,22 @@ static bool __list_find(list_t *list,
228330
curr = (list_node_t *) atomic_load(prev);
229331
(void) list_hp_protect_ptr(list->hp, HP_CURR, (uintptr_t) curr);
230332
if (atomic_load(prev) != get_unmarked(curr))
231-
goto try_again;
333+
TRACE_GOTO_TRY_AGAIN;
232334
while (true) {
335+
#ifdef RUNTIME_STAT
336+
if (is_marked(curr))
337+
TRACE_WAIT_FREE_CONS;
338+
#endif
233339
next = (list_node_t *) atomic_load(&get_unmarked_node(curr)->next);
234340
(void) list_hp_protect_ptr(list->hp, HP_NEXT, get_unmarked(next));
235341
/* On a CAS failure, the search function, "__list_find," will simply
236342
* have to go backwards in the list until an unmarked element is found
237343
* from which the search in increasing key order can be started.
238344
*/
239345
if (atomic_load(&get_unmarked_node(curr)->next) != (uintptr_t) next)
240-
goto try_again;
346+
TRACE_GOTO_TRY_AGAIN;
241347
if (atomic_load(prev) != get_unmarked(curr))
242-
goto try_again;
348+
TRACE_GOTO_TRY_AGAIN;
243349
if (get_unmarked_node(next) == next) {
244350
if (!(get_unmarked_node(curr)->key < *key)) {
245351
*par_curr = curr;
@@ -252,12 +358,13 @@ static bool __list_find(list_t *list,
252358
get_unmarked(curr));
253359
} else {
254360
uintptr_t tmp = get_unmarked(curr);
255-
if (!atomic_compare_exchange_strong(prev, &tmp, get_unmarked(next)))
256-
goto try_again;
361+
if (!CAS(prev, &tmp, get_unmarked(next)))
362+
TRACE_GOTO_TRY_AGAIN;
257363
list_hp_retire(list->hp, get_unmarked(curr));
258364
}
259365
curr = next;
260366
(void) list_hp_protect_release(list->hp, HP_CURR, get_unmarked(next));
367+
TRACE_TRAVERSAL;
261368
}
262369
}
263370

@@ -277,10 +384,11 @@ bool list_insert(list_t *list, list_key_t key)
277384
atomic_store_explicit(&node->next, (uintptr_t) curr,
278385
memory_order_relaxed);
279386
uintptr_t tmp = get_unmarked(curr);
280-
if (atomic_compare_exchange_strong(prev, &tmp, (uintptr_t) node)) {
387+
if (CAS(prev, &tmp, (uintptr_t) node)) {
281388
list_hp_clear(list->hp);
282389
return true;
283390
}
391+
TRACE_INS;
284392
}
285393
}
286394

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

297405
uintptr_t tmp = get_unmarked(next);
298406

299-
if (!atomic_compare_exchange_strong(&curr->next, &tmp,
300-
get_marked(next)))
407+
if (!CAS(&curr->next, &tmp, get_marked(next))) {
408+
TRACE_DEL;
301409
continue;
410+
}
302411

303412
tmp = get_unmarked(curr);
304-
if (atomic_compare_exchange_strong(prev, &tmp, get_unmarked(next))) {
413+
if (CAS(prev, &tmp, get_unmarked(next))) {
305414
list_hp_clear(list->hp);
306415
list_hp_retire(list->hp, get_unmarked(curr));
307416
} else {
@@ -382,8 +491,8 @@ int main(void)
382491

383492
list_destroy(list);
384493

385-
fprintf(stderr, "inserts = %zu, deletes = %zu\n", atomic_load(&inserts),
386-
atomic_load(&deletes));
387-
494+
#ifdef RUNTIME_STAT
495+
analysis_func();
496+
#endif
388497
return 0;
389498
}

0 commit comments

Comments
 (0)