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