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; 45e70bf9d5SDavid Xu struct pthread *curthread; 46*1bdbd705SKonstantin Belousov int pshared; 47a091d823SDavid Xu 48a091d823SDavid Xu if (barrier == NULL || *barrier == NULL) 49d4d7df5cSMike Makonnen return (EINVAL); 50a091d823SDavid Xu 51*1bdbd705SKonstantin Belousov if (*barrier == THR_PSHARED_PTR) { 52*1bdbd705SKonstantin Belousov bar = __thr_pshared_offpage(barrier, 0); 53*1bdbd705SKonstantin Belousov if (bar == NULL) { 54*1bdbd705SKonstantin Belousov *barrier = NULL; 55*1bdbd705SKonstantin Belousov return (0); 56*1bdbd705SKonstantin Belousov } 57*1bdbd705SKonstantin Belousov pshared = 1; 58*1bdbd705SKonstantin Belousov } else { 59a091d823SDavid Xu bar = *barrier; 60*1bdbd705SKonstantin Belousov pshared = 0; 61*1bdbd705SKonstantin Belousov } 62*1bdbd705SKonstantin Belousov curthread = _get_curthread(); 63e70bf9d5SDavid Xu THR_UMUTEX_LOCK(curthread, &bar->b_lock); 64e70bf9d5SDavid Xu if (bar->b_destroying) { 65e70bf9d5SDavid Xu THR_UMUTEX_UNLOCK(curthread, &bar->b_lock); 66d4d7df5cSMike Makonnen return (EBUSY); 67e70bf9d5SDavid Xu } 68e70bf9d5SDavid Xu bar->b_destroying = 1; 69e70bf9d5SDavid Xu do { 70e70bf9d5SDavid Xu if (bar->b_waiters > 0) { 71e70bf9d5SDavid Xu bar->b_destroying = 0; 72e70bf9d5SDavid Xu THR_UMUTEX_UNLOCK(curthread, &bar->b_lock); 73e70bf9d5SDavid Xu return (EBUSY); 74e70bf9d5SDavid Xu } 75e70bf9d5SDavid Xu if (bar->b_refcount != 0) { 76e70bf9d5SDavid Xu _thr_ucond_wait(&bar->b_cv, &bar->b_lock, NULL, 0); 77e70bf9d5SDavid Xu THR_UMUTEX_LOCK(curthread, &bar->b_lock); 78e70bf9d5SDavid Xu } else 79e70bf9d5SDavid Xu break; 80e70bf9d5SDavid Xu } while (1); 81e70bf9d5SDavid Xu bar->b_destroying = 0; 82e70bf9d5SDavid Xu THR_UMUTEX_UNLOCK(curthread, &bar->b_lock); 83e70bf9d5SDavid Xu 84d4d7df5cSMike Makonnen *barrier = NULL; 85*1bdbd705SKonstantin Belousov if (pshared) 86*1bdbd705SKonstantin Belousov __thr_pshared_destroy(barrier); 87*1bdbd705SKonstantin Belousov else 88a091d823SDavid Xu free(bar); 89d4d7df5cSMike Makonnen return (0); 90d4d7df5cSMike Makonnen } 91d4d7df5cSMike Makonnen 92d4d7df5cSMike Makonnen int 93d4d7df5cSMike Makonnen _pthread_barrier_init(pthread_barrier_t *barrier, 9437a6356bSDavid Xu const pthread_barrierattr_t *attr, unsigned count) 95d4d7df5cSMike Makonnen { 96a091d823SDavid Xu pthread_barrier_t bar; 97*1bdbd705SKonstantin Belousov int pshared; 9837a6356bSDavid Xu 99a091d823SDavid Xu if (barrier == NULL || count <= 0) 100d4d7df5cSMike Makonnen return (EINVAL); 101a091d823SDavid Xu 102*1bdbd705SKonstantin Belousov if (attr == NULL || *attr == NULL || 103*1bdbd705SKonstantin Belousov (*attr)->pshared == PTHREAD_PROCESS_PRIVATE) { 10483d74204SKonstantin Belousov bar = calloc(1, sizeof(struct pthread_barrier)); 105a091d823SDavid Xu if (bar == NULL) 106d4d7df5cSMike Makonnen return (ENOMEM); 107*1bdbd705SKonstantin Belousov *barrier = bar; 108*1bdbd705SKonstantin Belousov pshared = 0; 109*1bdbd705SKonstantin Belousov } else { 110*1bdbd705SKonstantin Belousov bar = __thr_pshared_offpage(barrier, 1); 111*1bdbd705SKonstantin Belousov if (bar == NULL) 112*1bdbd705SKonstantin Belousov return (EFAULT); 113*1bdbd705SKonstantin Belousov *barrier = THR_PSHARED_PTR; 114*1bdbd705SKonstantin Belousov pshared = 1; 115*1bdbd705SKonstantin Belousov } 116a091d823SDavid Xu 117bddd24cdSDavid Xu _thr_umutex_init(&bar->b_lock); 1184d617f2dSDavid Xu _thr_ucond_init(&bar->b_cv); 119*1bdbd705SKonstantin Belousov if (pshared) { 120*1bdbd705SKonstantin Belousov bar->b_lock.m_flags |= USYNC_PROCESS_SHARED; 121*1bdbd705SKonstantin Belousov bar->b_cv.c_flags |= USYNC_PROCESS_SHARED; 122*1bdbd705SKonstantin Belousov } 123a091d823SDavid Xu bar->b_count = count; 124d4d7df5cSMike Makonnen return (0); 125d4d7df5cSMike Makonnen } 126d4d7df5cSMike Makonnen 127d4d7df5cSMike Makonnen int 128d4d7df5cSMike Makonnen _pthread_barrier_wait(pthread_barrier_t *barrier) 129d4d7df5cSMike Makonnen { 130*1bdbd705SKonstantin Belousov struct pthread *curthread; 131a091d823SDavid Xu pthread_barrier_t bar; 1324d617f2dSDavid Xu int64_t cycle; 133a091d823SDavid Xu int ret; 134d4d7df5cSMike Makonnen 135a091d823SDavid Xu if (barrier == NULL || *barrier == NULL) 136d4d7df5cSMike Makonnen return (EINVAL); 137d4d7df5cSMike Makonnen 138*1bdbd705SKonstantin Belousov if (*barrier == THR_PSHARED_PTR) { 139*1bdbd705SKonstantin Belousov bar = __thr_pshared_offpage(barrier, 0); 140*1bdbd705SKonstantin Belousov if (bar == NULL) 141*1bdbd705SKonstantin Belousov return (EINVAL); 142*1bdbd705SKonstantin Belousov } else { 143a091d823SDavid Xu bar = *barrier; 144*1bdbd705SKonstantin Belousov } 145*1bdbd705SKonstantin Belousov curthread = _get_curthread(); 146bddd24cdSDavid Xu THR_UMUTEX_LOCK(curthread, &bar->b_lock); 147a091d823SDavid Xu if (++bar->b_waiters == bar->b_count) { 148a091d823SDavid Xu /* Current thread is lastest thread */ 149a091d823SDavid Xu bar->b_waiters = 0; 150a091d823SDavid Xu bar->b_cycle++; 1514d617f2dSDavid Xu _thr_ucond_broadcast(&bar->b_cv); 152bddd24cdSDavid Xu THR_UMUTEX_UNLOCK(curthread, &bar->b_lock); 153a091d823SDavid Xu ret = PTHREAD_BARRIER_SERIAL_THREAD; 154a091d823SDavid Xu } else { 155a091d823SDavid Xu cycle = bar->b_cycle; 156e70bf9d5SDavid Xu bar->b_refcount++; 157d4d7df5cSMike Makonnen do { 1584d617f2dSDavid Xu _thr_ucond_wait(&bar->b_cv, &bar->b_lock, NULL, 0); 159a8a343d2SDavid Xu THR_UMUTEX_LOCK(curthread, &bar->b_lock); 160a091d823SDavid Xu /* test cycle to avoid bogus wakeup */ 161a091d823SDavid Xu } while (cycle == bar->b_cycle); 162e70bf9d5SDavid Xu if (--bar->b_refcount == 0 && bar->b_destroying) 163e70bf9d5SDavid Xu _thr_ucond_broadcast(&bar->b_cv); 1644d617f2dSDavid Xu THR_UMUTEX_UNLOCK(curthread, &bar->b_lock); 165a091d823SDavid Xu ret = 0; 166d4d7df5cSMike Makonnen } 167a091d823SDavid Xu return (ret); 168d4d7df5cSMike Makonnen } 169