tc17_sembar.c revision 95d2242e2e1a24c327f95064e3451be68863b7ab
1b411202f9ff33a587558e2e836626bc7eb9db183sewardj#include <stdio.h> 2b411202f9ff33a587558e2e836626bc7eb9db183sewardj#include <stdlib.h> 3b411202f9ff33a587558e2e836626bc7eb9db183sewardj#include <assert.h> 4b411202f9ff33a587558e2e836626bc7eb9db183sewardj#include <pthread.h> 5b411202f9ff33a587558e2e836626bc7eb9db183sewardj#include <semaphore.h> 6e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj#include <unistd.h> 7b411202f9ff33a587558e2e836626bc7eb9db183sewardj/* This is really a test of semaphore handling 8b411202f9ff33a587558e2e836626bc7eb9db183sewardj (sem_{init,destroy,post,wait}). Using semaphores a barrier 9d024ae5ca3949fa1fa9bee62825c4e0d2bda31e3sewardj function is created. Helgrind-3.3 (p.k.a Thrcheck) does understand 10d024ae5ca3949fa1fa9bee62825c4e0d2bda31e3sewardj the barrier semantics implied by the barrier, as pieced together 11d024ae5ca3949fa1fa9bee62825c4e0d2bda31e3sewardj from happens-before relationships obtained from the component 12d024ae5ca3949fa1fa9bee62825c4e0d2bda31e3sewardj semaphores. However, it does falsely report one race. Ah well. 13d024ae5ca3949fa1fa9bee62825c4e0d2bda31e3sewardj Helgrind-3.4 is pure h-b and so reports no races (yay!). */ 14b411202f9ff33a587558e2e836626bc7eb9db183sewardj/* This code is derived from 15b411202f9ff33a587558e2e836626bc7eb9db183sewardj gcc-4.3-20071012/libgomp/config/posix/bar.c, which is 16b411202f9ff33a587558e2e836626bc7eb9db183sewardj 17b411202f9ff33a587558e2e836626bc7eb9db183sewardj Copyright (C) 2005 Free Software Foundation, Inc. 18b411202f9ff33a587558e2e836626bc7eb9db183sewardj Contributed by Richard Henderson <rth@redhat.com>. 19b411202f9ff33a587558e2e836626bc7eb9db183sewardj 20b411202f9ff33a587558e2e836626bc7eb9db183sewardj and available under version 2.1 or later of the GNU Lesser General 21b411202f9ff33a587558e2e836626bc7eb9db183sewardj Public License. 22b411202f9ff33a587558e2e836626bc7eb9db183sewardj 23b411202f9ff33a587558e2e836626bc7eb9db183sewardj Relative to the libgomp sources, the gomp_barrier_t type here has 24b411202f9ff33a587558e2e836626bc7eb9db183sewardj an extra semaphore field, xxx. This is not functionally useful, 25b411202f9ff33a587558e2e836626bc7eb9db183sewardj but it is used to create enough extra inter-thread dependencies 26b411202f9ff33a587558e2e836626bc7eb9db183sewardj that the barrier-like behaviour of gomp_barrier_t is evident to 27b411202f9ff33a587558e2e836626bc7eb9db183sewardj Thrcheck. There is no other purpose for the .xxx field. */ 2895d2242e2e1a24c327f95064e3451be68863b7abbartstatic sem_t* my_sem_init(char*, int, unsigned); 29e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardjstatic int my_sem_destroy(sem_t*); 30e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardjstatic int my_sem_wait(sem_t*); static int my_sem_post(sem_t*); 31b411202f9ff33a587558e2e836626bc7eb9db183sewardjtypedef struct 32b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 33b411202f9ff33a587558e2e836626bc7eb9db183sewardj pthread_mutex_t mutex1; 34b411202f9ff33a587558e2e836626bc7eb9db183sewardj pthread_mutex_t mutex2; 3595d2242e2e1a24c327f95064e3451be68863b7abbart sem_t* sem1; 3695d2242e2e1a24c327f95064e3451be68863b7abbart sem_t* sem2; 37b411202f9ff33a587558e2e836626bc7eb9db183sewardj unsigned total; 38b411202f9ff33a587558e2e836626bc7eb9db183sewardj unsigned arrived; 3995d2242e2e1a24c327f95064e3451be68863b7abbart sem_t* xxx; 40b411202f9ff33a587558e2e836626bc7eb9db183sewardj} gomp_barrier_t; 41b411202f9ff33a587558e2e836626bc7eb9db183sewardj 42b411202f9ff33a587558e2e836626bc7eb9db183sewardjtypedef long bool; 43b411202f9ff33a587558e2e836626bc7eb9db183sewardj 44b411202f9ff33a587558e2e836626bc7eb9db183sewardjvoid 45b411202f9ff33a587558e2e836626bc7eb9db183sewardjgomp_barrier_init (gomp_barrier_t *bar, unsigned count) 46b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 47b411202f9ff33a587558e2e836626bc7eb9db183sewardj pthread_mutex_init (&bar->mutex1, NULL); 48b411202f9ff33a587558e2e836626bc7eb9db183sewardj pthread_mutex_init (&bar->mutex2, NULL); 4995d2242e2e1a24c327f95064e3451be68863b7abbart bar->sem1 = my_sem_init ("sem1", 0, 0); 5095d2242e2e1a24c327f95064e3451be68863b7abbart bar->sem2 = my_sem_init ("sem2", 0, 0); 5195d2242e2e1a24c327f95064e3451be68863b7abbart bar->xxx = my_sem_init ("xxx", 0, 0); 52b411202f9ff33a587558e2e836626bc7eb9db183sewardj bar->total = count; 53b411202f9ff33a587558e2e836626bc7eb9db183sewardj bar->arrived = 0; 54b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 55b411202f9ff33a587558e2e836626bc7eb9db183sewardj 56b411202f9ff33a587558e2e836626bc7eb9db183sewardjvoid 57b411202f9ff33a587558e2e836626bc7eb9db183sewardjgomp_barrier_destroy (gomp_barrier_t *bar) 58b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 59b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* Before destroying, make sure all threads have left the barrier. */ 60b411202f9ff33a587558e2e836626bc7eb9db183sewardj pthread_mutex_lock (&bar->mutex1); 61b411202f9ff33a587558e2e836626bc7eb9db183sewardj pthread_mutex_unlock (&bar->mutex1); 62b411202f9ff33a587558e2e836626bc7eb9db183sewardj 63b411202f9ff33a587558e2e836626bc7eb9db183sewardj pthread_mutex_destroy (&bar->mutex1); 64b411202f9ff33a587558e2e836626bc7eb9db183sewardj pthread_mutex_destroy (&bar->mutex2); 6595d2242e2e1a24c327f95064e3451be68863b7abbart my_sem_destroy(bar->sem1); 6695d2242e2e1a24c327f95064e3451be68863b7abbart my_sem_destroy(bar->sem2); 6795d2242e2e1a24c327f95064e3451be68863b7abbart my_sem_destroy(bar->xxx); 68b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 69b411202f9ff33a587558e2e836626bc7eb9db183sewardj 70b411202f9ff33a587558e2e836626bc7eb9db183sewardjvoid 71b411202f9ff33a587558e2e836626bc7eb9db183sewardjgomp_barrier_reinit (gomp_barrier_t *bar, unsigned count) 72b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 73b411202f9ff33a587558e2e836626bc7eb9db183sewardj pthread_mutex_lock (&bar->mutex1); 74b411202f9ff33a587558e2e836626bc7eb9db183sewardj bar->total = count; 75b411202f9ff33a587558e2e836626bc7eb9db183sewardj pthread_mutex_unlock (&bar->mutex1); 76b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 77b411202f9ff33a587558e2e836626bc7eb9db183sewardj 78b411202f9ff33a587558e2e836626bc7eb9db183sewardjvoid 79b411202f9ff33a587558e2e836626bc7eb9db183sewardjgomp_barrier_wait (gomp_barrier_t *bar) 80b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 81b411202f9ff33a587558e2e836626bc7eb9db183sewardj unsigned int n; 82b411202f9ff33a587558e2e836626bc7eb9db183sewardj pthread_mutex_lock (&bar->mutex1); 83b411202f9ff33a587558e2e836626bc7eb9db183sewardj 84b411202f9ff33a587558e2e836626bc7eb9db183sewardj ++bar->arrived; 85b411202f9ff33a587558e2e836626bc7eb9db183sewardj 86b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (bar->arrived == bar->total) 87b411202f9ff33a587558e2e836626bc7eb9db183sewardj { 88b411202f9ff33a587558e2e836626bc7eb9db183sewardj bar->arrived--; 89b411202f9ff33a587558e2e836626bc7eb9db183sewardj n = bar->arrived; 90b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (n > 0) 91b411202f9ff33a587558e2e836626bc7eb9db183sewardj { 92b411202f9ff33a587558e2e836626bc7eb9db183sewardj { unsigned int i; 93b411202f9ff33a587558e2e836626bc7eb9db183sewardj for (i = 0; i < n; i++) 9495d2242e2e1a24c327f95064e3451be68863b7abbart my_sem_wait(bar->xxx); // acquire an obvious dependency from 95b411202f9ff33a587558e2e836626bc7eb9db183sewardj // all other threads arriving at the barrier 96b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 97b411202f9ff33a587558e2e836626bc7eb9db183sewardj // 1 up n times, 2 down once 98b411202f9ff33a587558e2e836626bc7eb9db183sewardj // now let all the other threads past the barrier, giving them 99b411202f9ff33a587558e2e836626bc7eb9db183sewardj // an obvious dependency with this thread. 100b411202f9ff33a587558e2e836626bc7eb9db183sewardj do 10195d2242e2e1a24c327f95064e3451be68863b7abbart my_sem_post (bar->sem1); // 1 up 102b411202f9ff33a587558e2e836626bc7eb9db183sewardj while (--n != 0); 103b411202f9ff33a587558e2e836626bc7eb9db183sewardj // and wait till the last thread has left 10495d2242e2e1a24c327f95064e3451be68863b7abbart my_sem_wait (bar->sem2); // 2 down 105b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 106b411202f9ff33a587558e2e836626bc7eb9db183sewardj pthread_mutex_unlock (&bar->mutex1); 107e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj /* �Resultats professionnels!� First we made this thread have an 108b411202f9ff33a587558e2e836626bc7eb9db183sewardj obvious (Thrcheck-visible) dependency on all other threads 109b411202f9ff33a587558e2e836626bc7eb9db183sewardj calling gomp_barrier_wait. Then, we released them all again, 110b411202f9ff33a587558e2e836626bc7eb9db183sewardj so they all have a (visible) dependency on this thread. 111b411202f9ff33a587558e2e836626bc7eb9db183sewardj Transitively, the result is that all threads leaving the 112b411202f9ff33a587558e2e836626bc7eb9db183sewardj barrier have a a Thrcheck-visible dependency on all threads 113b411202f9ff33a587558e2e836626bc7eb9db183sewardj arriving at the barrier. As required. */ 114b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 115b411202f9ff33a587558e2e836626bc7eb9db183sewardj else 116b411202f9ff33a587558e2e836626bc7eb9db183sewardj { 117b411202f9ff33a587558e2e836626bc7eb9db183sewardj pthread_mutex_unlock (&bar->mutex1); 11895d2242e2e1a24c327f95064e3451be68863b7abbart my_sem_post(bar->xxx); 119b411202f9ff33a587558e2e836626bc7eb9db183sewardj // first N-1 threads wind up waiting here 12095d2242e2e1a24c327f95064e3451be68863b7abbart my_sem_wait (bar->sem1); // 1 down 121b411202f9ff33a587558e2e836626bc7eb9db183sewardj 122b411202f9ff33a587558e2e836626bc7eb9db183sewardj pthread_mutex_lock (&bar->mutex2); 123b411202f9ff33a587558e2e836626bc7eb9db183sewardj n = --bar->arrived; /* XXX see below */ 124b411202f9ff33a587558e2e836626bc7eb9db183sewardj pthread_mutex_unlock (&bar->mutex2); 125b411202f9ff33a587558e2e836626bc7eb9db183sewardj 126b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (n == 0) 12795d2242e2e1a24c327f95064e3451be68863b7abbart my_sem_post (bar->sem2); // 2 up 128b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 129b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 130b411202f9ff33a587558e2e836626bc7eb9db183sewardj 131b411202f9ff33a587558e2e836626bc7eb9db183sewardj 132b411202f9ff33a587558e2e836626bc7eb9db183sewardj/* re XXX, thrcheck reports a race at this point. It doesn't 133b411202f9ff33a587558e2e836626bc7eb9db183sewardj understand that bar->arrived is protected by mutex1 whilst threads 134b411202f9ff33a587558e2e836626bc7eb9db183sewardj are arriving at the barrier and by mutex2 whilst they are leaving, 135b411202f9ff33a587558e2e836626bc7eb9db183sewardj but not consistently by either of them. Oh well. */ 136b411202f9ff33a587558e2e836626bc7eb9db183sewardj 137b411202f9ff33a587558e2e836626bc7eb9db183sewardjstatic gomp_barrier_t bar; 138b411202f9ff33a587558e2e836626bc7eb9db183sewardj 139b411202f9ff33a587558e2e836626bc7eb9db183sewardj/* What's with the volatile here? It stops gcc compiling 140b411202f9ff33a587558e2e836626bc7eb9db183sewardj "if (myid == 4) { unprotected = 99; }" and 141b411202f9ff33a587558e2e836626bc7eb9db183sewardj "if (myid == 3) { unprotected = 88; }" into a conditional 142b411202f9ff33a587558e2e836626bc7eb9db183sewardj load followed by a store. The cmov/store sequence reads and 143b411202f9ff33a587558e2e836626bc7eb9db183sewardj writes memory in all threads and cause Thrcheck to (correctly) 144b411202f9ff33a587558e2e836626bc7eb9db183sewardj report a race, the underlying cause of which is that gcc is 145b411202f9ff33a587558e2e836626bc7eb9db183sewardj generating non threadsafe code. 146b411202f9ff33a587558e2e836626bc7eb9db183sewardj 147b411202f9ff33a587558e2e836626bc7eb9db183sewardj (The lack of) thread safe code generation by gcc is currently a 148b411202f9ff33a587558e2e836626bc7eb9db183sewardj hot topic. See the following discussions: 149b411202f9ff33a587558e2e836626bc7eb9db183sewardj http://gcc.gnu.org/ml/gcc/2007-10/msg00266.html 150b411202f9ff33a587558e2e836626bc7eb9db183sewardj http://lkml.org/lkml/2007/10/24/673 151b411202f9ff33a587558e2e836626bc7eb9db183sewardj and this is interesting background: 152b411202f9ff33a587558e2e836626bc7eb9db183sewardj www.hpl.hp.com/techreports/2004/HPL-2004-209.pdf 153b411202f9ff33a587558e2e836626bc7eb9db183sewardj*/ 15442a06975942581adbaadcda6c8f806831c709d50bartstatic volatile long unprotected = 0; 155b411202f9ff33a587558e2e836626bc7eb9db183sewardj 156b411202f9ff33a587558e2e836626bc7eb9db183sewardjvoid* child ( void* argV ) 157b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 158b411202f9ff33a587558e2e836626bc7eb9db183sewardj long myid = (long)argV; 159b411202f9ff33a587558e2e836626bc7eb9db183sewardj // assert(myid >= 2 && myid <= 5); 160b411202f9ff33a587558e2e836626bc7eb9db183sewardj 161b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* First, we all wait to get to this point. */ 162b411202f9ff33a587558e2e836626bc7eb9db183sewardj gomp_barrier_wait( &bar ); 163b411202f9ff33a587558e2e836626bc7eb9db183sewardj 164b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* Now, thread #4 writes to 'unprotected' and so becomes its 165b411202f9ff33a587558e2e836626bc7eb9db183sewardj owner. */ 166b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (myid == 4) { 167b411202f9ff33a587558e2e836626bc7eb9db183sewardj unprotected = 99; 168b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 169b411202f9ff33a587558e2e836626bc7eb9db183sewardj 170b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* Now we all wait again. */ 171b411202f9ff33a587558e2e836626bc7eb9db183sewardj gomp_barrier_wait( &bar ); 172b411202f9ff33a587558e2e836626bc7eb9db183sewardj 173b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* This time, thread #3 writes to 'unprotected'. If all goes well, 174b411202f9ff33a587558e2e836626bc7eb9db183sewardj Thrcheck sees the dependency through the barrier back to thread 175b411202f9ff33a587558e2e836626bc7eb9db183sewardj #4 before it, and so thread #3 becomes the exclusive owner of 176b411202f9ff33a587558e2e836626bc7eb9db183sewardj 'unprotected'. */ 177b411202f9ff33a587558e2e836626bc7eb9db183sewardj if (myid == 3) { 178b411202f9ff33a587558e2e836626bc7eb9db183sewardj unprotected = 88; 179b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 180b411202f9ff33a587558e2e836626bc7eb9db183sewardj 181b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* And just to be on the safe side ... */ 182b411202f9ff33a587558e2e836626bc7eb9db183sewardj gomp_barrier_wait( &bar ); 183b411202f9ff33a587558e2e836626bc7eb9db183sewardj return NULL; 184b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 185b411202f9ff33a587558e2e836626bc7eb9db183sewardj 186b411202f9ff33a587558e2e836626bc7eb9db183sewardj 187b411202f9ff33a587558e2e836626bc7eb9db183sewardjint main (int argc, char *argv[]) 188b411202f9ff33a587558e2e836626bc7eb9db183sewardj{ 189b411202f9ff33a587558e2e836626bc7eb9db183sewardj long i; int res; 190b411202f9ff33a587558e2e836626bc7eb9db183sewardj pthread_t thr[4]; 191b411202f9ff33a587558e2e836626bc7eb9db183sewardj fprintf(stderr, "starting\n"); 192b411202f9ff33a587558e2e836626bc7eb9db183sewardj 193b411202f9ff33a587558e2e836626bc7eb9db183sewardj gomp_barrier_init( &bar, 4 ); 194b411202f9ff33a587558e2e836626bc7eb9db183sewardj 195b411202f9ff33a587558e2e836626bc7eb9db183sewardj for (i = 0; i < 4; i++) { 196b411202f9ff33a587558e2e836626bc7eb9db183sewardj res = pthread_create( &thr[i], NULL, child, (void*)(i+2) ); 197b411202f9ff33a587558e2e836626bc7eb9db183sewardj assert(!res); 198b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 199b411202f9ff33a587558e2e836626bc7eb9db183sewardj 200b411202f9ff33a587558e2e836626bc7eb9db183sewardj for (i = 0; i < 4; i++) { 201b411202f9ff33a587558e2e836626bc7eb9db183sewardj res = pthread_join( thr[i], NULL ); 202b411202f9ff33a587558e2e836626bc7eb9db183sewardj assert(!res); 203b411202f9ff33a587558e2e836626bc7eb9db183sewardj } 204b411202f9ff33a587558e2e836626bc7eb9db183sewardj 205b411202f9ff33a587558e2e836626bc7eb9db183sewardj gomp_barrier_destroy( &bar ); 206b411202f9ff33a587558e2e836626bc7eb9db183sewardj 207b411202f9ff33a587558e2e836626bc7eb9db183sewardj /* And finally here, the root thread can get exclusive ownership 208b411202f9ff33a587558e2e836626bc7eb9db183sewardj back from thread #4, because #4 has exited by this point and so 209b411202f9ff33a587558e2e836626bc7eb9db183sewardj we have a dependency edge back to the write it did. */ 210b411202f9ff33a587558e2e836626bc7eb9db183sewardj fprintf(stderr, "done, result is %ld, should be 88\n", unprotected); 211b411202f9ff33a587558e2e836626bc7eb9db183sewardj 212b411202f9ff33a587558e2e836626bc7eb9db183sewardj return 0; 213b411202f9ff33a587558e2e836626bc7eb9db183sewardj} 214e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj 215e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj 216e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj 217e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj 218e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj 219e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj 220e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj 22195d2242e2e1a24c327f95064e3451be68863b7abbartstatic sem_t* my_sem_init (char* identity, int pshared, unsigned count) 222e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj{ 22395d2242e2e1a24c327f95064e3451be68863b7abbart sem_t* s; 22495d2242e2e1a24c327f95064e3451be68863b7abbart 225e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj#if defined(VGO_linux) 22695d2242e2e1a24c327f95064e3451be68863b7abbart s = malloc(sizeof(*s)); 22795d2242e2e1a24c327f95064e3451be68863b7abbart if (s) { 22895d2242e2e1a24c327f95064e3451be68863b7abbart if (sem_init(s, pshared, count) < 0) { 22995d2242e2e1a24c327f95064e3451be68863b7abbart perror("sem_init"); 23095d2242e2e1a24c327f95064e3451be68863b7abbart free(s); 23195d2242e2e1a24c327f95064e3451be68863b7abbart s = NULL; 23295d2242e2e1a24c327f95064e3451be68863b7abbart } 23395d2242e2e1a24c327f95064e3451be68863b7abbart } 234e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj#elif defined(VGO_darwin) 235e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj char name[100]; 236e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj sprintf(name, "anonsem_%s_pid%d", identity, (int)getpid()); 237e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj name[ sizeof(name)-1 ] = 0; 238e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj if (0) printf("name = %s\n", name); 23995d2242e2e1a24c327f95064e3451be68863b7abbart s = sem_open(name, O_CREAT | O_EXCL, 0600, count); 24095d2242e2e1a24c327f95064e3451be68863b7abbart if (s == SEM_FAILED) { 24195d2242e2e1a24c327f95064e3451be68863b7abbart perror("sem_open"); 24295d2242e2e1a24c327f95064e3451be68863b7abbart s = NULL; 24395d2242e2e1a24c327f95064e3451be68863b7abbart } 244e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj#else 245e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj# error "Unsupported OS" 246e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj#endif 24795d2242e2e1a24c327f95064e3451be68863b7abbart 24895d2242e2e1a24c327f95064e3451be68863b7abbart return s; 249e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj} 250e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj 251e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardjstatic int my_sem_destroy ( sem_t* s ) 252e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj{ 253e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj return sem_destroy(s); 254e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj} 255e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj 256e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardjstatic int my_sem_wait(sem_t* s) 257e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj{ 258e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj return sem_wait(s); 259e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj} 260e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj 261e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardjstatic int my_sem_post(sem_t* s) 262e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj{ 263e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj return sem_post(s); 264e84c7f437ada7b7ceade1a00498f663e15ea7b57sewardj} 265