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