171b3fa15SDavid Xu /*- 271b3fa15SDavid Xu * Copyright (c) 2003 David Xu <davidxu@freebsd.org> 371b3fa15SDavid Xu * All rights reserved. 471b3fa15SDavid Xu * 571b3fa15SDavid Xu * Redistribution and use in source and binary forms, with or without 671b3fa15SDavid Xu * modification, are permitted provided that the following conditions 771b3fa15SDavid Xu * are met: 871b3fa15SDavid Xu * 1. Redistributions of source code must retain the above copyright 971b3fa15SDavid Xu * notice, this list of conditions and the following disclaimer. 1071b3fa15SDavid Xu * 2. Redistributions in binary form must reproduce the above copyright 1171b3fa15SDavid Xu * notice, this list of conditions and the following disclaimer in the 1271b3fa15SDavid Xu * documentation and/or other materials provided with the distribution. 1371b3fa15SDavid Xu * 1471b3fa15SDavid Xu * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1571b3fa15SDavid Xu * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1671b3fa15SDavid Xu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1771b3fa15SDavid Xu * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1871b3fa15SDavid Xu * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1971b3fa15SDavid Xu * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2071b3fa15SDavid Xu * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2171b3fa15SDavid Xu * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2271b3fa15SDavid Xu * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2371b3fa15SDavid Xu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2471b3fa15SDavid Xu * SUCH DAMAGE. 2571b3fa15SDavid Xu * 2671b3fa15SDavid Xu * $FreeBSD: src/lib/libpthread/thread/thr_barrier.c,v 1.1 2003/09/04 14:06:43 davidxu Exp $ 2771b3fa15SDavid Xu */ 2871b3fa15SDavid Xu 29fc71f871SDavid Xu #include "namespace.h" 309e2ee207SJoerg Sonnenberger #include <machine/tls.h> 3171b3fa15SDavid Xu #include <errno.h> 3271b3fa15SDavid Xu #include <stdlib.h> 3371b3fa15SDavid Xu #include <pthread.h> 34fc71f871SDavid Xu #include "un-namespace.h" 3571b3fa15SDavid Xu 3671b3fa15SDavid Xu #include "thr_private.h" 3771b3fa15SDavid Xu 3871b3fa15SDavid Xu int 3971b3fa15SDavid Xu _pthread_barrier_destroy(pthread_barrier_t *barrier) 4071b3fa15SDavid Xu { 4171b3fa15SDavid Xu pthread_barrier_t bar; 4271b3fa15SDavid Xu 4371b3fa15SDavid Xu if (barrier == NULL || *barrier == NULL) 4471b3fa15SDavid Xu return (EINVAL); 4571b3fa15SDavid Xu 4671b3fa15SDavid Xu bar = *barrier; 4771b3fa15SDavid Xu if (bar->b_waiters > 0) 4871b3fa15SDavid Xu return (EBUSY); 4971b3fa15SDavid Xu *barrier = NULL; 50e7bf3f77SMatthew Dillon __free(bar); 5171b3fa15SDavid Xu return (0); 5271b3fa15SDavid Xu } 5371b3fa15SDavid Xu 5471b3fa15SDavid Xu int 55d33005aaSSascha Wildner _pthread_barrier_init(pthread_barrier_t * __restrict barrier, 56e7bf3f77SMatthew Dillon const pthread_barrierattr_t * __restrict attr __unused, 57e7bf3f77SMatthew Dillon unsigned count) 5871b3fa15SDavid Xu { 5971b3fa15SDavid Xu pthread_barrier_t bar; 6071b3fa15SDavid Xu 619f94c26dSSascha Wildner if (barrier == NULL || count == 0 || count > INT_MAX) 6271b3fa15SDavid Xu return (EINVAL); 6371b3fa15SDavid Xu 64e7bf3f77SMatthew Dillon bar = __malloc(sizeof(struct pthread_barrier)); 6571b3fa15SDavid Xu if (bar == NULL) 6671b3fa15SDavid Xu return (ENOMEM); 6771b3fa15SDavid Xu 6871b3fa15SDavid Xu _thr_umtx_init(&bar->b_lock); 6971b3fa15SDavid Xu bar->b_cycle = 0; 7071b3fa15SDavid Xu bar->b_waiters = 0; 7171b3fa15SDavid Xu bar->b_count = count; 7271b3fa15SDavid Xu *barrier = bar; 7371b3fa15SDavid Xu 7471b3fa15SDavid Xu return (0); 7571b3fa15SDavid Xu } 7671b3fa15SDavid Xu 7771b3fa15SDavid Xu int 7871b3fa15SDavid Xu _pthread_barrier_wait(pthread_barrier_t *barrier) 7971b3fa15SDavid Xu { 80*940be950Szrj pthread_t curthread; 8171b3fa15SDavid Xu pthread_barrier_t bar; 8219451dc5Szrj int64_t cycle; 8371b3fa15SDavid Xu int ret; 8471b3fa15SDavid Xu 8571b3fa15SDavid Xu if (barrier == NULL || *barrier == NULL) 8671b3fa15SDavid Xu return (EINVAL); 8771b3fa15SDavid Xu 8871b3fa15SDavid Xu bar = *barrier; 8919451dc5Szrj curthread = tls_get_curthread(); 9071b3fa15SDavid Xu THR_UMTX_LOCK(curthread, &bar->b_lock); 9171b3fa15SDavid Xu if (++bar->b_waiters == bar->b_count) { 9271b3fa15SDavid Xu /* Current thread is lastest thread */ 9371b3fa15SDavid Xu bar->b_waiters = 0; 9471b3fa15SDavid Xu bar->b_cycle++; 9598247283SMatthew Dillon _thr_umtx_wake(&bar->b_cycle, 0); 9671b3fa15SDavid Xu THR_UMTX_UNLOCK(curthread, &bar->b_lock); 9771b3fa15SDavid Xu ret = PTHREAD_BARRIER_SERIAL_THREAD; 9871b3fa15SDavid Xu } else { 9971b3fa15SDavid Xu cycle = bar->b_cycle; 10071b3fa15SDavid Xu THR_UMTX_UNLOCK(curthread, &bar->b_lock); 10171b3fa15SDavid Xu do { 1029219c44cSDavid Xu _thr_umtx_wait(&bar->b_cycle, cycle, NULL, 0); 10371b3fa15SDavid Xu /* test cycle to avoid bogus wakeup */ 10471b3fa15SDavid Xu } while (cycle == bar->b_cycle); 10571b3fa15SDavid Xu ret = 0; 10671b3fa15SDavid Xu } 10771b3fa15SDavid Xu return (ret); 10871b3fa15SDavid Xu } 1095a1048c8SDavid Xu 1105a1048c8SDavid Xu __strong_reference(_pthread_barrier_init, pthread_barrier_init); 1115a1048c8SDavid Xu __strong_reference(_pthread_barrier_wait, pthread_barrier_wait); 1125a1048c8SDavid Xu __strong_reference(_pthread_barrier_destroy, pthread_barrier_destroy); 113