]> pd.if.org Git - nbds/blob - test/rcu_test.c
refactor header files
[nbds] / test / rcu_test.c
1 #include <stdio.h>
2 #include <errno.h>
3 #include <pthread.h>
4 #include "common.h"
5 #include "runtime.h"
6 #include "mem.h"
7
8 #define NUM_ITERATIONS 10000000
9
10 typedef struct node {
11     struct node *next;
12 } node_t;
13
14 typedef struct lifo {
15     node_t *head;
16 } lifo_t;
17
18 static volatile int wait_;
19 static lifo_t *stk_;
20
21 static lifo_t *lifo_alloc (void) {
22     lifo_t *stk = (lifo_t *)nbd_malloc(sizeof(lifo_t)); 
23     memset(stk, 0, sizeof(lifo_t));
24     return stk;
25 }
26
27 static void lifo_aba_push (lifo_t *stk, node_t *x) {
28     node_t *head;
29     do {
30         head = ((volatile lifo_t *)stk)->head;
31         ((volatile node_t *)x)->next = head;
32     } while (__sync_val_compare_and_swap(&stk->head, head, x) != head);
33 }
34
35 node_t *lifo_aba_pop (lifo_t *stk) {
36     node_t *head;
37     do {
38         head = ((volatile lifo_t *)stk)->head;
39         if (head == NULL)
40             return NULL;
41     } while (__sync_val_compare_and_swap(&stk->head, head, head->next) != head);
42     head->next = NULL;
43     return head;
44 }
45
46 node_t *node_alloc (void) {
47     node_t *node = (node_t *)nbd_malloc(sizeof(node_t));
48     memset(node, 0, sizeof(node_t));
49     return node;
50 }
51
52 void *worker (void *arg) {
53     int id = (int)(size_t)arg;
54     unsigned int rand_seed = (unsigned int)id + 1;
55
56     // Wait for all the worker threads to be ready.
57     __sync_fetch_and_add(&wait_, -1);
58     do {} while (wait_); 
59
60     int i;
61     for (i = 0; i < NUM_ITERATIONS; ++ i) {
62         int n = rand_r(&rand_seed);
63         if (n & 0x1) {
64             lifo_aba_push(stk_, node_alloc());
65         } else {
66             node_t *x = lifo_aba_pop(stk_);
67             if (x) {
68                 nbd_defer_free(x);
69             }
70         }
71         rcu_update();
72     }
73
74     return NULL;
75 }
76
77 int main (int argc, char **argv) {
78     nbd_init();
79     //lwt_set_trace_level("m0r0");
80
81     int num_threads = 2;
82     if (argc == 2)
83     {
84         errno = 0;
85         num_threads = strtol(argv[1], NULL, 10);
86         if (errno) {
87             fprintf(stderr, "%s: Invalid argument for number of threads\n", argv[0]);
88             return -1;
89         }
90         if (num_threads <= 0) {
91             fprintf(stderr, "%s: Number of threads must be at least 1\n", argv[0]);
92             return -1;
93         }
94     }
95
96     stk_ = lifo_alloc();
97     wait_ = num_threads;
98
99     pthread_t thread[num_threads];
100     for (int i = 0; i < num_threads; ++i) {
101         int rc = nbd_thread_create(thread + i, i, worker, (void *)(size_t)i);
102         if (rc != 0) { perror("pthread_create"); return rc; }
103     }
104     for (int i = 0; i < num_threads; ++i) {
105         pthread_join(thread[i], NULL);
106     }
107
108     return 0;
109 }