Test RCU read-side validity
[libside.git] / tests / regression / side-rcu-test.c
CommitLineData
a536d5a4
MD
1// SPDX-License-Identifier: MIT
2/*
3 * Copyright 2022 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 */
5
6#include <pthread.h>
7#include <stdint.h>
8#include <inttypes.h>
9
748f8271
MD
10static int nr_reader_threads = 2;
11static int nr_writer_threads = 2;
a536d5a4
MD
12static int duration_s = 10;
13
14static volatile int start_test, stop_test;
15
16struct thread_ctx {
17 pthread_t thread_id;
18 uint64_t count;
19};
20
80a8b8dd
MD
21#include "../../src/rcu.h"
22
a536d5a4
MD
23static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
24
25static struct side_rcu_gp_state test_rcu_gp;
26
8b17fb21 27#define POISON_VALUE 55
a536d5a4
MD
28
29struct test_data {
30 int v;
31};
32
8b17fb21 33static struct test_data *rcu_p;
a536d5a4
MD
34
35static
36void *test_reader_thread(void *arg)
37{
38 struct thread_ctx *thread_ctx = (struct thread_ctx *) arg;
39 uint64_t count = 0;
40
41 while (!start_test) { }
42
43 while (!stop_test) {
8b17fb21
MD
44 struct test_data *p;
45 int v, period;
a536d5a4
MD
46
47 period = side_rcu_read_begin(&test_rcu_gp);
8b17fb21
MD
48 p = side_rcu_dereference(rcu_p);
49 if (p) {
50 v = p->v;
51 if (v != 0 && v != 1) {
52 fprintf(stderr, "Unexpected value: %d\n", v);
53 abort();
54 }
55 }
a536d5a4
MD
56 side_rcu_read_end(&test_rcu_gp, period);
57 count++;
58 }
59 thread_ctx->count = count;
60 return NULL;
61}
62
63static
64void *test_writer_thread(void *arg)
65{
66 struct thread_ctx *thread_ctx = (struct thread_ctx *) arg;
67 uint64_t count = 0;
68
69 while (!start_test) { }
70
71 while (!stop_test) {
72 struct test_data *new_data, *old_data;
73
74 new_data = calloc(1, sizeof(struct test_data));
75 if (!new_data)
76 abort();
77
78 pthread_mutex_lock(&lock);
8b17fb21 79 old_data = rcu_p;
a536d5a4
MD
80 if (old_data)
81 new_data->v = old_data->v ^ 1; /* 0 or 1 */
8b17fb21 82 side_rcu_assign_pointer(rcu_p, new_data);
a536d5a4
MD
83 pthread_mutex_unlock(&lock);
84
85 side_rcu_wait_grace_period(&test_rcu_gp);
86
87 if (old_data) {
88 old_data->v = POISON_VALUE;
89 free(old_data);
90 }
91 count++;
92 }
93 thread_ctx->count = count;
94 return NULL;
95}
96
80a8b8dd
MD
97int main(int argc, char **argv)
98{
a536d5a4
MD
99 struct thread_ctx *reader_ctx;
100 struct thread_ctx *writer_ctx;
101 int i, ret;
102 int sleep_s = duration_s;
103 uint64_t read_tot = 0, write_tot = 0;
104
105 side_rcu_gp_init(&test_rcu_gp);
106 //TODO: parse command line args.
107
108 reader_ctx = calloc(nr_reader_threads, sizeof(struct thread_ctx));
109 if (!reader_ctx)
110 abort();
111 writer_ctx = calloc(nr_writer_threads, sizeof(struct thread_ctx));
112 if (!writer_ctx)
113 abort();
114
115
116 for (i = 0; i < nr_reader_threads; i++) {
117 ret = pthread_create(&reader_ctx[i].thread_id, NULL, test_reader_thread, &reader_ctx[i]);
118 if (ret) {
119 errno = ret;
120 perror("pthread_create");
121 abort();
122 }
123 }
124 for (i = 0; i < nr_writer_threads; i++) {
125 ret = pthread_create(&writer_ctx[i].thread_id, NULL, test_writer_thread, &writer_ctx[i]);
126 if (ret) {
127 errno = ret;
128 perror("pthread_create");
129 abort();
130 }
131 }
132
133 start_test = 1;
134
135 while (sleep_s > 0) {
136 sleep_s = sleep(sleep_s);
137 }
138
139 stop_test = 1;
140
141 for (i = 0; i < nr_reader_threads; i++) {
142 void *res;
143
144 ret = pthread_join(reader_ctx[i].thread_id, &res);
145 if (ret) {
146 errno = ret;
147 perror("pthread_join");
148 abort();
149 }
150 read_tot += reader_ctx[i].count;
151 }
152 for (i = 0; i < nr_writer_threads; i++) {
153 void *res;
154
155 ret = pthread_join(writer_ctx[i].thread_id, &res);
156 if (ret) {
157 errno = ret;
158 perror("pthread_join");
159 abort();
160 }
161 write_tot += writer_ctx[i].count;
162 }
163 printf("Summary: duration: %d, nr_reader_threads: %d, nr_writer_threads: %d, reads: %" PRIu64 ", writes: %" PRIu64 "\n",
164 duration_s, nr_reader_threads, nr_writer_threads, read_tot, write_tot);
165 free(reader_ctx);
166 free(writer_ctx);
167 side_rcu_gp_exit(&test_rcu_gp);
80a8b8dd
MD
168 return 0;
169}
This page took 0.029118 seconds and 4 git commands to generate.