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; 45*e70bf9d5SDavid Xu struct pthread *curthread; 46a091d823SDavid Xu 47a091d823SDavid Xu if (barrier == NULL || *barrier == NULL) 48d4d7df5cSMike Makonnen return (EINVAL); 49a091d823SDavid Xu 50*e70bf9d5SDavid Xu curthread = _get_curthread(); 51a091d823SDavid Xu bar = *barrier; 52*e70bf9d5SDavid Xu THR_UMUTEX_LOCK(curthread, &bar->b_lock); 53*e70bf9d5SDavid Xu if (bar->b_destroying) { 54*e70bf9d5SDavid Xu THR_UMUTEX_UNLOCK(curthread, &bar->b_lock); 55d4d7df5cSMike Makonnen return (EBUSY); 56*e70bf9d5SDavid Xu } 57*e70bf9d5SDavid Xu bar->b_destroying = 1; 58*e70bf9d5SDavid Xu do { 59*e70bf9d5SDavid Xu if (bar->b_waiters > 0) { 60*e70bf9d5SDavid Xu bar->b_destroying = 0; 61*e70bf9d5SDavid Xu THR_UMUTEX_UNLOCK(curthread, &bar->b_lock); 62*e70bf9d5SDavid Xu return (EBUSY); 63*e70bf9d5SDavid Xu } 64*e70bf9d5SDavid Xu if (bar->b_refcount != 0) { 65*e70bf9d5SDavid Xu _thr_ucond_wait(&bar->b_cv, &bar->b_lock, NULL, 0); 66*e70bf9d5SDavid Xu THR_UMUTEX_LOCK(curthread, &bar->b_lock); 67*e70bf9d5SDavid Xu } else 68*e70bf9d5SDavid Xu break; 69*e70bf9d5SDavid Xu } while (1); 70*e70bf9d5SDavid Xu bar->b_destroying = 0; 71*e70bf9d5SDavid Xu THR_UMUTEX_UNLOCK(curthread, &bar->b_lock); 72*e70bf9d5SDavid Xu 73d4d7df5cSMike Makonnen *barrier = NULL; 74a091d823SDavid Xu free(bar); 75d4d7df5cSMike Makonnen return (0); 76d4d7df5cSMike Makonnen } 77d4d7df5cSMike Makonnen 78d4d7df5cSMike Makonnen int 79d4d7df5cSMike Makonnen _pthread_barrier_init(pthread_barrier_t *barrier, 8037a6356bSDavid Xu const pthread_barrierattr_t *attr, unsigned count) 81d4d7df5cSMike Makonnen { 82a091d823SDavid Xu pthread_barrier_t bar; 83a091d823SDavid Xu 8437a6356bSDavid Xu (void)attr; 8537a6356bSDavid Xu 86a091d823SDavid Xu if (barrier == NULL || count <= 0) 87d4d7df5cSMike Makonnen return (EINVAL); 88a091d823SDavid Xu 89a091d823SDavid Xu bar = malloc(sizeof(struct pthread_barrier)); 90a091d823SDavid Xu if (bar == NULL) 91d4d7df5cSMike Makonnen return (ENOMEM); 92a091d823SDavid Xu 93bddd24cdSDavid Xu _thr_umutex_init(&bar->b_lock); 944d617f2dSDavid Xu _thr_ucond_init(&bar->b_cv); 95a091d823SDavid Xu bar->b_cycle = 0; 96a091d823SDavid Xu bar->b_waiters = 0; 97a091d823SDavid Xu bar->b_count = count; 98*e70bf9d5SDavid Xu bar->b_refcount = 0; 99a091d823SDavid Xu *barrier = bar; 100a091d823SDavid Xu 101d4d7df5cSMike Makonnen return (0); 102d4d7df5cSMike Makonnen } 103d4d7df5cSMike Makonnen 104d4d7df5cSMike Makonnen int 105d4d7df5cSMike Makonnen _pthread_barrier_wait(pthread_barrier_t *barrier) 106d4d7df5cSMike Makonnen { 107a091d823SDavid Xu struct pthread *curthread = _get_curthread(); 108a091d823SDavid Xu pthread_barrier_t bar; 1094d617f2dSDavid Xu int64_t cycle; 110a091d823SDavid Xu int ret; 111d4d7df5cSMike Makonnen 112a091d823SDavid Xu if (barrier == NULL || *barrier == NULL) 113d4d7df5cSMike Makonnen return (EINVAL); 114d4d7df5cSMike Makonnen 115a091d823SDavid Xu bar = *barrier; 116bddd24cdSDavid Xu THR_UMUTEX_LOCK(curthread, &bar->b_lock); 117a091d823SDavid Xu if (++bar->b_waiters == bar->b_count) { 118a091d823SDavid Xu /* Current thread is lastest thread */ 119a091d823SDavid Xu bar->b_waiters = 0; 120a091d823SDavid Xu bar->b_cycle++; 1214d617f2dSDavid Xu _thr_ucond_broadcast(&bar->b_cv); 122bddd24cdSDavid Xu THR_UMUTEX_UNLOCK(curthread, &bar->b_lock); 123a091d823SDavid Xu ret = PTHREAD_BARRIER_SERIAL_THREAD; 124a091d823SDavid Xu } else { 125a091d823SDavid Xu cycle = bar->b_cycle; 126*e70bf9d5SDavid Xu bar->b_refcount++; 127d4d7df5cSMike Makonnen do { 1284d617f2dSDavid Xu _thr_ucond_wait(&bar->b_cv, &bar->b_lock, NULL, 0); 129a8a343d2SDavid Xu THR_UMUTEX_LOCK(curthread, &bar->b_lock); 130a091d823SDavid Xu /* test cycle to avoid bogus wakeup */ 131a091d823SDavid Xu } while (cycle == bar->b_cycle); 132*e70bf9d5SDavid Xu if (--bar->b_refcount == 0 && bar->b_destroying) 133*e70bf9d5SDavid Xu _thr_ucond_broadcast(&bar->b_cv); 1344d617f2dSDavid Xu THR_UMUTEX_UNLOCK(curthread, &bar->b_lock); 135a091d823SDavid Xu ret = 0; 136d4d7df5cSMike Makonnen } 137a091d823SDavid Xu return (ret); 138d4d7df5cSMike Makonnen } 139