Add ACCESS_ONCE to _STORE_SHARED
[urcu.git] / test_urcu_timing.c
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)
25 static inline pid_t gettid(void)
26 {
27 return syscall(__NR_gettid);
28 }
29 #else
30 #warning "use pid as tid"
31 static inline pid_t gettid(void)
32 {
33 return getpid();
34 }
35 #endif
36
37 #include "urcu.h"
38
39 pthread_mutex_t rcu_copy_mutex = PTHREAD_MUTEX_INITIALIZER;
40
41 void 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
51 void 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
62 struct test_array {
63 int a;
64 };
65
66 static 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
77 static cycles_t reader_time[NR_READ] __attribute__((aligned(128)));
78
79 void *thr_reader(void *arg)
80 {
81 int i, j;
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++) {
94 rcu_read_lock();
95 local_ptr = rcu_dereference(test_rcu_pointer);
96 if (local_ptr) {
97 assert(local_ptr->a == 8);
98 }
99 rcu_read_unlock();
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
115 void *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));
126 rcu_copy_mutex_lock();
127 old = test_rcu_pointer;
128 if (old) {
129 assert(old->a == 8);
130 }
131 new->a = 8;
132 old = urcu_publish_content(&test_rcu_pointer, new);
133 rcu_copy_mutex_unlock();
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
147 int 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.045011 seconds and 5 git commands to generate.