OSDN Git Service

ANRdaemon: move trace result from /sdcard to /data
[android-x86/system-extras.git] / tests / bionic / libc / common / test_pthread_rwlock.c
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *  * Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *  * Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in
12  *    the documentation and/or other materials provided with the
13  *    distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 #include <pthread.h>
29 #include <errno.h>
30 #include <string.h>
31 #include <stdarg.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34
35 /* Posix states that EDEADLK should be returned in case a deadlock condition
36  * is detected with a PTHREAD_MUTEX_ERRORCHECK lock() or trylock(), but
37  * GLibc returns EBUSY instead.
38  */
39 #ifdef HOST
40 #  define ERRNO_PTHREAD_EDEADLK   EBUSY
41 #else
42 #  define ERRNO_PTHREAD_EDEADLK   EDEADLK
43 #endif
44
45 static void __attribute__((noreturn))
46 panic(const char* func, const char* format, ...)
47 {
48     va_list  args;
49     fprintf(stderr, "%s: ", func);
50     va_start(args, format);
51     vfprintf(stderr, format, args);
52     va_end(args);
53     fprintf(stderr, "\n");
54     exit(1);
55 }
56
57 #define  PANIC(...)   panic(__FUNCTION__,__VA_ARGS__)
58
59 static void __attribute__((noreturn))
60 error(int  errcode, const char* func, const char* format, ...)
61 {
62     va_list  args;
63     fprintf(stderr, "%s: ", func);
64     va_start(args, format);
65     vfprintf(stderr, format, args);
66     va_end(args);
67     fprintf(stderr, " error=%d: %s\n", errcode, strerror(errcode));
68     exit(1);
69 }
70
71 /* return current time in seconds as floating point value */
72 static double
73 time_now(void)
74 {
75     struct timespec ts[1];
76
77     clock_gettime(CLOCK_MONOTONIC, ts);
78     return (double)ts->tv_sec + ts->tv_nsec/1e9;
79 }
80
81 static void
82 time_sleep(double  delay)
83 {
84     struct timespec ts;
85     int             ret;
86
87     ts.tv_sec  = (time_t)delay;
88     ts.tv_nsec = (long)((delay - ts.tv_sec)*1e9);
89
90     do {
91         ret = nanosleep(&ts, &ts);
92     } while (ret < 0 && errno == EINTR);
93 }
94
95 #define  ERROR(errcode,...)   error((errcode),__FUNCTION__,__VA_ARGS__)
96
97 #define  TZERO(cond)   \
98     { int _ret = (cond); if (_ret != 0) ERROR(_ret,"%d:%s", __LINE__, #cond); }
99
100 #define  TTRUE(cond)   \
101     { if (!(cond)) PANIC("%d:%s", __LINE__, #cond); }
102
103 #define  TFALSE(cond)   \
104     { if (!!(cond)) PANIC("%d:%s", __LINE__, #cond); }
105
106 #define  TEXPECT_INT(cond,val) \
107     { int _ret = (cond); if (_ret != (val)) PANIC("%d:%s returned %d (%d expected)", __LINE__, #cond, _ret, (val)); }
108
109 /* perform a simple init/lock/unlock/destroy test on a rwlock of given attributes */
110 static void do_test_rwlock_rd1(pthread_rwlockattr_t *attr)
111 {
112     int               ret;
113     pthread_rwlock_t  lock[1];
114
115     TZERO(pthread_rwlock_init(lock, attr));
116     TZERO(pthread_rwlock_rdlock(lock));
117     TZERO(pthread_rwlock_unlock(lock));
118     TZERO(pthread_rwlock_destroy(lock));
119 }
120
121 static void do_test_rwlock_wr1(pthread_rwlockattr_t *attr)
122 {
123     int               ret;
124     pthread_rwlock_t  lock[1];
125
126     TZERO(pthread_rwlock_init(lock, attr));
127     TZERO(pthread_rwlock_wrlock(lock));
128     TZERO(pthread_rwlock_unlock(lock));
129     TZERO(pthread_rwlock_destroy(lock));
130 }
131
132 static void set_rwlockattr_shared(pthread_rwlockattr_t *attr, int shared)
133 {
134     int  newshared;
135     TZERO(pthread_rwlockattr_setpshared(attr, shared));
136     newshared = ~shared;
137     TZERO(pthread_rwlockattr_getpshared(attr, &newshared));
138     TEXPECT_INT(newshared,shared);
139 }
140
141 /* simple init/lock/unlock/destroy on all rwlock types */
142 static void do_test_1(void)
143 {
144     int                  ret, type;
145     pthread_rwlockattr_t  attr[1];
146
147     do_test_rwlock_rd1(NULL);
148     do_test_rwlock_wr1(NULL);
149
150     /* non-shared version */
151
152     TZERO(pthread_rwlockattr_init(attr));
153
154     set_rwlockattr_shared(attr, PTHREAD_PROCESS_PRIVATE);
155     do_test_rwlock_rd1(attr);
156     do_test_rwlock_wr1(attr);
157
158     set_rwlockattr_shared(attr, PTHREAD_PROCESS_SHARED);
159     do_test_rwlock_rd1(attr);
160     do_test_rwlock_wr1(attr);
161
162     TZERO(pthread_rwlockattr_destroy(attr));
163 }
164
165 static void do_test_rwlock_rd2_rec(pthread_rwlockattr_t *attr)
166 {
167     pthread_rwlock_t  lock[1];
168
169     TZERO(pthread_rwlock_init(lock, attr));
170     TZERO(pthread_rwlock_tryrdlock(lock));
171     TZERO(pthread_rwlock_unlock(lock));
172     TZERO(pthread_rwlock_destroy(lock));
173
174     TZERO(pthread_rwlock_init(lock, attr));
175     TZERO(pthread_rwlock_tryrdlock(lock));
176     TZERO(pthread_rwlock_tryrdlock(lock));
177     TZERO(pthread_rwlock_unlock(lock));
178     TZERO(pthread_rwlock_unlock(lock));
179     TZERO(pthread_rwlock_destroy(lock));
180 }
181
182 static void do_test_rwlock_wr2_rec(pthread_rwlockattr_t *attr)
183 {
184     pthread_rwlock_t  lock[1];
185
186     TZERO(pthread_rwlock_init(lock, attr));
187     TZERO(pthread_rwlock_trywrlock(lock));
188     TZERO(pthread_rwlock_unlock(lock));
189     TZERO(pthread_rwlock_destroy(lock));
190
191     TZERO(pthread_rwlock_init(lock, attr));
192     TZERO(pthread_rwlock_trywrlock(lock));
193 #ifdef HOST
194     /* The host implementation (GLibc) does not support recursive
195      * write locks */
196     TEXPECT_INT(pthread_rwlock_trywrlock(lock),EBUSY);
197 #else
198     /* Our implementation supports recursive write locks ! */
199     TZERO(pthread_rwlock_trywrlock(lock));
200     TZERO(pthread_rwlock_unlock(lock));
201 #endif
202     TZERO(pthread_rwlock_unlock(lock));
203     TZERO(pthread_rwlock_destroy(lock));
204 }
205
206 static void do_test_2(void)
207 {
208     pthread_rwlockattr_t  attr[1];
209
210     do_test_rwlock_rd2_rec(NULL);
211     do_test_rwlock_wr2_rec(NULL);
212
213     /* non-shared version */
214
215     TZERO(pthread_rwlockattr_init(attr));
216
217     set_rwlockattr_shared(attr, PTHREAD_PROCESS_PRIVATE);
218     do_test_rwlock_rd2_rec(attr);
219     do_test_rwlock_wr2_rec(attr);
220
221     set_rwlockattr_shared(attr, PTHREAD_PROCESS_SHARED);
222     do_test_rwlock_rd2_rec(attr);
223     do_test_rwlock_wr2_rec(attr);
224
225     TZERO(pthread_rwlockattr_destroy(attr));
226 }
227
228 /* This is more complex example to test contention of rwlockes.
229  * Essentially, what happens is this:
230  *
231  * - main thread creates a rwlock and rdlocks it
232  * - it then creates thread 1 and thread 2
233  *
234  * - it then record the current time, sleep for a specific 'waitDelay'
235  *   then unlock the rwlock.
236  *
237  * - thread 1 tryrdlocks() the rwlock. It shall acquire the lock
238  *   immediately, then release it, then wrlock().
239  *
240  * - thread 2 trywrlocks() the rwlock. In case of failure (EBUSY), it waits
241  *   for a small amount of time (see 'spinDelay') and tries again, until
242  *   it succeeds. It then unlocks the rwlock.
243  *
244  * The goal of this test is to verify that thread 1 has been stopped
245  * for a sufficiently long time (in the wrlock), and that thread 2 has
246  * been spinning for the same minimum period. There is no guarantee as
247  * to which thread is going to acquire the rwlock first.
248  */
249 typedef struct {
250     pthread_rwlock_t  rwlock[1];
251     double            t0;
252     double            waitDelay;
253     double            spinDelay;
254 } Test3State;
255
256 static void* do_rwlock_test_rd3_t1(void* arg)
257 {
258     Test3State *s = arg;
259     double      t1;
260
261     /* try-acquire the lock, should succeed immediately */
262     TZERO(pthread_rwlock_tryrdlock(s->rwlock));
263     TZERO(pthread_rwlock_unlock(s->rwlock));
264
265     /* wrlock() the lock, now */
266     TZERO(pthread_rwlock_wrlock(s->rwlock));
267
268     t1 = time_now();
269     //DEBUG ONLY: printf("t1-s->t0=%g waitDelay=%g\n", t1-s->t0, s->waitDelay);
270     TTRUE((t1-s->t0) >= s->waitDelay); 
271     TZERO(pthread_rwlock_unlock(s->rwlock));
272     return NULL;
273 }
274
275 static void* do_rwlock_test_rd3_t2(void* arg)
276 {
277     Test3State *s = arg;
278     double      t1;
279
280     for (;;) {
281         int ret = pthread_rwlock_trywrlock(s->rwlock);
282         if (ret == 0)
283             break;
284         if (ret == EBUSY) {
285             time_sleep(s->spinDelay);
286             continue;
287         }
288     }
289     t1 = time_now();
290     TTRUE((t1-s->t0) >= s->waitDelay);
291     TZERO(pthread_rwlock_unlock(s->rwlock));
292     return NULL;
293 }
294
295
296 static void do_test_rwlock_rd3(pthread_rwlockattr_t *attr, double delay)
297 {
298     Test3State  s[1];
299     pthread_t   th1, th2;
300     void*       dummy;
301
302     TZERO(pthread_rwlock_init(s->rwlock, attr));
303     s->waitDelay = delay;
304     s->spinDelay = delay/20.;
305
306     TZERO(pthread_rwlock_rdlock(s->rwlock));
307
308     pthread_create(&th1, NULL, do_rwlock_test_rd3_t1, s);
309     pthread_create(&th2, NULL, do_rwlock_test_rd3_t2, s);
310
311     s->t0 = time_now();
312     time_sleep(delay);
313
314     TZERO(pthread_rwlock_unlock(s->rwlock));
315
316     TZERO(pthread_join(th1, &dummy));
317     TZERO(pthread_join(th2, &dummy));
318 }
319
320 static void do_test_3(double  delay)
321 {
322     pthread_rwlockattr_t  attr[1];
323
324     do_test_rwlock_rd3(NULL, delay);
325
326     /* non-shared version */
327
328     TZERO(pthread_rwlockattr_init(attr));
329
330     set_rwlockattr_shared(attr, PTHREAD_PROCESS_PRIVATE);
331     do_test_rwlock_rd3(attr, delay);
332
333     set_rwlockattr_shared(attr, PTHREAD_PROCESS_SHARED);
334     do_test_rwlock_rd3(attr, delay);
335
336     TZERO(pthread_rwlockattr_destroy(attr));
337 }
338
339
340 int main(void)
341 {
342     do_test_1();
343     do_test_2();
344     do_test_3(0.1);
345     return 0;
346 }