2 * Copyright (C) 2010 The Android Open Source Project
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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
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
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.
40 # define ERRNO_PTHREAD_EDEADLK EBUSY
42 # define ERRNO_PTHREAD_EDEADLK EDEADLK
45 static void __attribute__((noreturn))
46 panic(const char* func, const char* format, ...)
49 fprintf(stderr, "%s: ", func);
50 va_start(args, format);
51 vfprintf(stderr, format, args);
53 fprintf(stderr, "\n");
57 #define PANIC(...) panic(__FUNCTION__,__VA_ARGS__)
59 static void __attribute__((noreturn))
60 error(int errcode, const char* func, const char* format, ...)
63 fprintf(stderr, "%s: ", func);
64 va_start(args, format);
65 vfprintf(stderr, format, args);
67 fprintf(stderr, " error=%d: %s\n", errcode, strerror(errcode));
71 /* return current time in seconds as floating point value */
75 struct timespec ts[1];
77 clock_gettime(CLOCK_MONOTONIC, ts);
78 return (double)ts->tv_sec + ts->tv_nsec/1e9;
82 time_sleep(double delay)
87 ts.tv_sec = (time_t)delay;
88 ts.tv_nsec = (long)((delay - ts.tv_sec)*1e9);
91 ret = nanosleep(&ts, &ts);
92 } while (ret < 0 && errno == EINTR);
95 #define ERROR(errcode,...) error((errcode),__FUNCTION__,__VA_ARGS__)
98 { int _ret = (cond); if (_ret != 0) ERROR(_ret,"%d:%s", __LINE__, #cond); }
100 #define TTRUE(cond) \
101 { if (!(cond)) PANIC("%d:%s", __LINE__, #cond); }
103 #define TFALSE(cond) \
104 { if (!!(cond)) PANIC("%d:%s", __LINE__, #cond); }
106 #define TEXPECT_INT(cond,val) \
107 { int _ret = (cond); if (_ret != (val)) PANIC("%d:%s returned %d (%d expected)", __LINE__, #cond, _ret, (val)); }
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)
113 pthread_rwlock_t lock[1];
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));
121 static void do_test_rwlock_wr1(pthread_rwlockattr_t *attr)
124 pthread_rwlock_t lock[1];
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));
132 static void set_rwlockattr_shared(pthread_rwlockattr_t *attr, int shared)
135 TZERO(pthread_rwlockattr_setpshared(attr, shared));
137 TZERO(pthread_rwlockattr_getpshared(attr, &newshared));
138 TEXPECT_INT(newshared,shared);
141 /* simple init/lock/unlock/destroy on all rwlock types */
142 static void do_test_1(void)
145 pthread_rwlockattr_t attr[1];
147 do_test_rwlock_rd1(NULL);
148 do_test_rwlock_wr1(NULL);
150 /* non-shared version */
152 TZERO(pthread_rwlockattr_init(attr));
154 set_rwlockattr_shared(attr, PTHREAD_PROCESS_PRIVATE);
155 do_test_rwlock_rd1(attr);
156 do_test_rwlock_wr1(attr);
158 set_rwlockattr_shared(attr, PTHREAD_PROCESS_SHARED);
159 do_test_rwlock_rd1(attr);
160 do_test_rwlock_wr1(attr);
162 TZERO(pthread_rwlockattr_destroy(attr));
165 static void do_test_rwlock_rd2_rec(pthread_rwlockattr_t *attr)
167 pthread_rwlock_t lock[1];
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));
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));
182 static void do_test_rwlock_wr2_rec(pthread_rwlockattr_t *attr)
184 pthread_rwlock_t lock[1];
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));
191 TZERO(pthread_rwlock_init(lock, attr));
192 TZERO(pthread_rwlock_trywrlock(lock));
194 /* The host implementation (GLibc) does not support recursive
196 TEXPECT_INT(pthread_rwlock_trywrlock(lock),EBUSY);
198 /* Our implementation supports recursive write locks ! */
199 TZERO(pthread_rwlock_trywrlock(lock));
200 TZERO(pthread_rwlock_unlock(lock));
202 TZERO(pthread_rwlock_unlock(lock));
203 TZERO(pthread_rwlock_destroy(lock));
206 static void do_test_2(void)
208 pthread_rwlockattr_t attr[1];
210 do_test_rwlock_rd2_rec(NULL);
211 do_test_rwlock_wr2_rec(NULL);
213 /* non-shared version */
215 TZERO(pthread_rwlockattr_init(attr));
217 set_rwlockattr_shared(attr, PTHREAD_PROCESS_PRIVATE);
218 do_test_rwlock_rd2_rec(attr);
219 do_test_rwlock_wr2_rec(attr);
221 set_rwlockattr_shared(attr, PTHREAD_PROCESS_SHARED);
222 do_test_rwlock_rd2_rec(attr);
223 do_test_rwlock_wr2_rec(attr);
225 TZERO(pthread_rwlockattr_destroy(attr));
228 /* This is more complex example to test contention of rwlockes.
229 * Essentially, what happens is this:
231 * - main thread creates a rwlock and rdlocks it
232 * - it then creates thread 1 and thread 2
234 * - it then record the current time, sleep for a specific 'waitDelay'
235 * then unlock the rwlock.
237 * - thread 1 tryrdlocks() the rwlock. It shall acquire the lock
238 * immediately, then release it, then wrlock().
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.
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.
250 pthread_rwlock_t rwlock[1];
256 static void* do_rwlock_test_rd3_t1(void* arg)
261 /* try-acquire the lock, should succeed immediately */
262 TZERO(pthread_rwlock_tryrdlock(s->rwlock));
263 TZERO(pthread_rwlock_unlock(s->rwlock));
265 /* wrlock() the lock, now */
266 TZERO(pthread_rwlock_wrlock(s->rwlock));
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));
275 static void* do_rwlock_test_rd3_t2(void* arg)
281 int ret = pthread_rwlock_trywrlock(s->rwlock);
285 time_sleep(s->spinDelay);
290 TTRUE((t1-s->t0) >= s->waitDelay);
291 TZERO(pthread_rwlock_unlock(s->rwlock));
296 static void do_test_rwlock_rd3(pthread_rwlockattr_t *attr, double delay)
302 TZERO(pthread_rwlock_init(s->rwlock, attr));
303 s->waitDelay = delay;
304 s->spinDelay = delay/20.;
306 TZERO(pthread_rwlock_rdlock(s->rwlock));
308 pthread_create(&th1, NULL, do_rwlock_test_rd3_t1, s);
309 pthread_create(&th2, NULL, do_rwlock_test_rd3_t2, s);
314 TZERO(pthread_rwlock_unlock(s->rwlock));
316 TZERO(pthread_join(th1, &dummy));
317 TZERO(pthread_join(th2, &dummy));
320 static void do_test_3(double delay)
322 pthread_rwlockattr_t attr[1];
324 do_test_rwlock_rd3(NULL, delay);
326 /* non-shared version */
328 TZERO(pthread_rwlockattr_init(attr));
330 set_rwlockattr_shared(attr, PTHREAD_PROCESS_PRIVATE);
331 do_test_rwlock_rd3(attr, delay);
333 set_rwlockattr_shared(attr, PTHREAD_PROCESS_SHARED);
334 do_test_rwlock_rd3(attr, delay);
336 TZERO(pthread_rwlockattr_destroy(attr));