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