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