Add ACCESS_ONCE to _STORE_SHARED
[urcu.git] / test_urcu_timing.c
CommitLineData
20bf310a
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 * Distributed under GPLv2
9 */
10
11#include <stdio.h>
12#include <pthread.h>
13#include <stdlib.h>
14#include <string.h>
15#include <sys/types.h>
16#include <sys/wait.h>
17#include <unistd.h>
18#include <stdio.h>
19#include <assert.h>
20#include <sys/syscall.h>
21
22#if defined(_syscall0)
23_syscall0(pid_t, gettid)
24#elif defined(__NR_gettid)
25static inline pid_t gettid(void)
26{
27 return syscall(__NR_gettid);
28}
29#else
30#warning "use pid as tid"
31static inline pid_t gettid(void)
32{
33 return getpid();
34}
35#endif
36
20bf310a
MD
37#include "urcu.h"
38
c265818b
MD
39pthread_mutex_t rcu_copy_mutex = PTHREAD_MUTEX_INITIALIZER;
40
41void rcu_copy_mutex_lock(void)
42{
43 int ret;
44 ret = pthread_mutex_lock(&rcu_copy_mutex);
45 if (ret) {
46 perror("Error in pthread mutex lock");
47 exit(-1);
48 }
49}
50
51void rcu_copy_mutex_unlock(void)
52{
53 int ret;
54
55 ret = pthread_mutex_unlock(&rcu_copy_mutex);
56 if (ret) {
57 perror("Error in pthread mutex unlock");
58 exit(-1);
59 }
60}
61
20bf310a
MD
62struct test_array {
63 int a;
64};
65
66static struct test_array *test_rcu_pointer;
67
68#define OUTER_READ_LOOP 2000U
69#define INNER_READ_LOOP 100000U
70#define READ_LOOP ((unsigned long long)OUTER_READ_LOOP * INNER_READ_LOOP)
71
72#define WRITE_LOOP 2000U
73
74#define NR_READ 10
75#define NR_WRITE 9
76
77static cycles_t reader_time[NR_READ] __attribute__((aligned(128)));
78
79void *thr_reader(void *arg)
80{
1430ee0b 81 int i, j;
20bf310a
MD
82 struct test_array *local_ptr;
83 cycles_t time1, time2;
84
85 printf("thread_begin %s, thread id : %lx, tid %lu\n",
86 "reader", pthread_self(), (unsigned long)gettid());
87 sleep(2);
88
89 urcu_register_thread();
90
91 time1 = get_cycles();
92 for (i = 0; i < OUTER_READ_LOOP; i++) {
93 for (j = 0; j < INNER_READ_LOOP; j++) {
1430ee0b 94 rcu_read_lock();
20bf310a
MD
95 local_ptr = rcu_dereference(test_rcu_pointer);
96 if (local_ptr) {
97 assert(local_ptr->a == 8);
98 }
1430ee0b 99 rcu_read_unlock();
20bf310a
MD
100 }
101 }
102 time2 = get_cycles();
103
104 urcu_unregister_thread();
105
106 reader_time[(unsigned long)arg] = time2 - time1;
107
108 sleep(2);
109 printf("thread_end %s, thread id : %lx, tid %lu\n",
110 "reader", pthread_self(), (unsigned long)gettid());
111 return ((void*)1);
112
113}
114
115void *thr_writer(void *arg)
116{
117 int i;
118 struct test_array *new, *old;
119
120 printf("thread_begin %s, thread id : %lx, tid %lu\n",
121 "writer", pthread_self(), (unsigned long)gettid());
122 sleep(2);
123
124 for (i = 0; i < WRITE_LOOP; i++) {
125 new = malloc(sizeof(struct test_array));
c265818b 126 rcu_copy_mutex_lock();
20bf310a
MD
127 old = test_rcu_pointer;
128 if (old) {
129 assert(old->a == 8);
130 }
131 new->a = 8;
f4a486ac 132 old = urcu_publish_content(&test_rcu_pointer, new);
c265818b 133 rcu_copy_mutex_unlock();
20bf310a
MD
134 /* can be done after unlock */
135 if (old) {
136 old->a = 0;
137 }
138 free(old);
139 usleep(1);
140 }
141
142 printf("thread_end %s, thread id : %lx, tid %lu\n",
143 "writer", pthread_self(), (unsigned long)gettid());
144 return ((void*)2);
145}
146
147int main()
148{
149 int err;
150 pthread_t tid_reader[NR_READ], tid_writer[NR_WRITE];
151 void *tret;
152 int i;
153 cycles_t tot_time = 0;
154
155 printf("thread %-6s, thread id : %lx, tid %lu\n",
156 "main", pthread_self(), (unsigned long)gettid());
157
158 for (i = 0; i < NR_READ; i++) {
159 err = pthread_create(&tid_reader[i], NULL, thr_reader,
160 (void *)(long)i);
161 if (err != 0)
162 exit(1);
163 }
164 for (i = 0; i < NR_WRITE; i++) {
165 err = pthread_create(&tid_writer[i], NULL, thr_writer, NULL);
166 if (err != 0)
167 exit(1);
168 }
169
170 sleep(10);
171
172 for (i = 0; i < NR_READ; i++) {
173 err = pthread_join(tid_reader[i], &tret);
174 if (err != 0)
175 exit(1);
176 tot_time += reader_time[i];
177 }
178 for (i = 0; i < NR_WRITE; i++) {
179 err = pthread_join(tid_writer[i], &tret);
180 if (err != 0)
181 exit(1);
182 }
183 free(test_rcu_pointer);
184 printf("Time per read : %g cycles\n",
185 (double)tot_time / ((double)NR_READ * (double)READ_LOOP));
186
187 return 0;
188}
This page took 0.029551 seconds and 4 git commands to generate.