xref: /aosp_15_r20/external/deqp/framework/delibs/decpp/deSpinBarrier.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements C++ Base Library
3*35238bceSAndroid Build Coastguard Worker  * -----------------------------
4*35238bceSAndroid Build Coastguard Worker  *
5*35238bceSAndroid Build Coastguard Worker  * Copyright 2015 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker  *
11*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker  *
19*35238bceSAndroid Build Coastguard Worker  *//*!
20*35238bceSAndroid Build Coastguard Worker  * \file
21*35238bceSAndroid Build Coastguard Worker  * \brief Cross-thread barrier.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "deSpinBarrier.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "deThread.hpp"
26*35238bceSAndroid Build Coastguard Worker #include "deRandom.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "deInt32.h"
28*35238bceSAndroid Build Coastguard Worker 
29*35238bceSAndroid Build Coastguard Worker #include <vector>
30*35238bceSAndroid Build Coastguard Worker 
31*35238bceSAndroid Build Coastguard Worker namespace de
32*35238bceSAndroid Build Coastguard Worker {
33*35238bceSAndroid Build Coastguard Worker 
SpinBarrier(int32_t numThreads)34*35238bceSAndroid Build Coastguard Worker SpinBarrier::SpinBarrier(int32_t numThreads)
35*35238bceSAndroid Build Coastguard Worker     : m_numCores(deGetNumAvailableLogicalCores())
36*35238bceSAndroid Build Coastguard Worker     , m_numThreads(numThreads)
37*35238bceSAndroid Build Coastguard Worker     , m_numEntered(0)
38*35238bceSAndroid Build Coastguard Worker     , m_numLeaving(0)
39*35238bceSAndroid Build Coastguard Worker     , m_numRemoved(0)
40*35238bceSAndroid Build Coastguard Worker {
41*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(numThreads > 0);
42*35238bceSAndroid Build Coastguard Worker }
43*35238bceSAndroid Build Coastguard Worker 
~SpinBarrier(void)44*35238bceSAndroid Build Coastguard Worker SpinBarrier::~SpinBarrier(void)
45*35238bceSAndroid Build Coastguard Worker {
46*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(m_numEntered == 0 && m_numLeaving == 0);
47*35238bceSAndroid Build Coastguard Worker }
48*35238bceSAndroid Build Coastguard Worker 
reset(uint32_t numThreads)49*35238bceSAndroid Build Coastguard Worker void SpinBarrier::reset(uint32_t numThreads)
50*35238bceSAndroid Build Coastguard Worker {
51*35238bceSAndroid Build Coastguard Worker     // If last threads were removed, m_numEntered > 0 && m_numRemoved > 0
52*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(m_numLeaving == 0);
53*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(numThreads > 0);
54*35238bceSAndroid Build Coastguard Worker     m_numThreads = numThreads;
55*35238bceSAndroid Build Coastguard Worker     m_numEntered = 0;
56*35238bceSAndroid Build Coastguard Worker     m_numLeaving = 0;
57*35238bceSAndroid Build Coastguard Worker     m_numRemoved = 0;
58*35238bceSAndroid Build Coastguard Worker }
59*35238bceSAndroid Build Coastguard Worker 
getWaitMode(SpinBarrier::WaitMode requested,uint32_t numCores,int32_t numThreads)60*35238bceSAndroid Build Coastguard Worker inline SpinBarrier::WaitMode getWaitMode(SpinBarrier::WaitMode requested, uint32_t numCores, int32_t numThreads)
61*35238bceSAndroid Build Coastguard Worker {
62*35238bceSAndroid Build Coastguard Worker     if (requested == SpinBarrier::WAIT_MODE_AUTO)
63*35238bceSAndroid Build Coastguard Worker         return ((uint32_t)numThreads <= numCores) ? SpinBarrier::WAIT_MODE_BUSY : SpinBarrier::WAIT_MODE_YIELD;
64*35238bceSAndroid Build Coastguard Worker     else
65*35238bceSAndroid Build Coastguard Worker         return requested;
66*35238bceSAndroid Build Coastguard Worker }
67*35238bceSAndroid Build Coastguard Worker 
wait(SpinBarrier::WaitMode mode)68*35238bceSAndroid Build Coastguard Worker inline void wait(SpinBarrier::WaitMode mode)
69*35238bceSAndroid Build Coastguard Worker {
70*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(mode == SpinBarrier::WAIT_MODE_YIELD || mode == SpinBarrier::WAIT_MODE_BUSY);
71*35238bceSAndroid Build Coastguard Worker 
72*35238bceSAndroid Build Coastguard Worker     if (mode == SpinBarrier::WAIT_MODE_YIELD)
73*35238bceSAndroid Build Coastguard Worker         deYield();
74*35238bceSAndroid Build Coastguard Worker }
75*35238bceSAndroid Build Coastguard Worker 
sync(WaitMode requestedMode)76*35238bceSAndroid Build Coastguard Worker void SpinBarrier::sync(WaitMode requestedMode)
77*35238bceSAndroid Build Coastguard Worker {
78*35238bceSAndroid Build Coastguard Worker     const int32_t cachedNumThreads = m_numThreads;
79*35238bceSAndroid Build Coastguard Worker     const WaitMode waitMode        = getWaitMode(requestedMode, m_numCores, cachedNumThreads);
80*35238bceSAndroid Build Coastguard Worker 
81*35238bceSAndroid Build Coastguard Worker     deMemoryReadWriteFence();
82*35238bceSAndroid Build Coastguard Worker 
83*35238bceSAndroid Build Coastguard Worker     // m_numEntered must not be touched until all threads have had
84*35238bceSAndroid Build Coastguard Worker     // a chance to observe it being 0.
85*35238bceSAndroid Build Coastguard Worker     if (m_numLeaving > 0)
86*35238bceSAndroid Build Coastguard Worker     {
87*35238bceSAndroid Build Coastguard Worker         for (;;)
88*35238bceSAndroid Build Coastguard Worker         {
89*35238bceSAndroid Build Coastguard Worker             if (m_numLeaving == 0)
90*35238bceSAndroid Build Coastguard Worker                 break;
91*35238bceSAndroid Build Coastguard Worker 
92*35238bceSAndroid Build Coastguard Worker             wait(waitMode);
93*35238bceSAndroid Build Coastguard Worker         }
94*35238bceSAndroid Build Coastguard Worker     }
95*35238bceSAndroid Build Coastguard Worker 
96*35238bceSAndroid Build Coastguard Worker     // If m_numRemoved > 0, m_numThreads will decrease. If m_numThreads is decreased
97*35238bceSAndroid Build Coastguard Worker     // just after atomicOp and before comparison, the branch could be taken by multiple
98*35238bceSAndroid Build Coastguard Worker     // threads. Since m_numThreads only changes if all threads are inside the spinbarrier,
99*35238bceSAndroid Build Coastguard Worker     // cached value at snapshotted at the beginning of the function will be equal for
100*35238bceSAndroid Build Coastguard Worker     // all threads.
101*35238bceSAndroid Build Coastguard Worker     if (deAtomicIncrement32(&m_numEntered) == cachedNumThreads)
102*35238bceSAndroid Build Coastguard Worker     {
103*35238bceSAndroid Build Coastguard Worker         // Release all waiting threads. Since this thread has not been removed, m_numLeaving will
104*35238bceSAndroid Build Coastguard Worker         // be >= 1 until m_numLeaving is decremented at the end of this function.
105*35238bceSAndroid Build Coastguard Worker         m_numThreads = m_numThreads - m_numRemoved;
106*35238bceSAndroid Build Coastguard Worker         m_numLeaving = m_numThreads;
107*35238bceSAndroid Build Coastguard Worker         m_numRemoved = 0;
108*35238bceSAndroid Build Coastguard Worker 
109*35238bceSAndroid Build Coastguard Worker         deMemoryReadWriteFence();
110*35238bceSAndroid Build Coastguard Worker         m_numEntered = 0;
111*35238bceSAndroid Build Coastguard Worker     }
112*35238bceSAndroid Build Coastguard Worker     else
113*35238bceSAndroid Build Coastguard Worker     {
114*35238bceSAndroid Build Coastguard Worker         for (;;)
115*35238bceSAndroid Build Coastguard Worker         {
116*35238bceSAndroid Build Coastguard Worker             if (m_numEntered == 0)
117*35238bceSAndroid Build Coastguard Worker                 break;
118*35238bceSAndroid Build Coastguard Worker 
119*35238bceSAndroid Build Coastguard Worker             wait(waitMode);
120*35238bceSAndroid Build Coastguard Worker         }
121*35238bceSAndroid Build Coastguard Worker     }
122*35238bceSAndroid Build Coastguard Worker 
123*35238bceSAndroid Build Coastguard Worker     deAtomicDecrement32(&m_numLeaving);
124*35238bceSAndroid Build Coastguard Worker     deMemoryReadWriteFence();
125*35238bceSAndroid Build Coastguard Worker }
126*35238bceSAndroid Build Coastguard Worker 
removeThread(WaitMode requestedMode)127*35238bceSAndroid Build Coastguard Worker void SpinBarrier::removeThread(WaitMode requestedMode)
128*35238bceSAndroid Build Coastguard Worker {
129*35238bceSAndroid Build Coastguard Worker     const int32_t cachedNumThreads = m_numThreads;
130*35238bceSAndroid Build Coastguard Worker     const WaitMode waitMode        = getWaitMode(requestedMode, m_numCores, cachedNumThreads);
131*35238bceSAndroid Build Coastguard Worker 
132*35238bceSAndroid Build Coastguard Worker     // Wait for other threads exiting previous barrier
133*35238bceSAndroid Build Coastguard Worker     if (m_numLeaving > 0)
134*35238bceSAndroid Build Coastguard Worker     {
135*35238bceSAndroid Build Coastguard Worker         for (;;)
136*35238bceSAndroid Build Coastguard Worker         {
137*35238bceSAndroid Build Coastguard Worker             if (m_numLeaving == 0)
138*35238bceSAndroid Build Coastguard Worker                 break;
139*35238bceSAndroid Build Coastguard Worker 
140*35238bceSAndroid Build Coastguard Worker             wait(waitMode);
141*35238bceSAndroid Build Coastguard Worker         }
142*35238bceSAndroid Build Coastguard Worker     }
143*35238bceSAndroid Build Coastguard Worker 
144*35238bceSAndroid Build Coastguard Worker     // Ask for last thread entering barrier to adjust thread count
145*35238bceSAndroid Build Coastguard Worker     deAtomicIncrement32(&m_numRemoved);
146*35238bceSAndroid Build Coastguard Worker 
147*35238bceSAndroid Build Coastguard Worker     // See sync() - use cached value
148*35238bceSAndroid Build Coastguard Worker     if (deAtomicIncrement32(&m_numEntered) == cachedNumThreads)
149*35238bceSAndroid Build Coastguard Worker     {
150*35238bceSAndroid Build Coastguard Worker         // Release all waiting threads.
151*35238bceSAndroid Build Coastguard Worker         m_numThreads = m_numThreads - m_numRemoved;
152*35238bceSAndroid Build Coastguard Worker         m_numLeaving = m_numThreads;
153*35238bceSAndroid Build Coastguard Worker         m_numRemoved = 0;
154*35238bceSAndroid Build Coastguard Worker 
155*35238bceSAndroid Build Coastguard Worker         deMemoryReadWriteFence();
156*35238bceSAndroid Build Coastguard Worker         m_numEntered = 0;
157*35238bceSAndroid Build Coastguard Worker     }
158*35238bceSAndroid Build Coastguard Worker }
159*35238bceSAndroid Build Coastguard Worker 
160*35238bceSAndroid Build Coastguard Worker namespace
161*35238bceSAndroid Build Coastguard Worker {
162*35238bceSAndroid Build Coastguard Worker 
singleThreadTest(SpinBarrier::WaitMode mode)163*35238bceSAndroid Build Coastguard Worker void singleThreadTest(SpinBarrier::WaitMode mode)
164*35238bceSAndroid Build Coastguard Worker {
165*35238bceSAndroid Build Coastguard Worker     SpinBarrier barrier(1);
166*35238bceSAndroid Build Coastguard Worker 
167*35238bceSAndroid Build Coastguard Worker     barrier.sync(mode);
168*35238bceSAndroid Build Coastguard Worker     barrier.sync(mode);
169*35238bceSAndroid Build Coastguard Worker     barrier.sync(mode);
170*35238bceSAndroid Build Coastguard Worker }
171*35238bceSAndroid Build Coastguard Worker 
172*35238bceSAndroid Build Coastguard Worker class TestThread : public de::Thread
173*35238bceSAndroid Build Coastguard Worker {
174*35238bceSAndroid Build Coastguard Worker public:
TestThread(SpinBarrier & barrier,volatile int32_t * sharedVar,int numThreads,int threadNdx)175*35238bceSAndroid Build Coastguard Worker     TestThread(SpinBarrier &barrier, volatile int32_t *sharedVar, int numThreads, int threadNdx)
176*35238bceSAndroid Build Coastguard Worker         : m_barrier(barrier)
177*35238bceSAndroid Build Coastguard Worker         , m_sharedVar(sharedVar)
178*35238bceSAndroid Build Coastguard Worker         , m_numThreads(numThreads)
179*35238bceSAndroid Build Coastguard Worker         , m_threadNdx(threadNdx)
180*35238bceSAndroid Build Coastguard Worker         , m_busyOk((uint32_t)m_numThreads <= deGetNumAvailableLogicalCores())
181*35238bceSAndroid Build Coastguard Worker     {
182*35238bceSAndroid Build Coastguard Worker     }
183*35238bceSAndroid Build Coastguard Worker 
run(void)184*35238bceSAndroid Build Coastguard Worker     void run(void)
185*35238bceSAndroid Build Coastguard Worker     {
186*35238bceSAndroid Build Coastguard Worker         const int numIters = 10000;
187*35238bceSAndroid Build Coastguard Worker         de::Random rnd(deInt32Hash(m_numThreads) ^ deInt32Hash(m_threadNdx));
188*35238bceSAndroid Build Coastguard Worker 
189*35238bceSAndroid Build Coastguard Worker         for (int iterNdx = 0; iterNdx < numIters; iterNdx++)
190*35238bceSAndroid Build Coastguard Worker         {
191*35238bceSAndroid Build Coastguard Worker             // Phase 1: count up
192*35238bceSAndroid Build Coastguard Worker             deAtomicIncrement32(m_sharedVar);
193*35238bceSAndroid Build Coastguard Worker 
194*35238bceSAndroid Build Coastguard Worker             // Verify
195*35238bceSAndroid Build Coastguard Worker             m_barrier.sync(getWaitMode(rnd));
196*35238bceSAndroid Build Coastguard Worker 
197*35238bceSAndroid Build Coastguard Worker             DE_TEST_ASSERT(*m_sharedVar == m_numThreads);
198*35238bceSAndroid Build Coastguard Worker 
199*35238bceSAndroid Build Coastguard Worker             m_barrier.sync(getWaitMode(rnd));
200*35238bceSAndroid Build Coastguard Worker 
201*35238bceSAndroid Build Coastguard Worker             // Phase 2: count down
202*35238bceSAndroid Build Coastguard Worker             deAtomicDecrement32(m_sharedVar);
203*35238bceSAndroid Build Coastguard Worker 
204*35238bceSAndroid Build Coastguard Worker             // Verify
205*35238bceSAndroid Build Coastguard Worker             m_barrier.sync(getWaitMode(rnd));
206*35238bceSAndroid Build Coastguard Worker 
207*35238bceSAndroid Build Coastguard Worker             DE_TEST_ASSERT(*m_sharedVar == 0);
208*35238bceSAndroid Build Coastguard Worker 
209*35238bceSAndroid Build Coastguard Worker             m_barrier.sync(getWaitMode(rnd));
210*35238bceSAndroid Build Coastguard Worker         }
211*35238bceSAndroid Build Coastguard Worker     }
212*35238bceSAndroid Build Coastguard Worker 
213*35238bceSAndroid Build Coastguard Worker private:
214*35238bceSAndroid Build Coastguard Worker     SpinBarrier &m_barrier;
215*35238bceSAndroid Build Coastguard Worker     volatile int32_t *const m_sharedVar;
216*35238bceSAndroid Build Coastguard Worker     const int m_numThreads;
217*35238bceSAndroid Build Coastguard Worker     const int m_threadNdx;
218*35238bceSAndroid Build Coastguard Worker     const bool m_busyOk;
219*35238bceSAndroid Build Coastguard Worker 
getWaitMode(de::Random & rnd)220*35238bceSAndroid Build Coastguard Worker     SpinBarrier::WaitMode getWaitMode(de::Random &rnd)
221*35238bceSAndroid Build Coastguard Worker     {
222*35238bceSAndroid Build Coastguard Worker         static const SpinBarrier::WaitMode s_allModes[] = {
223*35238bceSAndroid Build Coastguard Worker             SpinBarrier::WAIT_MODE_YIELD,
224*35238bceSAndroid Build Coastguard Worker             SpinBarrier::WAIT_MODE_AUTO,
225*35238bceSAndroid Build Coastguard Worker             SpinBarrier::WAIT_MODE_BUSY,
226*35238bceSAndroid Build Coastguard Worker         };
227*35238bceSAndroid Build Coastguard Worker         const int numModes = DE_LENGTH_OF_ARRAY(s_allModes) - (m_busyOk ? 0 : 1);
228*35238bceSAndroid Build Coastguard Worker 
229*35238bceSAndroid Build Coastguard Worker         return rnd.choose<SpinBarrier::WaitMode>(DE_ARRAY_BEGIN(s_allModes), DE_ARRAY_BEGIN(s_allModes) + numModes);
230*35238bceSAndroid Build Coastguard Worker     }
231*35238bceSAndroid Build Coastguard Worker };
232*35238bceSAndroid Build Coastguard Worker 
multiThreadTest(int numThreads)233*35238bceSAndroid Build Coastguard Worker void multiThreadTest(int numThreads)
234*35238bceSAndroid Build Coastguard Worker {
235*35238bceSAndroid Build Coastguard Worker     SpinBarrier barrier(numThreads);
236*35238bceSAndroid Build Coastguard Worker     volatile int32_t sharedVar = 0;
237*35238bceSAndroid Build Coastguard Worker     std::vector<TestThread *> threads(numThreads, static_cast<TestThread *>(DE_NULL));
238*35238bceSAndroid Build Coastguard Worker 
239*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < numThreads; ndx++)
240*35238bceSAndroid Build Coastguard Worker     {
241*35238bceSAndroid Build Coastguard Worker         threads[ndx] = new TestThread(barrier, &sharedVar, numThreads, ndx);
242*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(threads[ndx]);
243*35238bceSAndroid Build Coastguard Worker         threads[ndx]->start();
244*35238bceSAndroid Build Coastguard Worker     }
245*35238bceSAndroid Build Coastguard Worker 
246*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < numThreads; ndx++)
247*35238bceSAndroid Build Coastguard Worker     {
248*35238bceSAndroid Build Coastguard Worker         threads[ndx]->join();
249*35238bceSAndroid Build Coastguard Worker         delete threads[ndx];
250*35238bceSAndroid Build Coastguard Worker     }
251*35238bceSAndroid Build Coastguard Worker 
252*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(sharedVar == 0);
253*35238bceSAndroid Build Coastguard Worker }
254*35238bceSAndroid Build Coastguard Worker 
singleThreadRemoveTest(SpinBarrier::WaitMode mode)255*35238bceSAndroid Build Coastguard Worker void singleThreadRemoveTest(SpinBarrier::WaitMode mode)
256*35238bceSAndroid Build Coastguard Worker {
257*35238bceSAndroid Build Coastguard Worker     SpinBarrier barrier(3);
258*35238bceSAndroid Build Coastguard Worker 
259*35238bceSAndroid Build Coastguard Worker     barrier.removeThread(mode);
260*35238bceSAndroid Build Coastguard Worker     barrier.removeThread(mode);
261*35238bceSAndroid Build Coastguard Worker     barrier.sync(mode);
262*35238bceSAndroid Build Coastguard Worker     barrier.removeThread(mode);
263*35238bceSAndroid Build Coastguard Worker 
264*35238bceSAndroid Build Coastguard Worker     barrier.reset(1);
265*35238bceSAndroid Build Coastguard Worker     barrier.sync(mode);
266*35238bceSAndroid Build Coastguard Worker 
267*35238bceSAndroid Build Coastguard Worker     barrier.reset(2);
268*35238bceSAndroid Build Coastguard Worker     barrier.removeThread(mode);
269*35238bceSAndroid Build Coastguard Worker     barrier.sync(mode);
270*35238bceSAndroid Build Coastguard Worker }
271*35238bceSAndroid Build Coastguard Worker 
272*35238bceSAndroid Build Coastguard Worker class TestExitThread : public de::Thread
273*35238bceSAndroid Build Coastguard Worker {
274*35238bceSAndroid Build Coastguard Worker public:
TestExitThread(SpinBarrier & barrier,int numThreads,int threadNdx,SpinBarrier::WaitMode waitMode)275*35238bceSAndroid Build Coastguard Worker     TestExitThread(SpinBarrier &barrier, int numThreads, int threadNdx, SpinBarrier::WaitMode waitMode)
276*35238bceSAndroid Build Coastguard Worker         : m_barrier(barrier)
277*35238bceSAndroid Build Coastguard Worker         , m_numThreads(numThreads)
278*35238bceSAndroid Build Coastguard Worker         , m_threadNdx(threadNdx)
279*35238bceSAndroid Build Coastguard Worker         , m_waitMode(waitMode)
280*35238bceSAndroid Build Coastguard Worker     {
281*35238bceSAndroid Build Coastguard Worker     }
282*35238bceSAndroid Build Coastguard Worker 
run(void)283*35238bceSAndroid Build Coastguard Worker     void run(void)
284*35238bceSAndroid Build Coastguard Worker     {
285*35238bceSAndroid Build Coastguard Worker         const int numIters = 10000;
286*35238bceSAndroid Build Coastguard Worker         de::Random rnd(deInt32Hash(m_numThreads) ^ deInt32Hash(m_threadNdx) ^ deInt32Hash((int32_t)m_waitMode));
287*35238bceSAndroid Build Coastguard Worker         const int invExitProb = 1000;
288*35238bceSAndroid Build Coastguard Worker 
289*35238bceSAndroid Build Coastguard Worker         for (int iterNdx = 0; iterNdx < numIters; iterNdx++)
290*35238bceSAndroid Build Coastguard Worker         {
291*35238bceSAndroid Build Coastguard Worker             if (rnd.getInt(0, invExitProb) == 0)
292*35238bceSAndroid Build Coastguard Worker             {
293*35238bceSAndroid Build Coastguard Worker                 m_barrier.removeThread(m_waitMode);
294*35238bceSAndroid Build Coastguard Worker                 break;
295*35238bceSAndroid Build Coastguard Worker             }
296*35238bceSAndroid Build Coastguard Worker             else
297*35238bceSAndroid Build Coastguard Worker                 m_barrier.sync(m_waitMode);
298*35238bceSAndroid Build Coastguard Worker         }
299*35238bceSAndroid Build Coastguard Worker     }
300*35238bceSAndroid Build Coastguard Worker 
301*35238bceSAndroid Build Coastguard Worker private:
302*35238bceSAndroid Build Coastguard Worker     SpinBarrier &m_barrier;
303*35238bceSAndroid Build Coastguard Worker     const int m_numThreads;
304*35238bceSAndroid Build Coastguard Worker     const int m_threadNdx;
305*35238bceSAndroid Build Coastguard Worker     const SpinBarrier::WaitMode m_waitMode;
306*35238bceSAndroid Build Coastguard Worker };
307*35238bceSAndroid Build Coastguard Worker 
multiThreadRemoveTest(int numThreads,SpinBarrier::WaitMode waitMode)308*35238bceSAndroid Build Coastguard Worker void multiThreadRemoveTest(int numThreads, SpinBarrier::WaitMode waitMode)
309*35238bceSAndroid Build Coastguard Worker {
310*35238bceSAndroid Build Coastguard Worker     SpinBarrier barrier(numThreads);
311*35238bceSAndroid Build Coastguard Worker     std::vector<TestExitThread *> threads(numThreads, static_cast<TestExitThread *>(DE_NULL));
312*35238bceSAndroid Build Coastguard Worker 
313*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < numThreads; ndx++)
314*35238bceSAndroid Build Coastguard Worker     {
315*35238bceSAndroid Build Coastguard Worker         threads[ndx] = new TestExitThread(barrier, numThreads, ndx, waitMode);
316*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(threads[ndx]);
317*35238bceSAndroid Build Coastguard Worker         threads[ndx]->start();
318*35238bceSAndroid Build Coastguard Worker     }
319*35238bceSAndroid Build Coastguard Worker 
320*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < numThreads; ndx++)
321*35238bceSAndroid Build Coastguard Worker     {
322*35238bceSAndroid Build Coastguard Worker         threads[ndx]->join();
323*35238bceSAndroid Build Coastguard Worker         delete threads[ndx];
324*35238bceSAndroid Build Coastguard Worker     }
325*35238bceSAndroid Build Coastguard Worker }
326*35238bceSAndroid Build Coastguard Worker 
327*35238bceSAndroid Build Coastguard Worker } // namespace
328*35238bceSAndroid Build Coastguard Worker 
SpinBarrier_selfTest(void)329*35238bceSAndroid Build Coastguard Worker void SpinBarrier_selfTest(void)
330*35238bceSAndroid Build Coastguard Worker {
331*35238bceSAndroid Build Coastguard Worker     singleThreadTest(SpinBarrier::WAIT_MODE_YIELD);
332*35238bceSAndroid Build Coastguard Worker     singleThreadTest(SpinBarrier::WAIT_MODE_BUSY);
333*35238bceSAndroid Build Coastguard Worker     singleThreadTest(SpinBarrier::WAIT_MODE_AUTO);
334*35238bceSAndroid Build Coastguard Worker     multiThreadTest(1);
335*35238bceSAndroid Build Coastguard Worker     multiThreadTest(2);
336*35238bceSAndroid Build Coastguard Worker     multiThreadTest(4);
337*35238bceSAndroid Build Coastguard Worker     multiThreadTest(8);
338*35238bceSAndroid Build Coastguard Worker     multiThreadTest(16);
339*35238bceSAndroid Build Coastguard Worker 
340*35238bceSAndroid Build Coastguard Worker     singleThreadRemoveTest(SpinBarrier::WAIT_MODE_YIELD);
341*35238bceSAndroid Build Coastguard Worker     singleThreadRemoveTest(SpinBarrier::WAIT_MODE_BUSY);
342*35238bceSAndroid Build Coastguard Worker     singleThreadRemoveTest(SpinBarrier::WAIT_MODE_AUTO);
343*35238bceSAndroid Build Coastguard Worker     multiThreadRemoveTest(1, SpinBarrier::WAIT_MODE_BUSY);
344*35238bceSAndroid Build Coastguard Worker     multiThreadRemoveTest(2, SpinBarrier::WAIT_MODE_AUTO);
345*35238bceSAndroid Build Coastguard Worker     multiThreadRemoveTest(4, SpinBarrier::WAIT_MODE_AUTO);
346*35238bceSAndroid Build Coastguard Worker     multiThreadRemoveTest(8, SpinBarrier::WAIT_MODE_AUTO);
347*35238bceSAndroid Build Coastguard Worker     multiThreadRemoveTest(16, SpinBarrier::WAIT_MODE_AUTO);
348*35238bceSAndroid Build Coastguard Worker     multiThreadRemoveTest(1, SpinBarrier::WAIT_MODE_YIELD);
349*35238bceSAndroid Build Coastguard Worker     multiThreadRemoveTest(2, SpinBarrier::WAIT_MODE_YIELD);
350*35238bceSAndroid Build Coastguard Worker     multiThreadRemoveTest(4, SpinBarrier::WAIT_MODE_YIELD);
351*35238bceSAndroid Build Coastguard Worker     multiThreadRemoveTest(8, SpinBarrier::WAIT_MODE_YIELD);
352*35238bceSAndroid Build Coastguard Worker     multiThreadRemoveTest(16, SpinBarrier::WAIT_MODE_YIELD);
353*35238bceSAndroid Build Coastguard Worker }
354*35238bceSAndroid Build Coastguard Worker 
355*35238bceSAndroid Build Coastguard Worker } // namespace de
356