1b411202f9ff33a587558e2e836626bc7eb9db183sewardj/* This program attempts to verify that all functions that are
2b411202f9ff33a587558e2e836626bc7eb9db183sewardj   supposed to be wrapped by tc_intercepts.c really are wrapped.  The
3b411202f9ff33a587558e2e836626bc7eb9db183sewardj   main way it does this is to cause failures in those functions, so
4b411202f9ff33a587558e2e836626bc7eb9db183sewardj   as to obtain various error messages which imply that the wrapper
5b411202f9ff33a587558e2e836626bc7eb9db183sewardj   really did engage.
6b411202f9ff33a587558e2e836626bc7eb9db183sewardj
7b411202f9ff33a587558e2e836626bc7eb9db183sewardj   Any regressions shown up by this program are potentially serious
8b411202f9ff33a587558e2e836626bc7eb9db183sewardj   and should be investigated carefully. */
9b411202f9ff33a587558e2e836626bc7eb9db183sewardj
10b411202f9ff33a587558e2e836626bc7eb9db183sewardj/* Needed for older glibcs (2.3 and older, at least) who don't
11b411202f9ff33a587558e2e836626bc7eb9db183sewardj   otherwise "know" about some more exotic pthread stuff, in this case
12b411202f9ff33a587558e2e836626bc7eb9db183sewardj   PTHREAD_MUTEX_ERRORCHECK. */
13b411202f9ff33a587558e2e836626bc7eb9db183sewardj#define _GNU_SOURCE 1
14b411202f9ff33a587558e2e836626bc7eb9db183sewardj#include <stdio.h>
15b411202f9ff33a587558e2e836626bc7eb9db183sewardj#include <string.h>
16b411202f9ff33a587558e2e836626bc7eb9db183sewardj#include <assert.h>
17b411202f9ff33a587558e2e836626bc7eb9db183sewardj#include <unistd.h>
1802b13a1023bf6d80d04095e71004d26498758b51tom#include "safe-pthread.h"
190c66d2e4293ee50ddb9b248107bfcdfffa96ccdamjw#include "safe-semaphore.h"
20b411202f9ff33a587558e2e836626bc7eb9db183sewardj
216e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#if !defined(__APPLE__)
222ee33955b80812a8f31ec06a0430103b50aeca8csewardj
238eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#if defined(__sun__)
248eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/* Fake __GLIBC_PREREQ on Solaris. Pretend glibc >= 2.4. */
258eb8bab992e3998c33770b0cdb16059a8b918a06sewardj# define __GLIBC_PREREQ
268eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#else
27b411202f9ff33a587558e2e836626bc7eb9db183sewardj#if !defined(__GLIBC_PREREQ)
28b411202f9ff33a587558e2e836626bc7eb9db183sewardj# error "This program needs __GLIBC_PREREQ (in /usr/include/features.h)"
29b411202f9ff33a587558e2e836626bc7eb9db183sewardj#endif
308eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#endif /* __sun__ */
31b411202f9ff33a587558e2e836626bc7eb9db183sewardj
32a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughestypedef union {
33a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   pthread_spinlock_t spinlock;
34a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   pthread_rwlock_t rwlock;
35a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes} spin_rw_lock;
36a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes
37b411202f9ff33a587558e2e836626bc7eb9db183sewardjshort unprotected = 0;
38b411202f9ff33a587558e2e836626bc7eb9db183sewardj
39b411202f9ff33a587558e2e836626bc7eb9db183sewardjvoid* lazy_child ( void* v ) {
40b411202f9ff33a587558e2e836626bc7eb9db183sewardj   assert(0); /* does not run */
41b411202f9ff33a587558e2e836626bc7eb9db183sewardj}
42b411202f9ff33a587558e2e836626bc7eb9db183sewardj
43b411202f9ff33a587558e2e836626bc7eb9db183sewardjvoid* racy_child ( void* v ) {
44b411202f9ff33a587558e2e836626bc7eb9db183sewardj   unprotected = 1234;
45b411202f9ff33a587558e2e836626bc7eb9db183sewardj   return NULL;
46b411202f9ff33a587558e2e836626bc7eb9db183sewardj}
47b411202f9ff33a587558e2e836626bc7eb9db183sewardj
48b411202f9ff33a587558e2e836626bc7eb9db183sewardjint main ( void )
49b411202f9ff33a587558e2e836626bc7eb9db183sewardj{
50b411202f9ff33a587558e2e836626bc7eb9db183sewardj   int r;
51b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* pthread_t thr; */
52b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* pthread_attr_t thra; */
53b411202f9ff33a587558e2e836626bc7eb9db183sewardj   pthread_mutexattr_t mxa, mxa2;
54b411202f9ff33a587558e2e836626bc7eb9db183sewardj   pthread_mutex_t mx, mx2, mx3, mx4;
55b411202f9ff33a587558e2e836626bc7eb9db183sewardj   pthread_cond_t cv;
56b411202f9ff33a587558e2e836626bc7eb9db183sewardj   struct timespec abstime;
57b411202f9ff33a587558e2e836626bc7eb9db183sewardj   pthread_rwlock_t rwl;
58b411202f9ff33a587558e2e836626bc7eb9db183sewardj   pthread_rwlock_t rwl2;
59b411202f9ff33a587558e2e836626bc7eb9db183sewardj   pthread_rwlock_t rwl3;
60b411202f9ff33a587558e2e836626bc7eb9db183sewardj   sem_t s1;
61b411202f9ff33a587558e2e836626bc7eb9db183sewardj
62b411202f9ff33a587558e2e836626bc7eb9db183sewardj#  if __GLIBC_PREREQ(2,4)
63b411202f9ff33a587558e2e836626bc7eb9db183sewardj   fprintf(stderr,
64b411202f9ff33a587558e2e836626bc7eb9db183sewardj           "\n\n------ This is output for >= glibc 2.4 ------\n");
65b411202f9ff33a587558e2e836626bc7eb9db183sewardj#  else
66b411202f9ff33a587558e2e836626bc7eb9db183sewardj   fprintf(stderr,
67b411202f9ff33a587558e2e836626bc7eb9db183sewardj           "\n\n------ This is output for < glibc 2.4 ------\n");
68b411202f9ff33a587558e2e836626bc7eb9db183sewardj#  endif
69b411202f9ff33a587558e2e836626bc7eb9db183sewardj
70b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* --------- pthread_create/join --------- */
71b411202f9ff33a587558e2e836626bc7eb9db183sewardj
72b411202f9ff33a587558e2e836626bc7eb9db183sewardj   fprintf(stderr,
73b411202f9ff33a587558e2e836626bc7eb9db183sewardj   "\n---------------- pthread_create/join ----------------\n\n");
74b411202f9ff33a587558e2e836626bc7eb9db183sewardj
75b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* make pthread_create fail */
76b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* It's amazingly difficult to make pthread_create fail
77b411202f9ff33a587558e2e836626bc7eb9db183sewardj      without first soaking up all the machine's resources.
78b411202f9ff33a587558e2e836626bc7eb9db183sewardj      Instead, in order to demonstrate that it's really wrapped,
79b411202f9ff33a587558e2e836626bc7eb9db183sewardj      create a child thread, generate a race error, and join with it
80b411202f9ff33a587558e2e836626bc7eb9db183sewardj      again. */
81b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* This just segfaults:
82b411202f9ff33a587558e2e836626bc7eb9db183sewardj      memset( &thra, 0xFF, sizeof(thra) );
83b411202f9ff33a587558e2e836626bc7eb9db183sewardj      r= pthread_create( &thr, NULL, lazy_child, NULL ); assert(r);
84b411202f9ff33a587558e2e836626bc7eb9db183sewardj   */
85b411202f9ff33a587558e2e836626bc7eb9db183sewardj   { pthread_t child;
86b411202f9ff33a587558e2e836626bc7eb9db183sewardj     r= pthread_create( &child, NULL, racy_child, NULL ); assert(!r);
87b411202f9ff33a587558e2e836626bc7eb9db183sewardj     sleep(1); /* just to ensure parent thread reports race, not child */
88b411202f9ff33a587558e2e836626bc7eb9db183sewardj     unprotected = 5678;
89b411202f9ff33a587558e2e836626bc7eb9db183sewardj     r= pthread_join( child, NULL ); assert(!r);
90b411202f9ff33a587558e2e836626bc7eb9db183sewardj   }
91b411202f9ff33a587558e2e836626bc7eb9db183sewardj
92b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* make pthread_join fail */
93b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_join( pthread_self(), NULL ); assert(r);
94b411202f9ff33a587558e2e836626bc7eb9db183sewardj
95b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* --------- pthread_mutex_lock et al --------- */
96b411202f9ff33a587558e2e836626bc7eb9db183sewardj
97b411202f9ff33a587558e2e836626bc7eb9db183sewardj   fprintf(stderr,
98b411202f9ff33a587558e2e836626bc7eb9db183sewardj   "\n---------------- pthread_mutex_lock et al ----------------\n\n");
99b411202f9ff33a587558e2e836626bc7eb9db183sewardj
100b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* make pthread_mutex_init fail */
1018eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#if defined(__sun__)
1028eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   pthread_mutexattr_init( &mxa );
1038eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   memset( mxa.__pthread_mutexattrp, 0xFF, 5 * sizeof(int) );
1048eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#else
105b411202f9ff33a587558e2e836626bc7eb9db183sewardj   memset( &mxa, 0xFF, sizeof(mxa) );
1068eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#endif
107b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_mutex_init( &mx, &mxa );
108b411202f9ff33a587558e2e836626bc7eb9db183sewardj#  if __GLIBC_PREREQ(2,4)
109b411202f9ff33a587558e2e836626bc7eb9db183sewardj   assert(r); /* glibc >= 2.4: the call should fail */
110b411202f9ff33a587558e2e836626bc7eb9db183sewardj#  else
111b411202f9ff33a587558e2e836626bc7eb9db183sewardj   assert(!r); /* glibc < 2.4: oh well, glibc didn't bounce this */
112b411202f9ff33a587558e2e836626bc7eb9db183sewardj#  endif
113b411202f9ff33a587558e2e836626bc7eb9db183sewardj
114b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* make pthread_mutex_destroy fail */
115b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_mutex_init( &mx2, NULL ); assert(!r);
116b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_mutex_lock( &mx2 ); assert(!r);
117d94082ef226012b4ed34155262deeeede2fe3e54bart   r= pthread_mutex_destroy( &mx2 );
118b411202f9ff33a587558e2e836626bc7eb9db183sewardj
119b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* make pthread_mutex_lock fail (skipped on < glibc 2.4 because it
120b411202f9ff33a587558e2e836626bc7eb9db183sewardj      doesn't fail, hence hangs the test) */
121b411202f9ff33a587558e2e836626bc7eb9db183sewardj#  if __GLIBC_PREREQ(2,4)
122b411202f9ff33a587558e2e836626bc7eb9db183sewardj   memset( &mx3, 0xFF, sizeof(mx3) );
123b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_mutex_lock( &mx3 ); assert(r);
124b411202f9ff33a587558e2e836626bc7eb9db183sewardj#  else
125b411202f9ff33a587558e2e836626bc7eb9db183sewardj   fprintf(stderr, "\nmake pthread_mutex_lock fail: "
126b411202f9ff33a587558e2e836626bc7eb9db183sewardj                   "skipped on glibc < 2.4\n\n");
127b411202f9ff33a587558e2e836626bc7eb9db183sewardj#  endif
128b411202f9ff33a587558e2e836626bc7eb9db183sewardj
129b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* make pthread_mutex_trylock fail */
130b411202f9ff33a587558e2e836626bc7eb9db183sewardj   memset( &mx3, 0xFF, sizeof(mx3) );
131b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_mutex_trylock( &mx3 ); assert(r);
132b411202f9ff33a587558e2e836626bc7eb9db183sewardj
133b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* make pthread_mutex_timedlock fail */
134b411202f9ff33a587558e2e836626bc7eb9db183sewardj   memset( &abstime, 0, sizeof(abstime) );
135b411202f9ff33a587558e2e836626bc7eb9db183sewardj   memset( &mx3, 0xFF, sizeof(mx3) );
136b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_mutex_timedlock( &mx3, &abstime ); assert(r);
137b411202f9ff33a587558e2e836626bc7eb9db183sewardj
138b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* make pthread_mutex_unlock fail */
139b411202f9ff33a587558e2e836626bc7eb9db183sewardj   memset( &mx3, 0xFF, sizeof(mx3) );
140b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_mutex_unlock( &mx3 );
141b411202f9ff33a587558e2e836626bc7eb9db183sewardj#  if __GLIBC_PREREQ(2,4)
142b411202f9ff33a587558e2e836626bc7eb9db183sewardj   assert(r);
143b411202f9ff33a587558e2e836626bc7eb9db183sewardj#  else
144b411202f9ff33a587558e2e836626bc7eb9db183sewardj   assert(!r);
145b411202f9ff33a587558e2e836626bc7eb9db183sewardj#  endif
146b411202f9ff33a587558e2e836626bc7eb9db183sewardj
147b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* --------- pthread_cond_wait et al --------- */
148b411202f9ff33a587558e2e836626bc7eb9db183sewardj
149b411202f9ff33a587558e2e836626bc7eb9db183sewardj   fprintf(stderr,
150b411202f9ff33a587558e2e836626bc7eb9db183sewardj   "\n---------------- pthread_cond_wait et al ----------------\n\n");
151b411202f9ff33a587558e2e836626bc7eb9db183sewardj
152b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* make pthread_cond_wait fail.  This is difficult.  Our cunning
153b411202f9ff33a587558e2e836626bc7eb9db183sewardj      plan (tm) is to show up at pthread_cond_wait bearing a
154b411202f9ff33a587558e2e836626bc7eb9db183sewardj      not-locked mutex of the ERRORCHECK flavour and hope (as is
155b411202f9ff33a587558e2e836626bc7eb9db183sewardj      indeed the case with glibc-2.5) that pthread_cond_wait notices
156b411202f9ff33a587558e2e836626bc7eb9db183sewardj      it is not locked, and bounces our request. */
157b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_mutexattr_init( &mxa2 ); assert(!r);
158b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_mutexattr_settype( &mxa2, PTHREAD_MUTEX_ERRORCHECK );
159b411202f9ff33a587558e2e836626bc7eb9db183sewardj      assert(!r);
160b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_mutex_init( &mx4, &mxa2 ); assert(!r);
161b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_cond_init( &cv, NULL ); assert(!r);
162b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_cond_wait( &cv, &mx4 ); assert(r);
163b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_mutexattr_destroy( &mxa2 ); assert(!r);
164b411202f9ff33a587558e2e836626bc7eb9db183sewardj
165b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* make pthread_cond_signal fail.  FIXME: can't figure out how
166b411202f9ff33a587558e2e836626bc7eb9db183sewardj      to */
167b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_cond_signal( &cv ); assert(!r);
168b411202f9ff33a587558e2e836626bc7eb9db183sewardj   fprintf(stderr, "\nFIXME: can't figure out how to "
169b411202f9ff33a587558e2e836626bc7eb9db183sewardj                   "verify wrap of pthread_cond_signal\n\n");
170b411202f9ff33a587558e2e836626bc7eb9db183sewardj
171b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* make pthread_cond_broadcast fail.  FIXME: can't figure out how
172b411202f9ff33a587558e2e836626bc7eb9db183sewardj      to */
173b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_cond_broadcast( &cv ); assert(!r);
174b411202f9ff33a587558e2e836626bc7eb9db183sewardj   fprintf(stderr, "\nFIXME: can't figure out how to "
175b411202f9ff33a587558e2e836626bc7eb9db183sewardj                   "verify wrap of pthread_broadcast_signal\n\n");
176b411202f9ff33a587558e2e836626bc7eb9db183sewardj
177b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* make pthread_cond_timedwait fail. */
178b411202f9ff33a587558e2e836626bc7eb9db183sewardj   memset( &abstime, 0, sizeof(abstime) );
179b411202f9ff33a587558e2e836626bc7eb9db183sewardj   abstime.tv_nsec = 1000000000 + 1;
180b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_cond_timedwait( &cv, &mx4, &abstime ); assert(r);
181b411202f9ff33a587558e2e836626bc7eb9db183sewardj
182b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* --------- pthread_rwlock_* --------- */
183b411202f9ff33a587558e2e836626bc7eb9db183sewardj
184b411202f9ff33a587558e2e836626bc7eb9db183sewardj   fprintf(stderr,
185b411202f9ff33a587558e2e836626bc7eb9db183sewardj   "\n---------------- pthread_rwlock_* ----------------\n\n");
186b411202f9ff33a587558e2e836626bc7eb9db183sewardj
187b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* pthread_rwlock_init, pthread_rwlock_unlock */
188b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* pthread_rwlock_init: can't make glibc's implementation fail.
189b411202f9ff33a587558e2e836626bc7eb9db183sewardj      However, can demonstrate interceptedness by initialising but not
190b411202f9ff33a587558e2e836626bc7eb9db183sewardj      locking a lock and then unlocking it.  Then the unlock call
191b411202f9ff33a587558e2e836626bc7eb9db183sewardj      should say "first seen at .. the init call."  So this tests
192b411202f9ff33a587558e2e836626bc7eb9db183sewardj      wrappedness of both calls. */
193b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_rwlock_init( &rwl, NULL ); assert(!r);
194b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_rwlock_unlock( &rwl );
195b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* assert(r); *//* glibc doesn't complain.  It really ought to. Oh well. */
196b411202f9ff33a587558e2e836626bc7eb9db183sewardj
197b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* We can infer the presence of wrapping for pthread_rwlock_rdlock,
198b411202f9ff33a587558e2e836626bc7eb9db183sewardj      pthread_rwlock_wrlock and pthread_rwlock_unlock by making
199b411202f9ff33a587558e2e836626bc7eb9db183sewardj      Thrcheck count the lockedness state, and warning when we unlock
200b411202f9ff33a587558e2e836626bc7eb9db183sewardj      a not-locked lock.  Thusly: */
201b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_rwlock_init( &rwl2, NULL ); assert(!r);
202b411202f9ff33a587558e2e836626bc7eb9db183sewardj
203b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* w-lock it */
204b411202f9ff33a587558e2e836626bc7eb9db183sewardj   fprintf(stderr, "(1) no error on next line\n");
205b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_rwlock_wrlock( &rwl2 ); assert(!r);
206b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* unlock it */
207b411202f9ff33a587558e2e836626bc7eb9db183sewardj   fprintf(stderr, "(2) no error on next line\n");
208b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_rwlock_unlock( &rwl2 ); assert(!r);
209b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* unlock it again, get an error */
210b411202f9ff33a587558e2e836626bc7eb9db183sewardj   fprintf(stderr, "(3)    ERROR on next line\n");
2118eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   r= pthread_rwlock_unlock( &rwl2 );
2128eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#if defined(__sun__)
2138eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   assert(r);
2148eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#else
2158eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   assert(!r);
2168eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#endif
217b411202f9ff33a587558e2e836626bc7eb9db183sewardj
218b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* same game with r-locks */
219b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_rwlock_init( &rwl2, NULL ); assert(!r);
220b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* r-lock it twice */
221b411202f9ff33a587558e2e836626bc7eb9db183sewardj   fprintf(stderr, "(4) no error on next line\n");
222b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_rwlock_rdlock( &rwl2 ); assert(!r);
223b411202f9ff33a587558e2e836626bc7eb9db183sewardj   fprintf(stderr, "(5) no error on next line\n");
224b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_rwlock_rdlock( &rwl2 ); assert(!r);
225b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* unlock it twice */
226b411202f9ff33a587558e2e836626bc7eb9db183sewardj   fprintf(stderr, "(6) no error on next line\n");
227b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_rwlock_unlock( &rwl2 ); assert(!r);
228b411202f9ff33a587558e2e836626bc7eb9db183sewardj   fprintf(stderr, "(7) no error on next line\n");
229b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_rwlock_unlock( &rwl2 ); assert(!r);
230b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* unlock it again, get an error */
231b411202f9ff33a587558e2e836626bc7eb9db183sewardj   fprintf(stderr, "(8)    ERROR on next line\n");
2328eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   r= pthread_rwlock_unlock( &rwl2 );
2338eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#if defined(__sun__)
2348eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   assert(r);
2358eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#else
2368eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   assert(!r);
2378eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#endif
238b411202f9ff33a587558e2e836626bc7eb9db183sewardj
239b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* Lock rwl3 so the locked-lock-at-dealloc check can complain about
240b411202f9ff33a587558e2e836626bc7eb9db183sewardj      it. */
241b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_rwlock_init( &rwl3, NULL ); assert(!r);
242b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= pthread_rwlock_rdlock( &rwl3 ); assert(!r);
243b411202f9ff33a587558e2e836626bc7eb9db183sewardj
244a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   /* --------- pthread_spin_* --------- */
245a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes
246a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   fprintf(stderr,
247a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   "\n---------------- pthread_spin_* ----------------\n\n");
248a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes
249a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   /* The following sequence verifies correct wrapping of pthread_spin_init()
250a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      and pthread_spin_destroy(). */
251a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   spin_rw_lock srwl1;
252a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   pthread_spin_init(&srwl1.spinlock, PTHREAD_PROCESS_PRIVATE);
253a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   pthread_spin_destroy(&srwl1.spinlock);
254a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes
255a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   pthread_rwlock_init(&srwl1.rwlock, NULL);
256a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   pthread_rwlock_destroy(&srwl1.rwlock);
257a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes
258b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* ------------- sem_* ------------- */
259b411202f9ff33a587558e2e836626bc7eb9db183sewardj
260b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* This is pretty lame, and duplicates tc18_semabuse.c. */
261b411202f9ff33a587558e2e836626bc7eb9db183sewardj
262b411202f9ff33a587558e2e836626bc7eb9db183sewardj   fprintf(stderr,
263b411202f9ff33a587558e2e836626bc7eb9db183sewardj   "\n---------------- sem_* ----------------\n\n");
264b411202f9ff33a587558e2e836626bc7eb9db183sewardj
265b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* verifies wrap of sem_init */
266b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* Do sem_init with huge initial count - fails */
267b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= sem_init(&s1, 0, ~0); assert(r);
268b411202f9ff33a587558e2e836626bc7eb9db183sewardj
269b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* initialise properly */
270b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= sem_init(&s1, 0, 0);
271b411202f9ff33a587558e2e836626bc7eb9db183sewardj
272b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* in glibc, sem_destroy is a no-op; making it fail is
273b411202f9ff33a587558e2e836626bc7eb9db183sewardj      impossible. */
274b411202f9ff33a587558e2e836626bc7eb9db183sewardj   fprintf(stderr, "\nFIXME: can't figure out how to verify wrap of "
275b411202f9ff33a587558e2e836626bc7eb9db183sewardj                   "sem_destroy\n\n");
276b411202f9ff33a587558e2e836626bc7eb9db183sewardj
277b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* verifies wrap of sem_wait */
278b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* Do 'wait' on a bogus semaphore.  This should fail, but on glibc
279b411202f9ff33a587558e2e836626bc7eb9db183sewardj      it succeeds. */
280b411202f9ff33a587558e2e836626bc7eb9db183sewardj   memset(&s1, 0x55, sizeof(s1));
281b411202f9ff33a587558e2e836626bc7eb9db183sewardj   r= sem_wait(&s1); /* assert(r != 0); */
282b411202f9ff33a587558e2e836626bc7eb9db183sewardj
283612c87b192fc6e5466d16ac6bb2448f1224e6fc9bart   /* this only fails with glibc 2.7 or later. */
284612c87b192fc6e5466d16ac6bb2448f1224e6fc9bart   r= sem_post(&s1);
285b411202f9ff33a587558e2e836626bc7eb9db183sewardj   fprintf(stderr, "\nFIXME: can't figure out how to verify wrap of "
286b411202f9ff33a587558e2e836626bc7eb9db183sewardj                   "sem_post\n\n");
287b411202f9ff33a587558e2e836626bc7eb9db183sewardj
288b411202f9ff33a587558e2e836626bc7eb9db183sewardj   sem_destroy(&s1);
289b411202f9ff33a587558e2e836626bc7eb9db183sewardj
290b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* ------------- dealloc of mem holding locks ------------- */
291b411202f9ff33a587558e2e836626bc7eb9db183sewardj
292b411202f9ff33a587558e2e836626bc7eb9db183sewardj   fprintf(stderr,
293b411202f9ff33a587558e2e836626bc7eb9db183sewardj   "\n------------ dealloc of mem holding locks ------------\n\n");
294b411202f9ff33a587558e2e836626bc7eb9db183sewardj
295b411202f9ff33a587558e2e836626bc7eb9db183sewardj   /* At this point it should complain about deallocation
296b411202f9ff33a587558e2e836626bc7eb9db183sewardj      of memory containing locked locks:
297b411202f9ff33a587558e2e836626bc7eb9db183sewardj         rwl3
298b411202f9ff33a587558e2e836626bc7eb9db183sewardj   */
299b411202f9ff33a587558e2e836626bc7eb9db183sewardj
300b411202f9ff33a587558e2e836626bc7eb9db183sewardj   return 0;
301b411202f9ff33a587558e2e836626bc7eb9db183sewardj}
3022ee33955b80812a8f31ec06a0430103b50aeca8csewardj
3036e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#else /* defined(__APPLE__) */
3042ee33955b80812a8f31ec06a0430103b50aeca8csewardjint main ( void )
3052ee33955b80812a8f31ec06a0430103b50aeca8csewardj{
3066e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj   fprintf(stderr, "This program does not work on Mac OS X.\n");
3072ee33955b80812a8f31ec06a0430103b50aeca8csewardj   return 0;
3082ee33955b80812a8f31ec06a0430103b50aeca8csewardj}
3092ee33955b80812a8f31ec06a0430103b50aeca8csewardj#endif
310