17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5a574db85Sraf * Common Development and Distribution License (the "License").
6a574db85Sraf * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
21a574db85Sraf
227c478bd9Sstevel@tonic-gate /*
23a574db85Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate #include "lint.h"
287c478bd9Sstevel@tonic-gate #include "thr_uberdata.h"
297c478bd9Sstevel@tonic-gate #include <pthread.h>
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate /*
327c478bd9Sstevel@tonic-gate * Implementation-private attribute structure (for extensibility).
337c478bd9Sstevel@tonic-gate */
347c478bd9Sstevel@tonic-gate typedef struct {
357c478bd9Sstevel@tonic-gate int pshared;
367c478bd9Sstevel@tonic-gate } barrierattr_t;
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate int
pthread_barrierattr_init(pthread_barrierattr_t * attr)397257d1b4Sraf pthread_barrierattr_init(pthread_barrierattr_t *attr)
407c478bd9Sstevel@tonic-gate {
417c478bd9Sstevel@tonic-gate barrierattr_t *ap;
427c478bd9Sstevel@tonic-gate
437c478bd9Sstevel@tonic-gate if ((ap = lmalloc(sizeof (barrierattr_t))) == NULL)
447c478bd9Sstevel@tonic-gate return (ENOMEM);
457c478bd9Sstevel@tonic-gate ap->pshared = PTHREAD_PROCESS_PRIVATE;
467c478bd9Sstevel@tonic-gate attr->__pthread_barrierattrp = ap;
477c478bd9Sstevel@tonic-gate return (0);
487c478bd9Sstevel@tonic-gate }
497c478bd9Sstevel@tonic-gate
507c478bd9Sstevel@tonic-gate int
pthread_barrierattr_destroy(pthread_barrierattr_t * attr)517257d1b4Sraf pthread_barrierattr_destroy(pthread_barrierattr_t *attr)
527c478bd9Sstevel@tonic-gate {
537c478bd9Sstevel@tonic-gate if (attr == NULL || attr->__pthread_barrierattrp == NULL)
547c478bd9Sstevel@tonic-gate return (EINVAL);
557c478bd9Sstevel@tonic-gate lfree(attr->__pthread_barrierattrp, sizeof (barrierattr_t));
567c478bd9Sstevel@tonic-gate attr->__pthread_barrierattrp = NULL;
577c478bd9Sstevel@tonic-gate return (0);
587c478bd9Sstevel@tonic-gate }
597c478bd9Sstevel@tonic-gate
607c478bd9Sstevel@tonic-gate int
pthread_barrierattr_setpshared(pthread_barrierattr_t * attr,int pshared)617257d1b4Sraf pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared)
627c478bd9Sstevel@tonic-gate {
637c478bd9Sstevel@tonic-gate barrierattr_t *ap;
647c478bd9Sstevel@tonic-gate
657c478bd9Sstevel@tonic-gate if (attr == NULL || (ap = attr->__pthread_barrierattrp) == NULL ||
667c478bd9Sstevel@tonic-gate (pshared != PTHREAD_PROCESS_PRIVATE &&
677c478bd9Sstevel@tonic-gate pshared != PTHREAD_PROCESS_SHARED))
687c478bd9Sstevel@tonic-gate return (EINVAL);
697c478bd9Sstevel@tonic-gate ap->pshared = pshared;
707c478bd9Sstevel@tonic-gate return (0);
717c478bd9Sstevel@tonic-gate }
727c478bd9Sstevel@tonic-gate
737c478bd9Sstevel@tonic-gate int
pthread_barrierattr_getpshared(const pthread_barrierattr_t * attr,int * pshared)747257d1b4Sraf pthread_barrierattr_getpshared(const pthread_barrierattr_t *attr, int *pshared)
757c478bd9Sstevel@tonic-gate {
767c478bd9Sstevel@tonic-gate barrierattr_t *ap;
777c478bd9Sstevel@tonic-gate
787c478bd9Sstevel@tonic-gate if (attr == NULL || (ap = attr->__pthread_barrierattrp) == NULL ||
797c478bd9Sstevel@tonic-gate pshared == NULL)
807c478bd9Sstevel@tonic-gate return (EINVAL);
817c478bd9Sstevel@tonic-gate *pshared = ap->pshared;
827c478bd9Sstevel@tonic-gate return (0);
837c478bd9Sstevel@tonic-gate }
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate int
pthread_barrier_init(pthread_barrier_t * barrier,const pthread_barrierattr_t * attr,uint_t count)867257d1b4Sraf pthread_barrier_init(pthread_barrier_t *barrier,
877c478bd9Sstevel@tonic-gate const pthread_barrierattr_t *attr, uint_t count)
887c478bd9Sstevel@tonic-gate {
897c478bd9Sstevel@tonic-gate mutex_t *mp = (mutex_t *)&barrier->__pthread_barrier_lock;
907c478bd9Sstevel@tonic-gate cond_t *cvp = (cond_t *)&barrier->__pthread_barrier_cond;
917c478bd9Sstevel@tonic-gate barrierattr_t *ap;
927c478bd9Sstevel@tonic-gate int type;
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate if (attr == NULL)
95*a90d75b8SRichard PALO type = PTHREAD_PROCESS_PRIVATE;
967c478bd9Sstevel@tonic-gate else if ((ap = attr->__pthread_barrierattrp) != NULL)
977c478bd9Sstevel@tonic-gate type = ap->pshared;
987c478bd9Sstevel@tonic-gate else
997c478bd9Sstevel@tonic-gate type = -1;
1007c478bd9Sstevel@tonic-gate
1017c478bd9Sstevel@tonic-gate if (count == 0 ||
1027c478bd9Sstevel@tonic-gate (type != PTHREAD_PROCESS_PRIVATE && type != PTHREAD_PROCESS_SHARED))
1037c478bd9Sstevel@tonic-gate return (EINVAL);
1047c478bd9Sstevel@tonic-gate
1057c478bd9Sstevel@tonic-gate barrier->__pthread_barrier_count = count;
1067c478bd9Sstevel@tonic-gate barrier->__pthread_barrier_current = count;
1077c478bd9Sstevel@tonic-gate barrier->__pthread_barrier_cycle = 0;
1087c478bd9Sstevel@tonic-gate barrier->__pthread_barrier_reserved = 0;
1097257d1b4Sraf (void) mutex_init(mp, type, NULL);
1107257d1b4Sraf (void) cond_init(cvp, type, NULL);
1117c5714f6Sraf
1127c5714f6Sraf /*
1137c5714f6Sraf * This should be at the beginning of the function,
1147c5714f6Sraf * but for the sake of old broken applications that
1157c5714f6Sraf * do not have proper alignment for their barriers
1167c5714f6Sraf * (and don't check the return code from pthread_barrier_init),
1177c5714f6Sraf * we put it here, after initializing the barrier regardless.
1187c5714f6Sraf */
1197c5714f6Sraf if (((uintptr_t)barrier & (_LONG_LONG_ALIGNMENT - 1)) &&
1207c5714f6Sraf curthread->ul_misaligned == 0)
1217c5714f6Sraf return (EINVAL);
1227c5714f6Sraf
1237c478bd9Sstevel@tonic-gate return (0);
1247c478bd9Sstevel@tonic-gate }
1257c478bd9Sstevel@tonic-gate
1267c478bd9Sstevel@tonic-gate int
pthread_barrier_destroy(pthread_barrier_t * barrier)1277257d1b4Sraf pthread_barrier_destroy(pthread_barrier_t *barrier)
1287c478bd9Sstevel@tonic-gate {
1297c478bd9Sstevel@tonic-gate mutex_t *mp = (mutex_t *)&barrier->__pthread_barrier_lock;
1307c478bd9Sstevel@tonic-gate cond_t *cvp = (cond_t *)&barrier->__pthread_barrier_cond;
1317c478bd9Sstevel@tonic-gate
1327257d1b4Sraf (void) mutex_destroy(mp);
1337257d1b4Sraf (void) cond_destroy(cvp);
1348cd45542Sraf (void) memset(barrier, -1, sizeof (*barrier));
1357c478bd9Sstevel@tonic-gate return (0);
1367c478bd9Sstevel@tonic-gate }
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate /*
1397c478bd9Sstevel@tonic-gate * pthread_barrier_wait() is not a cancellation point;
1407c478bd9Sstevel@tonic-gate */
1417c478bd9Sstevel@tonic-gate int
pthread_barrier_wait(pthread_barrier_t * barrier)1427257d1b4Sraf pthread_barrier_wait(pthread_barrier_t *barrier)
1437c478bd9Sstevel@tonic-gate {
1447c478bd9Sstevel@tonic-gate mutex_t *mp = (mutex_t *)&barrier->__pthread_barrier_lock;
1457c478bd9Sstevel@tonic-gate cond_t *cvp = (cond_t *)&barrier->__pthread_barrier_cond;
1467c478bd9Sstevel@tonic-gate uint64_t cycle;
147a574db85Sraf int cancel_state;
1487c478bd9Sstevel@tonic-gate
1497257d1b4Sraf (void) mutex_lock(mp);
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate if (--barrier->__pthread_barrier_current == 0) {
1527c478bd9Sstevel@tonic-gate barrier->__pthread_barrier_cycle++;
1537c478bd9Sstevel@tonic-gate barrier->__pthread_barrier_current =
1547c478bd9Sstevel@tonic-gate barrier->__pthread_barrier_count;
1557257d1b4Sraf (void) mutex_unlock(mp);
1567257d1b4Sraf (void) cond_broadcast(cvp);
1577c478bd9Sstevel@tonic-gate return (PTHREAD_BARRIER_SERIAL_THREAD);
1587c478bd9Sstevel@tonic-gate }
1597c478bd9Sstevel@tonic-gate
1607257d1b4Sraf (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancel_state);
1617c478bd9Sstevel@tonic-gate cycle = barrier->__pthread_barrier_cycle;
1627c478bd9Sstevel@tonic-gate do {
1637257d1b4Sraf (void) cond_wait(cvp, mp);
1647c478bd9Sstevel@tonic-gate } while (cycle == barrier->__pthread_barrier_cycle);
1657257d1b4Sraf (void) pthread_setcancelstate(cancel_state, NULL);
1667c478bd9Sstevel@tonic-gate
1677257d1b4Sraf (void) mutex_unlock(mp);
1687c478bd9Sstevel@tonic-gate return (0);
1697c478bd9Sstevel@tonic-gate }
170