test_pthread_rwlock.c revision 545e6ca13f744650e4a62630f1b901c0840dcd43
1545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner/*
2545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * Copyright (C) 2010 The Android Open Source Project
3545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * All rights reserved.
4545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner *
5545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * Redistribution and use in source and binary forms, with or without
6545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * modification, are permitted provided that the following conditions
7545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * are met:
8545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner *  * Redistributions of source code must retain the above copyright
9545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner *    notice, this list of conditions and the following disclaimer.
10545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner *  * Redistributions in binary form must reproduce the above copyright
11545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner *    notice, this list of conditions and the following disclaimer in
12545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner *    the documentation and/or other materials provided with the
13545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner *    distribution.
14545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner *
15545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * SUCH DAMAGE.
27545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner */
28545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner#include <pthread.h>
29545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner#include <errno.h>
30545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner#include <string.h>
31545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner#include <stdarg.h>
32545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner#include <stdio.h>
33545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner#include <stdlib.h>
34545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
35545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner/* Posix states that EDEADLK should be returned in case a deadlock condition
36545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * is detected with a PTHREAD_MUTEX_ERRORCHECK lock() or trylock(), but
37545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * GLibc returns EBUSY instead.
38545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner */
39545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner#ifdef HOST
40545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner#  define ERRNO_PTHREAD_EDEADLK   EBUSY
41545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner#else
42545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner#  define ERRNO_PTHREAD_EDEADLK   EDEADLK
43545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner#endif
44545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
45545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turnerstatic void __attribute__((noreturn))
46545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turnerpanic(const char* func, const char* format, ...)
47545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner{
48545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    va_list  args;
49545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    fprintf(stderr, "%s: ", func);
50545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    va_start(args, format);
51545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    vfprintf(stderr, format, args);
52545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    va_end(args);
53545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    fprintf(stderr, "\n");
54545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    exit(1);
55545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner}
56545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
57545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner#define  PANIC(...)   panic(__FUNCTION__,__VA_ARGS__)
58545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
59545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turnerstatic void __attribute__((noreturn))
60545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turnererror(int  errcode, const char* func, const char* format, ...)
61545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner{
62545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    va_list  args;
63545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    fprintf(stderr, "%s: ", func);
64545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    va_start(args, format);
65545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    vfprintf(stderr, format, args);
66545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    va_end(args);
67545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    fprintf(stderr, " error=%d: %s\n", errcode, strerror(errcode));
68545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    exit(1);
69545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner}
70545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
71545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner/* return current time in seconds as floating point value */
72545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turnerstatic double
73545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turnertime_now(void)
74545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner{
75545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    struct timespec ts[1];
76545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
77545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    clock_gettime(CLOCK_MONOTONIC, ts);
78545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    return (double)ts->tv_sec + ts->tv_nsec/1e9;
79545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner}
80545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
81545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turnerstatic void
82545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turnertime_sleep(double  delay)
83545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner{
84545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    struct timespec ts;
85545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    int             ret;
86545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
87545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    ts.tv_sec  = (time_t)delay;
88545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    ts.tv_nsec = (long)((delay - ts.tv_sec)*1e9);
89545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
90545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    do {
91545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner        ret = nanosleep(&ts, &ts);
92545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    } while (ret < 0 && errno == EINTR);
93545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner}
94545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
95545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner#define  ERROR(errcode,...)   error((errcode),__FUNCTION__,__VA_ARGS__)
96545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
97545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner#define  TZERO(cond)   \
98545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    { int _ret = (cond); if (_ret != 0) ERROR(_ret,"%d:%s", __LINE__, #cond); }
99545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
100545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner#define  TTRUE(cond)   \
101545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    { if (!(cond)) PANIC("%d:%s", __LINE__, #cond); }
102545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
103545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner#define  TFALSE(cond)   \
104545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    { if (!!(cond)) PANIC("%d:%s", __LINE__, #cond); }
105545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
106545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner#define  TEXPECT_INT(cond,val) \
107545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    { int _ret = (cond); if (_ret != (val)) PANIC("%d:%s returned %d (%d expected)", __LINE__, #cond, _ret, (val)); }
108545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
109545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner/* perform a simple init/lock/unlock/destroy test on a rwlock of given attributes */
110545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turnerstatic void do_test_rwlock_rd1(pthread_rwlockattr_t *attr)
111545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner{
112545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    int               ret;
113545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    pthread_rwlock_t  lock[1];
114545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
115545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_init(lock, attr));
116545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_rdlock(lock));
117545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_unlock(lock));
118545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_destroy(lock));
119545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner}
120545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
121545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turnerstatic void do_test_rwlock_wr1(pthread_rwlockattr_t *attr)
122545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner{
123545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    int               ret;
124545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    pthread_rwlock_t  lock[1];
125545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
126545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_init(lock, attr));
127545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_wrlock(lock));
128545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_unlock(lock));
129545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_destroy(lock));
130545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner}
131545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
132545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turnerstatic void set_rwlockattr_shared(pthread_rwlockattr_t *attr, int shared)
133545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner{
134545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    int  newshared;
135545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlockattr_setpshared(attr, shared));
136545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    newshared = ~shared;
137545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlockattr_getpshared(attr, &newshared));
138545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TEXPECT_INT(newshared,shared);
139545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner}
140545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
141545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner/* simple init/lock/unlock/destroy on all rwlock types */
142545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turnerstatic void do_test_1(void)
143545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner{
144545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    int                  ret, type;
145545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    pthread_rwlockattr_t  attr[1];
146545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
147545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    do_test_rwlock_rd1(NULL);
148545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    do_test_rwlock_wr1(NULL);
149545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
150545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    /* non-shared version */
151545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
152545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlockattr_init(attr));
153545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
154545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    set_rwlockattr_shared(attr, PTHREAD_PROCESS_PRIVATE);
155545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    do_test_rwlock_rd1(attr);
156545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    do_test_rwlock_wr1(attr);
157545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
158545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    set_rwlockattr_shared(attr, PTHREAD_PROCESS_SHARED);
159545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    do_test_rwlock_rd1(attr);
160545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    do_test_rwlock_wr1(attr);
161545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
162545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlockattr_destroy(attr));
163545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner}
164545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
165545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turnerstatic void do_test_rwlock_rd2_rec(pthread_rwlockattr_t *attr)
166545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner{
167545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    pthread_rwlock_t  lock[1];
168545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
169545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_init(lock, attr));
170545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_tryrdlock(lock));
171545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_unlock(lock));
172545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_destroy(lock));
173545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
174545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_init(lock, attr));
175545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_tryrdlock(lock));
176545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_tryrdlock(lock));
177545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_unlock(lock));
178545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_unlock(lock));
179545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_destroy(lock));
180545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner}
181545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
182545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turnerstatic void do_test_rwlock_wr2_rec(pthread_rwlockattr_t *attr)
183545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner{
184545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    pthread_rwlock_t  lock[1];
185545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
186545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_init(lock, attr));
187545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_trywrlock(lock));
188545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_unlock(lock));
189545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_destroy(lock));
190545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
191545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_init(lock, attr));
192545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_trywrlock(lock));
193545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner#ifdef HOST
194545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    /* The host implementation (GLibc) does not support recursive
195545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner     * write locks */
196545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TEXPECT_INT(pthread_rwlock_trywrlock(lock),EBUSY);
197545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner#else
198545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    /* Our implementation supports recursive write locks ! */
199545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_trywrlock(lock));
200545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_unlock(lock));
201545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner#endif
202545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_unlock(lock));
203545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_destroy(lock));
204545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner}
205545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
206545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turnerstatic void do_test_2(void)
207545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner{
208545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    pthread_rwlockattr_t  attr[1];
209545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
210545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    do_test_rwlock_rd2_rec(NULL);
211545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    do_test_rwlock_wr2_rec(NULL);
212545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
213545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    /* non-shared version */
214545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
215545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlockattr_init(attr));
216545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
217545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    set_rwlockattr_shared(attr, PTHREAD_PROCESS_PRIVATE);
218545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    do_test_rwlock_rd2_rec(attr);
219545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    do_test_rwlock_wr2_rec(attr);
220545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
221545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    set_rwlockattr_shared(attr, PTHREAD_PROCESS_SHARED);
222545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    do_test_rwlock_rd2_rec(attr);
223545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    do_test_rwlock_wr2_rec(attr);
224545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
225545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlockattr_destroy(attr));
226545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner}
227545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
228545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner/* This is more complex example to test contention of rwlockes.
229545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * Essentially, what happens is this:
230545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner *
231545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * - main thread creates a rwlock and rdlocks it
232545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * - it then creates thread 1 and thread 2
233545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner *
234545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * - it then record the current time, sleep for a specific 'waitDelay'
235545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner *   then unlock the rwlock.
236545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner *
237545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * - thread 1 tryrdlocks() the rwlock. It shall acquire the lock
238545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner *   immediately, then release it, then wrlock().
239545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner *
240545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * - thread 2 trywrlocks() the rwlock. In case of failure (EBUSY), it waits
241545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner *   for a small amount of time (see 'spinDelay') and tries again, until
242545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner *   it succeeds. It then unlocks the rwlock.
243545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner *
244545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * The goal of this test is to verify that thread 1 has been stopped
245545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * for a sufficiently long time (in the wrlock), and that thread 2 has
246545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * been spinning for the same minimum period. There is no guarantee as
247545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner * to which thread is going to acquire the rwlock first.
248545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner */
249545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turnertypedef struct {
250545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    pthread_rwlock_t  rwlock[1];
251545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    double            t0;
252545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    double            waitDelay;
253545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    double            spinDelay;
254545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner} Test3State;
255545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
256545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turnerstatic void* do_rwlock_test_rd3_t1(void* arg)
257545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner{
258545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    Test3State *s = arg;
259545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    double      t1;
260545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
261545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    /* try-acquire the lock, should succeed immediately */
262545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_tryrdlock(s->rwlock));
263545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_unlock(s->rwlock));
264545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
265545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    /* wrlock() the lock, now */
266545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_wrlock(s->rwlock));
267545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
268545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    t1 = time_now();
269545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    //DEBUG ONLY: printf("t1-s->t0=%g waitDelay=%g\n", t1-s->t0, s->waitDelay);
270545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TTRUE((t1-s->t0) >= s->waitDelay);
271545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_unlock(s->rwlock));
272545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    return NULL;
273545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner}
274545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
275545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turnerstatic void* do_rwlock_test_rd3_t2(void* arg)
276545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner{
277545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    Test3State *s = arg;
278545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    double      t1;
279545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
280545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    for (;;) {
281545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner        int ret = pthread_rwlock_trywrlock(s->rwlock);
282545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner        if (ret == 0)
283545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner            break;
284545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner        if (ret == EBUSY) {
285545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner            time_sleep(s->spinDelay);
286545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner            continue;
287545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner        }
288545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    }
289545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    t1 = time_now();
290545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TTRUE((t1-s->t0) >= s->waitDelay);
291545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_unlock(s->rwlock));
292545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    return NULL;
293545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner}
294545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
295545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
296545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turnerstatic void do_test_rwlock_rd3(pthread_rwlockattr_t *attr, double delay)
297545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner{
298545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    Test3State  s[1];
299545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    pthread_t   th1, th2;
300545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    void*       dummy;
301545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
302545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_init(s->rwlock, attr));
303545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    s->waitDelay = delay;
304545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    s->spinDelay = delay/20.;
305545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
306545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_rdlock(s->rwlock));
307545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
308545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    pthread_create(&th1, NULL, do_rwlock_test_rd3_t1, s);
309545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    pthread_create(&th2, NULL, do_rwlock_test_rd3_t2, s);
310545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
311545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    s->t0 = time_now();
312545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    time_sleep(delay);
313545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
314545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlock_unlock(s->rwlock));
315545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
316545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_join(th1, &dummy));
317545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_join(th2, &dummy));
318545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner}
319545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
320545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turnerstatic void do_test_3(double  delay)
321545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner{
322545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    pthread_rwlockattr_t  attr[1];
323545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
324545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    do_test_rwlock_rd3(NULL, delay);
325545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
326545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    /* non-shared version */
327545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
328545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlockattr_init(attr));
329545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
330545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    set_rwlockattr_shared(attr, PTHREAD_PROCESS_PRIVATE);
331545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    do_test_rwlock_rd3(attr, delay);
332545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
333545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    set_rwlockattr_shared(attr, PTHREAD_PROCESS_SHARED);
334545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    do_test_rwlock_rd3(attr, delay);
335545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
336545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    TZERO(pthread_rwlockattr_destroy(attr));
337545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner}
338545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
339545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner
340545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turnerint main(void)
341545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner{
342545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    do_test_1();
343545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    do_test_2();
344545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    do_test_3(0.1);
345545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner    return 0;
346545e6ca13f744650e4a62630f1b901c0840dcd43David 'Digit' Turner}
347