1d4d7df5cSMike Makonnen /*- 2a091d823SDavid Xu * Copyright (c) 2003 David Xu <davidxu@freebsd.org> 3d4d7df5cSMike Makonnen * All rights reserved. 4d4d7df5cSMike Makonnen * 5d4d7df5cSMike Makonnen * Redistribution and use in source and binary forms, with or without 6d4d7df5cSMike Makonnen * modification, are permitted provided that the following conditions 7d4d7df5cSMike Makonnen * are met: 8d4d7df5cSMike Makonnen * 1. Redistributions of source code must retain the above copyright 9d4d7df5cSMike Makonnen * notice, this list of conditions and the following disclaimer. 10d4d7df5cSMike Makonnen * 2. Redistributions in binary form must reproduce the above copyright 11d4d7df5cSMike Makonnen * notice, this list of conditions and the following disclaimer in the 12d4d7df5cSMike Makonnen * documentation and/or other materials provided with the distribution. 13d4d7df5cSMike Makonnen * 14d4d7df5cSMike Makonnen * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15d4d7df5cSMike Makonnen * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16d4d7df5cSMike Makonnen * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17d4d7df5cSMike Makonnen * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18d4d7df5cSMike Makonnen * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19d4d7df5cSMike Makonnen * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20d4d7df5cSMike Makonnen * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21d4d7df5cSMike Makonnen * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22d4d7df5cSMike Makonnen * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23d4d7df5cSMike Makonnen * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24d4d7df5cSMike Makonnen * SUCH DAMAGE. 25d4d7df5cSMike Makonnen * 26d4d7df5cSMike Makonnen * $FreeBSD$ 27d4d7df5cSMike Makonnen */ 28d4d7df5cSMike Makonnen 2937a6356bSDavid Xu #include "namespace.h" 30a091d823SDavid Xu #include <errno.h> 31d4d7df5cSMike Makonnen #include <stdlib.h> 32a091d823SDavid Xu #include <pthread.h> 3337a6356bSDavid Xu #include "un-namespace.h" 34d4d7df5cSMike Makonnen 35d4d7df5cSMike Makonnen #include "thr_private.h" 36d4d7df5cSMike Makonnen 37d4d7df5cSMike Makonnen __weak_reference(_pthread_barrier_init, pthread_barrier_init); 38d4d7df5cSMike Makonnen __weak_reference(_pthread_barrier_wait, pthread_barrier_wait); 39a091d823SDavid Xu __weak_reference(_pthread_barrier_destroy, pthread_barrier_destroy); 40d4d7df5cSMike Makonnen 41d4d7df5cSMike Makonnen int 42d4d7df5cSMike Makonnen _pthread_barrier_destroy(pthread_barrier_t *barrier) 43d4d7df5cSMike Makonnen { 44a091d823SDavid Xu pthread_barrier_t bar; 45a091d823SDavid Xu 46a091d823SDavid Xu if (barrier == NULL || *barrier == NULL) 47d4d7df5cSMike Makonnen return (EINVAL); 48a091d823SDavid Xu 49a091d823SDavid Xu bar = *barrier; 50a091d823SDavid Xu if (bar->b_waiters > 0) 51d4d7df5cSMike Makonnen return (EBUSY); 52d4d7df5cSMike Makonnen *barrier = NULL; 53a091d823SDavid Xu free(bar); 54d4d7df5cSMike Makonnen return (0); 55d4d7df5cSMike Makonnen } 56d4d7df5cSMike Makonnen 57d4d7df5cSMike Makonnen int 58d4d7df5cSMike Makonnen _pthread_barrier_init(pthread_barrier_t *barrier, 5937a6356bSDavid Xu const pthread_barrierattr_t *attr, unsigned count) 60d4d7df5cSMike Makonnen { 61a091d823SDavid Xu pthread_barrier_t bar; 62a091d823SDavid Xu 6337a6356bSDavid Xu (void)attr; 6437a6356bSDavid Xu 65a091d823SDavid Xu if (barrier == NULL || count <= 0) 66d4d7df5cSMike Makonnen return (EINVAL); 67a091d823SDavid Xu 68a091d823SDavid Xu bar = malloc(sizeof(struct pthread_barrier)); 69a091d823SDavid Xu if (bar == NULL) 70d4d7df5cSMike Makonnen return (ENOMEM); 71a091d823SDavid Xu 72bddd24cdSDavid Xu _thr_umutex_init(&bar->b_lock); 734d617f2dSDavid Xu _thr_ucond_init(&bar->b_cv); 74a091d823SDavid Xu bar->b_cycle = 0; 75a091d823SDavid Xu bar->b_waiters = 0; 76a091d823SDavid Xu bar->b_count = count; 77a091d823SDavid Xu *barrier = bar; 78a091d823SDavid Xu 79d4d7df5cSMike Makonnen return (0); 80d4d7df5cSMike Makonnen } 81d4d7df5cSMike Makonnen 82d4d7df5cSMike Makonnen int 83d4d7df5cSMike Makonnen _pthread_barrier_wait(pthread_barrier_t *barrier) 84d4d7df5cSMike Makonnen { 85a091d823SDavid Xu struct pthread *curthread = _get_curthread(); 86a091d823SDavid Xu pthread_barrier_t bar; 874d617f2dSDavid Xu int64_t cycle; 88a091d823SDavid Xu int ret; 89d4d7df5cSMike Makonnen 90a091d823SDavid Xu if (barrier == NULL || *barrier == NULL) 91d4d7df5cSMike Makonnen return (EINVAL); 92d4d7df5cSMike Makonnen 93a091d823SDavid Xu bar = *barrier; 94bddd24cdSDavid Xu THR_UMUTEX_LOCK(curthread, &bar->b_lock); 95a091d823SDavid Xu if (++bar->b_waiters == bar->b_count) { 96a091d823SDavid Xu /* Current thread is lastest thread */ 97a091d823SDavid Xu bar->b_waiters = 0; 98a091d823SDavid Xu bar->b_cycle++; 994d617f2dSDavid Xu _thr_ucond_broadcast(&bar->b_cv); 100bddd24cdSDavid Xu THR_UMUTEX_UNLOCK(curthread, &bar->b_lock); 101a091d823SDavid Xu ret = PTHREAD_BARRIER_SERIAL_THREAD; 102a091d823SDavid Xu } else { 103a091d823SDavid Xu cycle = bar->b_cycle; 104d4d7df5cSMike Makonnen do { 1054d617f2dSDavid Xu _thr_ucond_wait(&bar->b_cv, &bar->b_lock, NULL, 0); 106a091d823SDavid Xu /* test cycle to avoid bogus wakeup */ 107a091d823SDavid Xu } while (cycle == bar->b_cycle); 1084d617f2dSDavid Xu THR_UMUTEX_UNLOCK(curthread, &bar->b_lock); 109a091d823SDavid Xu ret = 0; 110d4d7df5cSMike Makonnen } 111a091d823SDavid Xu return (ret); 112d4d7df5cSMike Makonnen } 113