In legion build config, updated path to GNU tools and updated deprecated Sun CC flag...
[OpenSPARC-T2-SAM] / legion / src / generic / barrier.c
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* OpenSPARC T2 Processor File: barrier.c
5* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
6* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
7*
8* The above named program is free software; you can redistribute it and/or
9* modify it under the terms of the GNU General Public
10* License version 2 as published by the Free Software Foundation.
11*
12* The above named program is distributed in the hope that it will be
13* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15* General Public License for more details.
16*
17* You should have received a copy of the GNU General Public
18* License along with this work; if not, write to the Free Software
19* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20*
21* ========== Copyright Header End ============================================
22*/
23/*
24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27
28#pragma ident "@(#)barrier.c 1.2 06/09/12 SMI"
29
30#include <errno.h>
31#include <thread.h>
32
33#include "barrier.h"
34
35int
36barrier_init(barrier_t *bp, int count)
37{
38 int n;
39 int i;
40
41 if (count < 1)
42 return (EINVAL);
43
44 bp->maxcnt = count;
45 bp->sbp = &bp->sb[0];
46
47 for (i = 0; i < 2; ++i) {
48 struct _sb *sbp = &(bp->sb[i]);
49 sbp->runners = count;
50
51 if (n = mutex_init(&sbp->wait_lk, NULL, NULL))
52 return (n);
53
54 if (n = cond_init(&sbp->wait_cv, NULL, NULL))
55 return (n);
56 }
57
58 return (0);
59}
60
61void
62barrier_wait(barrier_t *bp)
63{
64 struct _sb *sbp = bp->sbp;
65
66 mutex_lock(&sbp->wait_lk);
67
68 if (sbp->runners == 1) {
69 /* last thread to reach barrier */
70
71 if (bp->maxcnt != 1) {
72 /* reset runner count and switch sub-barriers */
73 sbp->runners = bp->maxcnt;
74 bp->sbp = (bp->sbp == &bp->sb[0])
75 ? &bp->sb[1] : &bp->sb[0];
76
77 /* wake up the waiters */
78 cond_broadcast(&sbp->wait_cv);
79 }
80 } else {
81 sbp->runners--; /* one less runner */
82
83 while (sbp->runners != bp->maxcnt)
84 cond_wait(&sbp->wait_cv, &sbp->wait_lk);
85 }
86
87 mutex_unlock(&sbp->wait_lk);
88}
89
90int
91barrier_busy_init(barrier_busy_t *bbp, int count)
92{
93 int i;
94
95 if (count < 1)
96 return (EINVAL);
97
98 bbp->maxcnt = count;
99 bbp->sbbp = &bbp->sbb[0];
100
101 for (i = 0; i < 2; ++i) {
102 struct _sbb *sbbp = &(bbp->sbb[i]);
103 sbbp->runners = count;
104 sbbp->spin_cv = ~0;
105 }
106
107 return (0);
108}
109
110void
111barrier_busy_wait(barrier_busy_t *bbp)
112{
113 extern uint32_t sim_atomic_add_32_nv(uint32_t *target, int32_t delta);
114 struct _sbb *sbbp = bbp->sbbp;
115
116 if (bbp->maxcnt == 1)
117 return;
118
119 if (sim_atomic_add_32_nv((uint32_t *)&sbbp->runners, -1) == 0) {
120 /* last thread to reach barrier */
121
122 /* switch sub-barriers, reset runner count and "cv" */
123 bbp->sbbp = (bbp->sbbp == &bbp->sbb[0])
124 ? &bbp->sbb[1] : &bbp->sbb[0];
125 bbp->sbbp->runners = bbp->maxcnt;
126 bbp->sbbp->spin_cv = ~0;
127
128 /* release the busy-waiters */
129 sbbp->spin_cv = 0;
130 } else {
131 while (sbbp->spin_cv)
132 ;
133 }
134}