Fix deadlock in qsbr code
[urcu.git] / test_rwlock.c
CommitLineData
10c48e14
MD
1/*
2 * test_urcu.c
3 *
4 * Userspace RCU library - test program
5 *
6 * Copyright February 2009 - Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23#include <stdio.h>
24#include <pthread.h>
25#include <stdlib.h>
26#include <string.h>
27#include <sys/types.h>
28#include <sys/wait.h>
29#include <unistd.h>
30#include <stdio.h>
31#include <assert.h>
32#include <sys/syscall.h>
33
7685d963
MD
34#include "arch.h"
35
10c48e14
MD
36#if defined(_syscall0)
37_syscall0(pid_t, gettid)
38#elif defined(__NR_gettid)
39static inline pid_t gettid(void)
40{
41 return syscall(__NR_gettid);
42}
43#else
44#warning "use pid as tid"
45static inline pid_t gettid(void)
46{
47 return getpid();
48}
49#endif
50
51#ifndef DYNAMIC_LINK_TEST
52#define _LGPL_SOURCE
53#else
54#define debug_yield_read()
55#endif
56#include "urcu.h"
57
58struct test_array {
59 int a;
60};
61
62pthread_rwlock_t lock = PTHREAD_RWLOCK_INITIALIZER;
63
78efb485 64static volatile int test_go, test_stop;
10c48e14
MD
65
66static int wdelay;
67
68static struct test_array test_array = { 8 };
69
70static unsigned long duration;
10c48e14
MD
71
72/*
73 * returns 0 if test should end.
74 */
75static int test_duration_write(void)
76{
78efb485 77 return !test_stop;
10c48e14
MD
78}
79
80static int test_duration_read(void)
81{
78efb485 82 return !test_stop;
10c48e14
MD
83}
84
85static unsigned long long __thread nr_writes;
86static unsigned long long __thread nr_reads;
87
88static unsigned int nr_readers;
89static unsigned int nr_writers;
90
91pthread_mutex_t rcu_copy_mutex = PTHREAD_MUTEX_INITIALIZER;
92
93void rcu_copy_mutex_lock(void)
94{
95 int ret;
96 ret = pthread_mutex_lock(&rcu_copy_mutex);
97 if (ret) {
98 perror("Error in pthread mutex lock");
99 exit(-1);
100 }
101}
102
103void rcu_copy_mutex_unlock(void)
104{
105 int ret;
106
107 ret = pthread_mutex_unlock(&rcu_copy_mutex);
108 if (ret) {
109 perror("Error in pthread mutex unlock");
110 exit(-1);
111 }
112}
113
114void *thr_reader(void *_count)
115{
116 unsigned long long *count = _count;
117
118 printf("thread_begin %s, thread id : %lx, tid %lu\n",
119 "reader", pthread_self(), (unsigned long)gettid());
120
121 while (!test_go)
122 {
123 }
124
125 for (;;) {
126 pthread_rwlock_rdlock(&lock);
127 assert(test_array.a == 8);
128 pthread_rwlock_unlock(&lock);
129 nr_reads++;
130 if (!test_duration_read())
131 break;
132 }
133
134 *count = nr_reads;
135 printf("thread_end %s, thread id : %lx, tid %lu\n",
136 "reader", pthread_self(), (unsigned long)gettid());
137 return ((void*)1);
138
139}
140
141void *thr_writer(void *_count)
142{
143 unsigned long long *count = _count;
144
145 printf("thread_begin %s, thread id : %lx, tid %lu\n",
146 "writer", pthread_self(), (unsigned long)gettid());
147
148 while (!test_go)
149 {
150 }
7685d963 151 smp_mb();
10c48e14
MD
152
153 for (;;) {
154 pthread_rwlock_wrlock(&lock);
155 test_array.a = 8;
156 pthread_rwlock_unlock(&lock);
157 nr_writes++;
158 if (!test_duration_write())
159 break;
160 if (wdelay)
161 usleep(wdelay);
162 }
163
164 printf("thread_end %s, thread id : %lx, tid %lu\n",
165 "writer", pthread_self(), (unsigned long)gettid());
166 *count = nr_writes;
167 return ((void*)2);
168}
169
170void show_usage(int argc, char **argv)
171{
172 printf("Usage : %s nr_readers nr_writers duration (s)", argv[0]);
173#ifdef DEBUG_YIELD
174 printf(" [-r] [-w] (yield reader and/or writer)");
175#endif
7685d963 176 printf(" [-d delay] (writer period (us))");
10c48e14
MD
177 printf("\n");
178}
179
180int main(int argc, char **argv)
181{
182 int err;
183 pthread_t *tid_reader, *tid_writer;
184 void *tret;
185 unsigned long long *count_reader, *count_writer;
186 unsigned long long tot_reads = 0, tot_writes = 0;
187 int i;
188
189 if (argc < 4) {
190 show_usage(argc, argv);
191 return -1;
192 }
7685d963 193 smp_mb();
10c48e14
MD
194
195 err = sscanf(argv[1], "%u", &nr_readers);
196 if (err != 1) {
197 show_usage(argc, argv);
198 return -1;
199 }
200
201 err = sscanf(argv[2], "%u", &nr_writers);
202 if (err != 1) {
203 show_usage(argc, argv);
204 return -1;
205 }
206
207 err = sscanf(argv[3], "%lu", &duration);
208 if (err != 1) {
209 show_usage(argc, argv);
210 return -1;
211 }
212
213 for (i = 4; i < argc; i++) {
214 if (argv[i][0] != '-')
215 continue;
216 switch (argv[i][1]) {
217#ifdef DEBUG_YIELD
218 case 'r':
219 yield_active |= YIELD_READ;
220 break;
221 case 'w':
222 yield_active |= YIELD_WRITE;
223 break;
224#endif
225 case 'd':
226 if (argc < i + 2) {
227 show_usage(argc, argv);
228 return -1;
229 }
230 wdelay = atoi(argv[++i]);
231 break;
232 }
233 }
234
235 printf("running test for %lu seconds, %u readers, %u writers.\n",
236 duration, nr_readers, nr_writers);
237 printf("Writer delay : %u us.\n", wdelay);
10c48e14
MD
238 printf("thread %-6s, thread id : %lx, tid %lu\n",
239 "main", pthread_self(), (unsigned long)gettid());
240
241 tid_reader = malloc(sizeof(*tid_reader) * nr_readers);
242 tid_writer = malloc(sizeof(*tid_writer) * nr_writers);
243 count_reader = malloc(sizeof(*count_reader) * nr_readers);
244 count_writer = malloc(sizeof(*count_writer) * nr_writers);
245
246 for (i = 0; i < nr_readers; i++) {
247 err = pthread_create(&tid_reader[i], NULL, thr_reader,
248 &count_reader[i]);
249 if (err != 0)
250 exit(1);
251 }
252 for (i = 0; i < nr_writers; i++) {
253 err = pthread_create(&tid_writer[i], NULL, thr_writer,
254 &count_writer[i]);
255 if (err != 0)
256 exit(1);
257 }
258
7685d963 259 smp_mb();
10c48e14 260
78efb485
MD
261 test_go = 1;
262
263 sleep(duration);
264
265 test_stop = 1;
266
10c48e14
MD
267 for (i = 0; i < nr_readers; i++) {
268 err = pthread_join(tid_reader[i], &tret);
269 if (err != 0)
270 exit(1);
271 tot_reads += count_reader[i];
272 }
273 for (i = 0; i < nr_writers; i++) {
274 err = pthread_join(tid_writer[i], &tret);
275 if (err != 0)
276 exit(1);
277 tot_writes += count_writer[i];
278 }
279
280 printf("total number of reads : %llu, writes %llu\n", tot_reads,
281 tot_writes);
282 free(tid_reader);
283 free(tid_writer);
284 free(count_reader);
285 free(count_writer);
286 return 0;
287}
This page took 0.047968 seconds and 4 git commands to generate.