5
* This translation unit implements barrier primitives.
7
* Pthreads-win32 - POSIX Threads Library for Win32
10
* This library is free software; you can redistribute it and/or
11
* modify it under the terms of the GNU Library General Public
12
* License as published by the Free Software Foundation; either
13
* version 2 of the License, or (at your option) any later version.
15
* This library is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18
* Library General Public License for more details.
20
* You should have received a copy of the GNU Library General Public
21
* License along with this library; if not, write to the Free
22
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27
#include "implement.h"
35
#define _LPLONG PVOID*
39
pthread_barrier_init(pthread_barrier_t * barrier,
40
const pthread_barrierattr_t * attr,
45
if (barrier == NULL || count == 0)
50
if (NULL != (b = (pthread_barrier_t) calloc(1, sizeof(*b))))
52
b->pshared = (attr != NULL && *attr != NULL
54
: PTHREAD_PROCESS_PRIVATE);
56
b->nCurrentBarrierHeight = b->nInitialBarrierHeight = count;
60
* Two semaphores are used in the same way as two stepping
61
* stones might be used in crossing a stream. Once all
62
* threads are safely on one stone, the other stone can
63
* be moved ahead, and the threads can start moving to it.
64
* If some threads decide to eat their lunch before moving
65
* then the other threads have to wait.
67
if (0 == sem_init(&(b->semBarrierBreeched[0]), b->pshared, 0))
69
if (0 == sem_init(&(b->semBarrierBreeched[1]), b->pshared, 0))
74
(void) sem_destroy(&(b->semBarrierBreeched[0]));
83
pthread_barrier_destroy(pthread_barrier_t *barrier)
88
if (barrier == NULL || *barrier == (pthread_barrier_t) PTW32_OBJECT_INVALID)
96
if (0 == (result = sem_destroy(&(b->semBarrierBreeched[0]))))
98
if (0 == (result = sem_destroy(&(b->semBarrierBreeched[1]))))
103
(void) sem_init(&(b->semBarrierBreeched[0]),
114
pthread_barrier_wait(pthread_barrier_t *barrier)
120
if (barrier == NULL || *barrier == (pthread_barrier_t) PTW32_OBJECT_INVALID)
128
if (0 == InterlockedDecrement((long *) &(b->nCurrentBarrierHeight)))
130
/* Must be done before posting the semaphore. */
131
b->nCurrentBarrierHeight = b->nInitialBarrierHeight;
134
* There is no race condition between the semaphore wait and post
135
* because we are using two alternating semas and all threads have
136
* entered barrier_wait and checked nCurrentBarrierHeight before this
137
* barrier's sema can be posted. Any threads that have not quite
138
* entered sem_wait below when the multiple_post has completed
139
* will nevertheless continue through the semaphore (barrier)
140
* and will not be left stranded.
142
result = (b->nInitialBarrierHeight > 1
143
? sem_post_multiple(&(b->semBarrierBreeched[step]),
144
b->nInitialBarrierHeight - 1)
149
BOOL switchCancelState;
151
pthread_t self = pthread_self();
154
* This routine is not a cancelation point, so temporarily
155
* prevent sem_wait() from being one.
156
* PTHREAD_CANCEL_ASYNCHRONOUS threads can still be canceled.
158
switchCancelState = (self->cancelType == PTHREAD_CANCEL_DEFERRED &&
159
0 == pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,
162
result = sem_wait(&(b->semBarrierBreeched[step]));
164
if (switchCancelState)
166
(void) pthread_setcancelstate(oldCancelState, NULL);
171
* The first thread across will be the PTHREAD_BARRIER_SERIAL_THREAD.
172
* It also sets up the alternate semaphore as the next barrier.
176
result = ((_LONG) step ==
177
InterlockedCompareExchange((_LPLONG) &(b->iStep),
180
? PTHREAD_BARRIER_SERIAL_THREAD
189
pthread_barrierattr_init (pthread_barrierattr_t * attr)
191
* ------------------------------------------------------
193
* Initializes a barrier attributes object with default
198
* pointer to an instance of pthread_barrierattr_t
202
* Initializes a barrier attributes object with default
206
* 1) Used to define barrier types
209
* 0 successfully initialized attr,
210
* ENOMEM insufficient memory for attr.
212
* ------------------------------------------------------
215
pthread_barrierattr_t ba;
218
ba = (pthread_barrierattr_t) calloc (1, sizeof (*ba));
225
ba->pshared = PTHREAD_PROCESS_PRIVATE;
231
} /* pthread_barrierattr_init */
235
pthread_barrierattr_destroy (pthread_barrierattr_t * attr)
237
* ------------------------------------------------------
239
* Destroys a barrier attributes object. The object can
244
* pointer to an instance of pthread_barrierattr_t
248
* Destroys a barrier attributes object. The object can
252
* 1) Does not affect barrieres created using 'attr'
255
* 0 successfully released attr,
256
* EINVAL 'attr' is invalid.
258
* ------------------------------------------------------
263
if (attr == NULL || *attr == NULL)
269
pthread_barrierattr_t ba = *attr;
279
} /* pthread_barrierattr_destroy */
283
pthread_barrierattr_getpshared (const pthread_barrierattr_t * attr,
286
* ------------------------------------------------------
288
* Determine whether barriers created with 'attr' can be
289
* shared between processes.
293
* pointer to an instance of pthread_barrierattr_t
296
* will be set to one of:
298
* PTHREAD_PROCESS_SHARED
299
* May be shared if in shared memory
301
* PTHREAD_PROCESS_PRIVATE
306
* Mutexes creatd with 'attr' can be shared between
307
* processes if pthread_barrier_t variable is allocated
308
* in memory shared by these processes.
310
* 1) pshared barriers MUST be allocated in shared
312
* 2) The following macro is defined if shared barriers
314
* _POSIX_THREAD_PROCESS_SHARED
317
* 0 successfully retrieved attribute,
318
* EINVAL 'attr' is invalid,
320
* ------------------------------------------------------
325
if ((attr != NULL && *attr != NULL) &&
328
*pshared = (*attr)->pshared;
333
*pshared = PTHREAD_PROCESS_PRIVATE;
339
} /* pthread_barrierattr_getpshared */
343
pthread_barrierattr_setpshared (pthread_barrierattr_t * attr,
346
* ------------------------------------------------------
348
* Barriers created with 'attr' can be shared between
349
* processes if pthread_barrier_t variable is allocated
350
* in memory shared by these processes.
354
* pointer to an instance of pthread_barrierattr_t
359
* PTHREAD_PROCESS_SHARED
360
* May be shared if in shared memory
362
* PTHREAD_PROCESS_PRIVATE
366
* Mutexes creatd with 'attr' can be shared between
367
* processes if pthread_barrier_t variable is allocated
368
* in memory shared by these processes.
371
* 1) pshared barriers MUST be allocated in shared
374
* 2) The following macro is defined if shared barriers
376
* _POSIX_THREAD_PROCESS_SHARED
379
* 0 successfully set attribute,
380
* EINVAL 'attr' or pshared is invalid,
381
* ENOSYS PTHREAD_PROCESS_SHARED not supported,
383
* ------------------------------------------------------
388
if ((attr != NULL && *attr != NULL) &&
389
((pshared == PTHREAD_PROCESS_SHARED) ||
390
(pshared == PTHREAD_PROCESS_PRIVATE)))
392
if (pshared == PTHREAD_PROCESS_SHARED)
395
#if !defined( _POSIX_THREAD_PROCESS_SHARED )
398
pshared = PTHREAD_PROCESS_PRIVATE;
404
#endif /* _POSIX_THREAD_PROCESS_SHARED */
412
(*attr)->pshared = pshared;
421
} /* pthread_barrierattr_setpshared */