xref: /aosp_15_r20/external/deqp/framework/delibs/dethread/deThreadTest.c (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements Thread Library
3*35238bceSAndroid Build Coastguard Worker  * ---------------------------
4*35238bceSAndroid Build Coastguard Worker  *
5*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 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 Thread library tests.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "deThreadTest.h"
25*35238bceSAndroid Build Coastguard Worker #include "deThread.h"
26*35238bceSAndroid Build Coastguard Worker #include "deMutex.h"
27*35238bceSAndroid Build Coastguard Worker #include "deSemaphore.h"
28*35238bceSAndroid Build Coastguard Worker #include "deMemory.h"
29*35238bceSAndroid Build Coastguard Worker #include "deRandom.h"
30*35238bceSAndroid Build Coastguard Worker #include "deAtomic.h"
31*35238bceSAndroid Build Coastguard Worker #include "deThreadLocal.h"
32*35238bceSAndroid Build Coastguard Worker #include "deSingleton.h"
33*35238bceSAndroid Build Coastguard Worker #include "deMemPool.h"
34*35238bceSAndroid Build Coastguard Worker #include "dePoolArray.h"
35*35238bceSAndroid Build Coastguard Worker 
threadTestThr1(void * arg)36*35238bceSAndroid Build Coastguard Worker static void threadTestThr1(void *arg)
37*35238bceSAndroid Build Coastguard Worker {
38*35238bceSAndroid Build Coastguard Worker     int32_t val = *((int32_t *)arg);
39*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(val == 123);
40*35238bceSAndroid Build Coastguard Worker }
41*35238bceSAndroid Build Coastguard Worker 
threadTestThr2(void * arg)42*35238bceSAndroid Build Coastguard Worker static void threadTestThr2(void *arg)
43*35238bceSAndroid Build Coastguard Worker {
44*35238bceSAndroid Build Coastguard Worker     DE_UNREF(arg);
45*35238bceSAndroid Build Coastguard Worker     deSleep(100);
46*35238bceSAndroid Build Coastguard Worker }
47*35238bceSAndroid Build Coastguard Worker 
48*35238bceSAndroid Build Coastguard Worker typedef struct ThreadData3_s
49*35238bceSAndroid Build Coastguard Worker {
50*35238bceSAndroid Build Coastguard Worker     uint8_t bytes[16];
51*35238bceSAndroid Build Coastguard Worker } ThreadData3;
52*35238bceSAndroid Build Coastguard Worker 
threadTestThr3(void * arg)53*35238bceSAndroid Build Coastguard Worker static void threadTestThr3(void *arg)
54*35238bceSAndroid Build Coastguard Worker {
55*35238bceSAndroid Build Coastguard Worker     ThreadData3 *data = (ThreadData3 *)arg;
56*35238bceSAndroid Build Coastguard Worker     int ndx;
57*35238bceSAndroid Build Coastguard Worker 
58*35238bceSAndroid Build Coastguard Worker     for (ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(data->bytes); ndx++)
59*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(data->bytes[ndx] == 0);
60*35238bceSAndroid Build Coastguard Worker 
61*35238bceSAndroid Build Coastguard Worker     for (ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(data->bytes); ndx++)
62*35238bceSAndroid Build Coastguard Worker         data->bytes[ndx] = 0xff;
63*35238bceSAndroid Build Coastguard Worker }
64*35238bceSAndroid Build Coastguard Worker 
threadTestThr4(void * arg)65*35238bceSAndroid Build Coastguard Worker static void threadTestThr4(void *arg)
66*35238bceSAndroid Build Coastguard Worker {
67*35238bceSAndroid Build Coastguard Worker     deThreadLocal tls = *(deThreadLocal *)arg;
68*35238bceSAndroid Build Coastguard Worker     deThreadLocal_set(tls, DE_NULL);
69*35238bceSAndroid Build Coastguard Worker }
70*35238bceSAndroid Build Coastguard Worker 
71*35238bceSAndroid Build Coastguard Worker #if defined(DE_THREAD_LOCAL)
72*35238bceSAndroid Build Coastguard Worker 
73*35238bceSAndroid Build Coastguard Worker static DE_THREAD_LOCAL int tls_testVar = 123;
74*35238bceSAndroid Build Coastguard Worker 
tlsTestThr(void * arg)75*35238bceSAndroid Build Coastguard Worker static void tlsTestThr(void *arg)
76*35238bceSAndroid Build Coastguard Worker {
77*35238bceSAndroid Build Coastguard Worker     DE_UNREF(arg);
78*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(tls_testVar == 123);
79*35238bceSAndroid Build Coastguard Worker     tls_testVar = 104;
80*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(tls_testVar == 104);
81*35238bceSAndroid Build Coastguard Worker }
82*35238bceSAndroid Build Coastguard Worker 
83*35238bceSAndroid Build Coastguard Worker #endif
84*35238bceSAndroid Build Coastguard Worker 
deThread_selfTest(void)85*35238bceSAndroid Build Coastguard Worker void deThread_selfTest(void)
86*35238bceSAndroid Build Coastguard Worker {
87*35238bceSAndroid Build Coastguard Worker     /* Test sleep & yield. */
88*35238bceSAndroid Build Coastguard Worker     deSleep(0);
89*35238bceSAndroid Build Coastguard Worker     deSleep(100);
90*35238bceSAndroid Build Coastguard Worker     deYield();
91*35238bceSAndroid Build Coastguard Worker 
92*35238bceSAndroid Build Coastguard Worker     /* Thread test 1. */
93*35238bceSAndroid Build Coastguard Worker     {
94*35238bceSAndroid Build Coastguard Worker         int32_t val = 123;
95*35238bceSAndroid Build Coastguard Worker         bool ret;
96*35238bceSAndroid Build Coastguard Worker         deThread thread = deThread_create(threadTestThr1, &val, DE_NULL);
97*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(thread);
98*35238bceSAndroid Build Coastguard Worker 
99*35238bceSAndroid Build Coastguard Worker         ret = deThread_join(thread);
100*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(ret);
101*35238bceSAndroid Build Coastguard Worker 
102*35238bceSAndroid Build Coastguard Worker         deThread_destroy(thread);
103*35238bceSAndroid Build Coastguard Worker     }
104*35238bceSAndroid Build Coastguard Worker 
105*35238bceSAndroid Build Coastguard Worker     /* Thread test 2. */
106*35238bceSAndroid Build Coastguard Worker     {
107*35238bceSAndroid Build Coastguard Worker         deThread thread = deThread_create(threadTestThr2, DE_NULL, DE_NULL);
108*35238bceSAndroid Build Coastguard Worker         int32_t ret;
109*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(thread);
110*35238bceSAndroid Build Coastguard Worker 
111*35238bceSAndroid Build Coastguard Worker         ret = deThread_join(thread);
112*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(ret);
113*35238bceSAndroid Build Coastguard Worker 
114*35238bceSAndroid Build Coastguard Worker         deThread_destroy(thread);
115*35238bceSAndroid Build Coastguard Worker     }
116*35238bceSAndroid Build Coastguard Worker 
117*35238bceSAndroid Build Coastguard Worker     /* Thread test 3. */
118*35238bceSAndroid Build Coastguard Worker     {
119*35238bceSAndroid Build Coastguard Worker         ThreadData3 data;
120*35238bceSAndroid Build Coastguard Worker         deThread thread;
121*35238bceSAndroid Build Coastguard Worker         bool ret;
122*35238bceSAndroid Build Coastguard Worker         int ndx;
123*35238bceSAndroid Build Coastguard Worker 
124*35238bceSAndroid Build Coastguard Worker         deMemset(&data, 0, sizeof(ThreadData3));
125*35238bceSAndroid Build Coastguard Worker 
126*35238bceSAndroid Build Coastguard Worker         thread = deThread_create(threadTestThr3, &data, DE_NULL);
127*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(thread);
128*35238bceSAndroid Build Coastguard Worker 
129*35238bceSAndroid Build Coastguard Worker         ret = deThread_join(thread);
130*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(ret);
131*35238bceSAndroid Build Coastguard Worker 
132*35238bceSAndroid Build Coastguard Worker         for (ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(data.bytes); ndx++)
133*35238bceSAndroid Build Coastguard Worker             DE_TEST_ASSERT(data.bytes[ndx] == 0xff);
134*35238bceSAndroid Build Coastguard Worker 
135*35238bceSAndroid Build Coastguard Worker         deThread_destroy(thread);
136*35238bceSAndroid Build Coastguard Worker     }
137*35238bceSAndroid Build Coastguard Worker 
138*35238bceSAndroid Build Coastguard Worker     /* Test tls. */
139*35238bceSAndroid Build Coastguard Worker     {
140*35238bceSAndroid Build Coastguard Worker         deThreadLocal tls;
141*35238bceSAndroid Build Coastguard Worker         deThread thread;
142*35238bceSAndroid Build Coastguard Worker 
143*35238bceSAndroid Build Coastguard Worker         tls = deThreadLocal_create();
144*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(tls);
145*35238bceSAndroid Build Coastguard Worker 
146*35238bceSAndroid Build Coastguard Worker         deThreadLocal_set(tls, (void *)(uintptr_t)0xff);
147*35238bceSAndroid Build Coastguard Worker 
148*35238bceSAndroid Build Coastguard Worker         thread = deThread_create(threadTestThr4, &tls, DE_NULL);
149*35238bceSAndroid Build Coastguard Worker         deThread_join(thread);
150*35238bceSAndroid Build Coastguard Worker         deThread_destroy(thread);
151*35238bceSAndroid Build Coastguard Worker 
152*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT((uintptr_t)deThreadLocal_get(tls) == 0xff);
153*35238bceSAndroid Build Coastguard Worker         deThreadLocal_destroy(tls);
154*35238bceSAndroid Build Coastguard Worker     }
155*35238bceSAndroid Build Coastguard Worker 
156*35238bceSAndroid Build Coastguard Worker #if defined(DE_THREAD_LOCAL)
157*35238bceSAndroid Build Coastguard Worker     {
158*35238bceSAndroid Build Coastguard Worker         deThread thread;
159*35238bceSAndroid Build Coastguard Worker 
160*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(tls_testVar == 123);
161*35238bceSAndroid Build Coastguard Worker         tls_testVar = 1;
162*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(tls_testVar == 1);
163*35238bceSAndroid Build Coastguard Worker 
164*35238bceSAndroid Build Coastguard Worker         thread = deThread_create(tlsTestThr, DE_NULL, DE_NULL);
165*35238bceSAndroid Build Coastguard Worker         deThread_join(thread);
166*35238bceSAndroid Build Coastguard Worker         deThread_destroy(thread);
167*35238bceSAndroid Build Coastguard Worker 
168*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(tls_testVar == 1);
169*35238bceSAndroid Build Coastguard Worker         tls_testVar = 123;
170*35238bceSAndroid Build Coastguard Worker     }
171*35238bceSAndroid Build Coastguard Worker #endif
172*35238bceSAndroid Build Coastguard Worker }
173*35238bceSAndroid Build Coastguard Worker 
mutexTestThr1(void * arg)174*35238bceSAndroid Build Coastguard Worker static void mutexTestThr1(void *arg)
175*35238bceSAndroid Build Coastguard Worker {
176*35238bceSAndroid Build Coastguard Worker     deMutex mutex = *((deMutex *)arg);
177*35238bceSAndroid Build Coastguard Worker 
178*35238bceSAndroid Build Coastguard Worker     deMutex_lock(mutex);
179*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(mutex);
180*35238bceSAndroid Build Coastguard Worker }
181*35238bceSAndroid Build Coastguard Worker 
182*35238bceSAndroid Build Coastguard Worker typedef struct MutexData2_s
183*35238bceSAndroid Build Coastguard Worker {
184*35238bceSAndroid Build Coastguard Worker     deMutex mutex;
185*35238bceSAndroid Build Coastguard Worker     int32_t counter;
186*35238bceSAndroid Build Coastguard Worker     int32_t counter2;
187*35238bceSAndroid Build Coastguard Worker     int32_t maxVal;
188*35238bceSAndroid Build Coastguard Worker } MutexData2;
189*35238bceSAndroid Build Coastguard Worker 
mutexTestThr2(void * arg)190*35238bceSAndroid Build Coastguard Worker static void mutexTestThr2(void *arg)
191*35238bceSAndroid Build Coastguard Worker {
192*35238bceSAndroid Build Coastguard Worker     MutexData2 *data       = (MutexData2 *)arg;
193*35238bceSAndroid Build Coastguard Worker     int32_t numIncremented = 0;
194*35238bceSAndroid Build Coastguard Worker 
195*35238bceSAndroid Build Coastguard Worker     for (;;)
196*35238bceSAndroid Build Coastguard Worker     {
197*35238bceSAndroid Build Coastguard Worker         int32_t localCounter;
198*35238bceSAndroid Build Coastguard Worker         deMutex_lock(data->mutex);
199*35238bceSAndroid Build Coastguard Worker 
200*35238bceSAndroid Build Coastguard Worker         if (data->counter >= data->maxVal)
201*35238bceSAndroid Build Coastguard Worker         {
202*35238bceSAndroid Build Coastguard Worker             deMutex_unlock(data->mutex);
203*35238bceSAndroid Build Coastguard Worker             break;
204*35238bceSAndroid Build Coastguard Worker         }
205*35238bceSAndroid Build Coastguard Worker 
206*35238bceSAndroid Build Coastguard Worker         localCounter = data->counter;
207*35238bceSAndroid Build Coastguard Worker         deYield();
208*35238bceSAndroid Build Coastguard Worker 
209*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(localCounter == data->counter);
210*35238bceSAndroid Build Coastguard Worker         localCounter += 1;
211*35238bceSAndroid Build Coastguard Worker         data->counter = localCounter;
212*35238bceSAndroid Build Coastguard Worker 
213*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(data->mutex);
214*35238bceSAndroid Build Coastguard Worker 
215*35238bceSAndroid Build Coastguard Worker         numIncremented++;
216*35238bceSAndroid Build Coastguard Worker     }
217*35238bceSAndroid Build Coastguard Worker 
218*35238bceSAndroid Build Coastguard Worker     deMutex_lock(data->mutex);
219*35238bceSAndroid Build Coastguard Worker     data->counter2 += numIncremented;
220*35238bceSAndroid Build Coastguard Worker     deMutex_unlock(data->mutex);
221*35238bceSAndroid Build Coastguard Worker }
222*35238bceSAndroid Build Coastguard Worker 
mutexTestThr3(void * arg)223*35238bceSAndroid Build Coastguard Worker void mutexTestThr3(void *arg)
224*35238bceSAndroid Build Coastguard Worker {
225*35238bceSAndroid Build Coastguard Worker     deMutex mutex = *((deMutex *)arg);
226*35238bceSAndroid Build Coastguard Worker     bool ret;
227*35238bceSAndroid Build Coastguard Worker 
228*35238bceSAndroid Build Coastguard Worker     ret = deMutex_tryLock(mutex);
229*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(!ret);
230*35238bceSAndroid Build Coastguard Worker }
231*35238bceSAndroid Build Coastguard Worker 
deMutex_selfTest(void)232*35238bceSAndroid Build Coastguard Worker void deMutex_selfTest(void)
233*35238bceSAndroid Build Coastguard Worker {
234*35238bceSAndroid Build Coastguard Worker     /* Default mutex from single thread. */
235*35238bceSAndroid Build Coastguard Worker     {
236*35238bceSAndroid Build Coastguard Worker         deMutex mutex = deMutex_create(DE_NULL);
237*35238bceSAndroid Build Coastguard Worker         bool ret;
238*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(mutex);
239*35238bceSAndroid Build Coastguard Worker 
240*35238bceSAndroid Build Coastguard Worker         deMutex_lock(mutex);
241*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(mutex);
242*35238bceSAndroid Build Coastguard Worker 
243*35238bceSAndroid Build Coastguard Worker         /* Should succeed. */
244*35238bceSAndroid Build Coastguard Worker         ret = deMutex_tryLock(mutex);
245*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(ret);
246*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(mutex);
247*35238bceSAndroid Build Coastguard Worker 
248*35238bceSAndroid Build Coastguard Worker         deMutex_destroy(mutex);
249*35238bceSAndroid Build Coastguard Worker     }
250*35238bceSAndroid Build Coastguard Worker 
251*35238bceSAndroid Build Coastguard Worker     /* Recursive mutex. */
252*35238bceSAndroid Build Coastguard Worker     {
253*35238bceSAndroid Build Coastguard Worker         deMutexAttributes attrs;
254*35238bceSAndroid Build Coastguard Worker         deMutex mutex;
255*35238bceSAndroid Build Coastguard Worker         int ndx;
256*35238bceSAndroid Build Coastguard Worker         int numLocks = 10;
257*35238bceSAndroid Build Coastguard Worker 
258*35238bceSAndroid Build Coastguard Worker         deMemset(&attrs, 0, sizeof(attrs));
259*35238bceSAndroid Build Coastguard Worker 
260*35238bceSAndroid Build Coastguard Worker         attrs.flags = DE_MUTEX_RECURSIVE;
261*35238bceSAndroid Build Coastguard Worker 
262*35238bceSAndroid Build Coastguard Worker         mutex = deMutex_create(&attrs);
263*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(mutex);
264*35238bceSAndroid Build Coastguard Worker 
265*35238bceSAndroid Build Coastguard Worker         for (ndx = 0; ndx < numLocks; ndx++)
266*35238bceSAndroid Build Coastguard Worker             deMutex_lock(mutex);
267*35238bceSAndroid Build Coastguard Worker 
268*35238bceSAndroid Build Coastguard Worker         for (ndx = 0; ndx < numLocks; ndx++)
269*35238bceSAndroid Build Coastguard Worker             deMutex_unlock(mutex);
270*35238bceSAndroid Build Coastguard Worker 
271*35238bceSAndroid Build Coastguard Worker         deMutex_destroy(mutex);
272*35238bceSAndroid Build Coastguard Worker     }
273*35238bceSAndroid Build Coastguard Worker 
274*35238bceSAndroid Build Coastguard Worker     /* Mutex and threads. */
275*35238bceSAndroid Build Coastguard Worker     {
276*35238bceSAndroid Build Coastguard Worker         deMutex mutex;
277*35238bceSAndroid Build Coastguard Worker         deThread thread;
278*35238bceSAndroid Build Coastguard Worker 
279*35238bceSAndroid Build Coastguard Worker         mutex = deMutex_create(DE_NULL);
280*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(mutex);
281*35238bceSAndroid Build Coastguard Worker 
282*35238bceSAndroid Build Coastguard Worker         deMutex_lock(mutex);
283*35238bceSAndroid Build Coastguard Worker 
284*35238bceSAndroid Build Coastguard Worker         thread = deThread_create(mutexTestThr1, &mutex, DE_NULL);
285*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(thread);
286*35238bceSAndroid Build Coastguard Worker 
287*35238bceSAndroid Build Coastguard Worker         deSleep(100);
288*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(mutex);
289*35238bceSAndroid Build Coastguard Worker 
290*35238bceSAndroid Build Coastguard Worker         deMutex_lock(mutex);
291*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(mutex);
292*35238bceSAndroid Build Coastguard Worker 
293*35238bceSAndroid Build Coastguard Worker         deThread_join(thread);
294*35238bceSAndroid Build Coastguard Worker 
295*35238bceSAndroid Build Coastguard Worker         deThread_destroy(thread);
296*35238bceSAndroid Build Coastguard Worker         deMutex_destroy(mutex);
297*35238bceSAndroid Build Coastguard Worker     }
298*35238bceSAndroid Build Coastguard Worker 
299*35238bceSAndroid Build Coastguard Worker     /* A bit more complex mutex test. */
300*35238bceSAndroid Build Coastguard Worker     {
301*35238bceSAndroid Build Coastguard Worker         MutexData2 data;
302*35238bceSAndroid Build Coastguard Worker         deThread threads[2];
303*35238bceSAndroid Build Coastguard Worker         int ndx;
304*35238bceSAndroid Build Coastguard Worker 
305*35238bceSAndroid Build Coastguard Worker         data.mutex = deMutex_create(DE_NULL);
306*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(data.mutex);
307*35238bceSAndroid Build Coastguard Worker 
308*35238bceSAndroid Build Coastguard Worker         data.counter  = 0;
309*35238bceSAndroid Build Coastguard Worker         data.counter2 = 0;
310*35238bceSAndroid Build Coastguard Worker         data.maxVal   = 1000;
311*35238bceSAndroid Build Coastguard Worker 
312*35238bceSAndroid Build Coastguard Worker         deMutex_lock(data.mutex);
313*35238bceSAndroid Build Coastguard Worker 
314*35238bceSAndroid Build Coastguard Worker         for (ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(threads); ndx++)
315*35238bceSAndroid Build Coastguard Worker         {
316*35238bceSAndroid Build Coastguard Worker             threads[ndx] = deThread_create(mutexTestThr2, &data, DE_NULL);
317*35238bceSAndroid Build Coastguard Worker             DE_TEST_ASSERT(threads[ndx]);
318*35238bceSAndroid Build Coastguard Worker         }
319*35238bceSAndroid Build Coastguard Worker 
320*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(data.mutex);
321*35238bceSAndroid Build Coastguard Worker 
322*35238bceSAndroid Build Coastguard Worker         for (ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(threads); ndx++)
323*35238bceSAndroid Build Coastguard Worker         {
324*35238bceSAndroid Build Coastguard Worker             bool ret = deThread_join(threads[ndx]);
325*35238bceSAndroid Build Coastguard Worker             DE_TEST_ASSERT(ret);
326*35238bceSAndroid Build Coastguard Worker             deThread_destroy(threads[ndx]);
327*35238bceSAndroid Build Coastguard Worker         }
328*35238bceSAndroid Build Coastguard Worker 
329*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(data.counter == data.counter2);
330*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(data.maxVal == data.counter);
331*35238bceSAndroid Build Coastguard Worker 
332*35238bceSAndroid Build Coastguard Worker         deMutex_destroy(data.mutex);
333*35238bceSAndroid Build Coastguard Worker     }
334*35238bceSAndroid Build Coastguard Worker 
335*35238bceSAndroid Build Coastguard Worker     /* tryLock() deadlock test. */
336*35238bceSAndroid Build Coastguard Worker     {
337*35238bceSAndroid Build Coastguard Worker         deThread thread;
338*35238bceSAndroid Build Coastguard Worker         deMutex mutex = deMutex_create(DE_NULL);
339*35238bceSAndroid Build Coastguard Worker         bool ret;
340*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(mutex);
341*35238bceSAndroid Build Coastguard Worker 
342*35238bceSAndroid Build Coastguard Worker         deMutex_lock(mutex);
343*35238bceSAndroid Build Coastguard Worker 
344*35238bceSAndroid Build Coastguard Worker         thread = deThread_create(mutexTestThr3, &mutex, DE_NULL);
345*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(mutex);
346*35238bceSAndroid Build Coastguard Worker 
347*35238bceSAndroid Build Coastguard Worker         ret = deThread_join(thread);
348*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(ret);
349*35238bceSAndroid Build Coastguard Worker 
350*35238bceSAndroid Build Coastguard Worker         deMutex_unlock(mutex);
351*35238bceSAndroid Build Coastguard Worker         deMutex_destroy(mutex);
352*35238bceSAndroid Build Coastguard Worker         deThread_destroy(thread);
353*35238bceSAndroid Build Coastguard Worker     }
354*35238bceSAndroid Build Coastguard Worker }
355*35238bceSAndroid Build Coastguard Worker 
356*35238bceSAndroid Build Coastguard Worker typedef struct TestBuffer_s
357*35238bceSAndroid Build Coastguard Worker {
358*35238bceSAndroid Build Coastguard Worker     uint32_t buffer[32];
359*35238bceSAndroid Build Coastguard Worker     deSemaphore empty;
360*35238bceSAndroid Build Coastguard Worker     deSemaphore fill;
361*35238bceSAndroid Build Coastguard Worker 
362*35238bceSAndroid Build Coastguard Worker     uint32_t producerHash;
363*35238bceSAndroid Build Coastguard Worker     uint32_t consumerHash;
364*35238bceSAndroid Build Coastguard Worker } TestBuffer;
365*35238bceSAndroid Build Coastguard Worker 
producerThread(void * arg)366*35238bceSAndroid Build Coastguard Worker void producerThread(void *arg)
367*35238bceSAndroid Build Coastguard Worker {
368*35238bceSAndroid Build Coastguard Worker     TestBuffer *buffer = (TestBuffer *)arg;
369*35238bceSAndroid Build Coastguard Worker     deRandom random;
370*35238bceSAndroid Build Coastguard Worker     int ndx;
371*35238bceSAndroid Build Coastguard Worker     int numToProduce = 10000;
372*35238bceSAndroid Build Coastguard Worker     int writePos     = 0;
373*35238bceSAndroid Build Coastguard Worker 
374*35238bceSAndroid Build Coastguard Worker     deRandom_init(&random, 123);
375*35238bceSAndroid Build Coastguard Worker 
376*35238bceSAndroid Build Coastguard Worker     for (ndx = 0; ndx <= numToProduce; ndx++)
377*35238bceSAndroid Build Coastguard Worker     {
378*35238bceSAndroid Build Coastguard Worker         uint32_t val;
379*35238bceSAndroid Build Coastguard Worker 
380*35238bceSAndroid Build Coastguard Worker         if (ndx == numToProduce)
381*35238bceSAndroid Build Coastguard Worker         {
382*35238bceSAndroid Build Coastguard Worker             val = 0u; /* End. */
383*35238bceSAndroid Build Coastguard Worker         }
384*35238bceSAndroid Build Coastguard Worker         else
385*35238bceSAndroid Build Coastguard Worker         {
386*35238bceSAndroid Build Coastguard Worker             val = deRandom_getUint32(&random);
387*35238bceSAndroid Build Coastguard Worker             val = val ? val : 1u;
388*35238bceSAndroid Build Coastguard Worker         }
389*35238bceSAndroid Build Coastguard Worker 
390*35238bceSAndroid Build Coastguard Worker         deSemaphore_decrement(buffer->empty);
391*35238bceSAndroid Build Coastguard Worker 
392*35238bceSAndroid Build Coastguard Worker         buffer->buffer[writePos] = val;
393*35238bceSAndroid Build Coastguard Worker         writePos                 = (writePos + 1) % DE_LENGTH_OF_ARRAY(buffer->buffer);
394*35238bceSAndroid Build Coastguard Worker 
395*35238bceSAndroid Build Coastguard Worker         deSemaphore_increment(buffer->fill);
396*35238bceSAndroid Build Coastguard Worker 
397*35238bceSAndroid Build Coastguard Worker         buffer->producerHash ^= val;
398*35238bceSAndroid Build Coastguard Worker     }
399*35238bceSAndroid Build Coastguard Worker }
400*35238bceSAndroid Build Coastguard Worker 
consumerThread(void * arg)401*35238bceSAndroid Build Coastguard Worker void consumerThread(void *arg)
402*35238bceSAndroid Build Coastguard Worker {
403*35238bceSAndroid Build Coastguard Worker     TestBuffer *buffer = (TestBuffer *)arg;
404*35238bceSAndroid Build Coastguard Worker     int readPos        = 0;
405*35238bceSAndroid Build Coastguard Worker 
406*35238bceSAndroid Build Coastguard Worker     for (;;)
407*35238bceSAndroid Build Coastguard Worker     {
408*35238bceSAndroid Build Coastguard Worker         int32_t val;
409*35238bceSAndroid Build Coastguard Worker 
410*35238bceSAndroid Build Coastguard Worker         deSemaphore_decrement(buffer->fill);
411*35238bceSAndroid Build Coastguard Worker 
412*35238bceSAndroid Build Coastguard Worker         val     = buffer->buffer[readPos];
413*35238bceSAndroid Build Coastguard Worker         readPos = (readPos + 1) % DE_LENGTH_OF_ARRAY(buffer->buffer);
414*35238bceSAndroid Build Coastguard Worker 
415*35238bceSAndroid Build Coastguard Worker         deSemaphore_increment(buffer->empty);
416*35238bceSAndroid Build Coastguard Worker 
417*35238bceSAndroid Build Coastguard Worker         buffer->consumerHash ^= val;
418*35238bceSAndroid Build Coastguard Worker 
419*35238bceSAndroid Build Coastguard Worker         if (val == 0)
420*35238bceSAndroid Build Coastguard Worker             break;
421*35238bceSAndroid Build Coastguard Worker     }
422*35238bceSAndroid Build Coastguard Worker }
423*35238bceSAndroid Build Coastguard Worker 
deSemaphore_selfTest(void)424*35238bceSAndroid Build Coastguard Worker void deSemaphore_selfTest(void)
425*35238bceSAndroid Build Coastguard Worker {
426*35238bceSAndroid Build Coastguard Worker     /* Basic test. */
427*35238bceSAndroid Build Coastguard Worker     {
428*35238bceSAndroid Build Coastguard Worker         deSemaphore semaphore = deSemaphore_create(1, DE_NULL);
429*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(semaphore);
430*35238bceSAndroid Build Coastguard Worker 
431*35238bceSAndroid Build Coastguard Worker         deSemaphore_increment(semaphore);
432*35238bceSAndroid Build Coastguard Worker         deSemaphore_decrement(semaphore);
433*35238bceSAndroid Build Coastguard Worker         deSemaphore_decrement(semaphore);
434*35238bceSAndroid Build Coastguard Worker 
435*35238bceSAndroid Build Coastguard Worker         deSemaphore_destroy(semaphore);
436*35238bceSAndroid Build Coastguard Worker     }
437*35238bceSAndroid Build Coastguard Worker 
438*35238bceSAndroid Build Coastguard Worker     /* Producer-consumer test. */
439*35238bceSAndroid Build Coastguard Worker     {
440*35238bceSAndroid Build Coastguard Worker         TestBuffer testBuffer;
441*35238bceSAndroid Build Coastguard Worker         deThread producer;
442*35238bceSAndroid Build Coastguard Worker         deThread consumer;
443*35238bceSAndroid Build Coastguard Worker         bool ret;
444*35238bceSAndroid Build Coastguard Worker 
445*35238bceSAndroid Build Coastguard Worker         deMemset(&testBuffer, 0, sizeof(testBuffer));
446*35238bceSAndroid Build Coastguard Worker 
447*35238bceSAndroid Build Coastguard Worker         testBuffer.empty = deSemaphore_create(DE_LENGTH_OF_ARRAY(testBuffer.buffer), DE_NULL);
448*35238bceSAndroid Build Coastguard Worker         testBuffer.fill  = deSemaphore_create(0, DE_NULL);
449*35238bceSAndroid Build Coastguard Worker 
450*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(testBuffer.empty && testBuffer.fill);
451*35238bceSAndroid Build Coastguard Worker 
452*35238bceSAndroid Build Coastguard Worker         consumer = deThread_create(consumerThread, &testBuffer, DE_NULL);
453*35238bceSAndroid Build Coastguard Worker         producer = deThread_create(producerThread, &testBuffer, DE_NULL);
454*35238bceSAndroid Build Coastguard Worker 
455*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(consumer && producer);
456*35238bceSAndroid Build Coastguard Worker 
457*35238bceSAndroid Build Coastguard Worker         ret = deThread_join(consumer) && deThread_join(producer);
458*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(ret);
459*35238bceSAndroid Build Coastguard Worker 
460*35238bceSAndroid Build Coastguard Worker         deThread_destroy(producer);
461*35238bceSAndroid Build Coastguard Worker         deThread_destroy(consumer);
462*35238bceSAndroid Build Coastguard Worker 
463*35238bceSAndroid Build Coastguard Worker         deSemaphore_destroy(testBuffer.empty);
464*35238bceSAndroid Build Coastguard Worker         deSemaphore_destroy(testBuffer.fill);
465*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(testBuffer.producerHash == testBuffer.consumerHash);
466*35238bceSAndroid Build Coastguard Worker     }
467*35238bceSAndroid Build Coastguard Worker }
468*35238bceSAndroid Build Coastguard Worker 
deAtomic_selfTest(void)469*35238bceSAndroid Build Coastguard Worker void deAtomic_selfTest(void)
470*35238bceSAndroid Build Coastguard Worker {
471*35238bceSAndroid Build Coastguard Worker     /* Single-threaded tests. */
472*35238bceSAndroid Build Coastguard Worker     {
473*35238bceSAndroid Build Coastguard Worker         volatile int32_t a = 11;
474*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicIncrementInt32(&a) == 12);
475*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(a == 12);
476*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicIncrementInt32(&a) == 13);
477*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(a == 13);
478*35238bceSAndroid Build Coastguard Worker 
479*35238bceSAndroid Build Coastguard Worker         a = -2;
480*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicIncrementInt32(&a) == -1);
481*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(a == -1);
482*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicIncrementInt32(&a) == 0);
483*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(a == 0);
484*35238bceSAndroid Build Coastguard Worker 
485*35238bceSAndroid Build Coastguard Worker         a = 11;
486*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicDecrementInt32(&a) == 10);
487*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(a == 10);
488*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicDecrementInt32(&a) == 9);
489*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(a == 9);
490*35238bceSAndroid Build Coastguard Worker 
491*35238bceSAndroid Build Coastguard Worker         a = 0;
492*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicDecrementInt32(&a) == -1);
493*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(a == -1);
494*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicDecrementInt32(&a) == -2);
495*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(a == -2);
496*35238bceSAndroid Build Coastguard Worker 
497*35238bceSAndroid Build Coastguard Worker         a = 0x7fffffff;
498*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicIncrementInt32(&a) == (int)0x80000000);
499*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(a == (int)0x80000000);
500*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicDecrementInt32(&a) == (int)0x7fffffff);
501*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(a == 0x7fffffff);
502*35238bceSAndroid Build Coastguard Worker     }
503*35238bceSAndroid Build Coastguard Worker 
504*35238bceSAndroid Build Coastguard Worker     {
505*35238bceSAndroid Build Coastguard Worker         volatile uint32_t a = 11;
506*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicIncrementUint32(&a) == 12);
507*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(a == 12);
508*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicIncrementUint32(&a) == 13);
509*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(a == 13);
510*35238bceSAndroid Build Coastguard Worker 
511*35238bceSAndroid Build Coastguard Worker         a = 0x7fffffff;
512*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicIncrementUint32(&a) == 0x80000000);
513*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(a == 0x80000000);
514*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicDecrementUint32(&a) == 0x7fffffff);
515*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(a == 0x7fffffff);
516*35238bceSAndroid Build Coastguard Worker 
517*35238bceSAndroid Build Coastguard Worker         a = 0xfffffffe;
518*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicIncrementUint32(&a) == 0xffffffff);
519*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(a == 0xffffffff);
520*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicDecrementUint32(&a) == 0xfffffffe);
521*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(a == 0xfffffffe);
522*35238bceSAndroid Build Coastguard Worker     }
523*35238bceSAndroid Build Coastguard Worker 
524*35238bceSAndroid Build Coastguard Worker     {
525*35238bceSAndroid Build Coastguard Worker         volatile uint32_t p;
526*35238bceSAndroid Build Coastguard Worker 
527*35238bceSAndroid Build Coastguard Worker         p = 0;
528*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicCompareExchange32(&p, 0, 1) == 0);
529*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(p == 1);
530*35238bceSAndroid Build Coastguard Worker 
531*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicCompareExchange32(&p, 0, 2) == 1);
532*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(p == 1);
533*35238bceSAndroid Build Coastguard Worker 
534*35238bceSAndroid Build Coastguard Worker         p = 7;
535*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicCompareExchange32(&p, 6, 8) == 7);
536*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(p == 7);
537*35238bceSAndroid Build Coastguard Worker 
538*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicCompareExchange32(&p, 7, 8) == 7);
539*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(p == 8);
540*35238bceSAndroid Build Coastguard Worker     }
541*35238bceSAndroid Build Coastguard Worker 
542*35238bceSAndroid Build Coastguard Worker #if (DE_PTR_SIZE == 8)
543*35238bceSAndroid Build Coastguard Worker     {
544*35238bceSAndroid Build Coastguard Worker         volatile int64_t a = 11;
545*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicIncrementInt64(&a) == 12);
546*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(a == 12);
547*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicIncrementInt64(&a) == 13);
548*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(a == 13);
549*35238bceSAndroid Build Coastguard Worker 
550*35238bceSAndroid Build Coastguard Worker         a = -2;
551*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicIncrementInt64(&a) == -1);
552*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(a == -1);
553*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicIncrementInt64(&a) == 0);
554*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(a == 0);
555*35238bceSAndroid Build Coastguard Worker 
556*35238bceSAndroid Build Coastguard Worker         a = 11;
557*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicDecrementInt64(&a) == 10);
558*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(a == 10);
559*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicDecrementInt64(&a) == 9);
560*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(a == 9);
561*35238bceSAndroid Build Coastguard Worker 
562*35238bceSAndroid Build Coastguard Worker         a = 0;
563*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicDecrementInt64(&a) == -1);
564*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(a == -1);
565*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicDecrementInt64(&a) == -2);
566*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(a == -2);
567*35238bceSAndroid Build Coastguard Worker 
568*35238bceSAndroid Build Coastguard Worker         a = (int64_t)((1ull << 63) - 1ull);
569*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicIncrementInt64(&a) == (int64_t)(1ull << 63));
570*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(a == (int64_t)(1ull << 63));
571*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deAtomicDecrementInt64(&a) == (int64_t)((1ull << 63) - 1));
572*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(a == (int64_t)((1ull << 63) - 1));
573*35238bceSAndroid Build Coastguard Worker     }
574*35238bceSAndroid Build Coastguard Worker #endif /* (DE_PTR_SIZE == 8) */
575*35238bceSAndroid Build Coastguard Worker 
576*35238bceSAndroid Build Coastguard Worker     /* \todo [2012-10-26 pyry] Implement multi-threaded tests. */
577*35238bceSAndroid Build Coastguard Worker }
578*35238bceSAndroid Build Coastguard Worker 
579*35238bceSAndroid Build Coastguard Worker /* Singleton self-test. */
580*35238bceSAndroid Build Coastguard Worker 
581*35238bceSAndroid Build Coastguard Worker DE_DECLARE_POOL_ARRAY(deThreadArray, deThread);
582*35238bceSAndroid Build Coastguard Worker 
583*35238bceSAndroid Build Coastguard Worker static volatile deSingletonState s_testSingleton = DE_SINGLETON_STATE_NOT_INITIALIZED;
584*35238bceSAndroid Build Coastguard Worker static volatile int s_testSingletonInitCount     = 0;
585*35238bceSAndroid Build Coastguard Worker static bool s_testSingletonInitialized           = false;
586*35238bceSAndroid Build Coastguard Worker static volatile bool s_singletonInitLock         = false;
587*35238bceSAndroid Build Coastguard Worker 
waitForSingletonInitLock(void)588*35238bceSAndroid Build Coastguard Worker static void waitForSingletonInitLock(void)
589*35238bceSAndroid Build Coastguard Worker {
590*35238bceSAndroid Build Coastguard Worker     for (;;)
591*35238bceSAndroid Build Coastguard Worker     {
592*35238bceSAndroid Build Coastguard Worker         deMemoryReadWriteFence();
593*35238bceSAndroid Build Coastguard Worker 
594*35238bceSAndroid Build Coastguard Worker         if (s_singletonInitLock)
595*35238bceSAndroid Build Coastguard Worker             break;
596*35238bceSAndroid Build Coastguard Worker     }
597*35238bceSAndroid Build Coastguard Worker }
598*35238bceSAndroid Build Coastguard Worker 
initTestSingleton(void * arg)599*35238bceSAndroid Build Coastguard Worker static void initTestSingleton(void *arg)
600*35238bceSAndroid Build Coastguard Worker {
601*35238bceSAndroid Build Coastguard Worker     int initTimeMs = *(const int *)arg;
602*35238bceSAndroid Build Coastguard Worker 
603*35238bceSAndroid Build Coastguard Worker     if (initTimeMs >= 0)
604*35238bceSAndroid Build Coastguard Worker         deSleep((uint32_t)initTimeMs);
605*35238bceSAndroid Build Coastguard Worker 
606*35238bceSAndroid Build Coastguard Worker     deAtomicIncrement32(&s_testSingletonInitCount);
607*35238bceSAndroid Build Coastguard Worker     s_testSingletonInitialized = true;
608*35238bceSAndroid Build Coastguard Worker }
609*35238bceSAndroid Build Coastguard Worker 
singletonTestThread(void * arg)610*35238bceSAndroid Build Coastguard Worker static void singletonTestThread(void *arg)
611*35238bceSAndroid Build Coastguard Worker {
612*35238bceSAndroid Build Coastguard Worker     waitForSingletonInitLock();
613*35238bceSAndroid Build Coastguard Worker 
614*35238bceSAndroid Build Coastguard Worker     deInitSingleton(&s_testSingleton, initTestSingleton, arg);
615*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(s_testSingletonInitialized);
616*35238bceSAndroid Build Coastguard Worker }
617*35238bceSAndroid Build Coastguard Worker 
resetTestState(void)618*35238bceSAndroid Build Coastguard Worker static void resetTestState(void)
619*35238bceSAndroid Build Coastguard Worker {
620*35238bceSAndroid Build Coastguard Worker     s_testSingleton            = DE_SINGLETON_STATE_NOT_INITIALIZED;
621*35238bceSAndroid Build Coastguard Worker     s_testSingletonInitCount   = 0;
622*35238bceSAndroid Build Coastguard Worker     s_testSingletonInitialized = false;
623*35238bceSAndroid Build Coastguard Worker     s_singletonInitLock        = false;
624*35238bceSAndroid Build Coastguard Worker }
625*35238bceSAndroid Build Coastguard Worker 
runSingletonThreadedTest(int numThreads,int initTimeMs)626*35238bceSAndroid Build Coastguard Worker static void runSingletonThreadedTest(int numThreads, int initTimeMs)
627*35238bceSAndroid Build Coastguard Worker {
628*35238bceSAndroid Build Coastguard Worker     deMemPool *tmpPool     = deMemPool_createRoot(DE_NULL, 0);
629*35238bceSAndroid Build Coastguard Worker     deThreadArray *threads = tmpPool ? deThreadArray_create(tmpPool) : DE_NULL;
630*35238bceSAndroid Build Coastguard Worker     int threadNdx;
631*35238bceSAndroid Build Coastguard Worker 
632*35238bceSAndroid Build Coastguard Worker     resetTestState();
633*35238bceSAndroid Build Coastguard Worker 
634*35238bceSAndroid Build Coastguard Worker     for (threadNdx = 0; threadNdx < numThreads; threadNdx++)
635*35238bceSAndroid Build Coastguard Worker     {
636*35238bceSAndroid Build Coastguard Worker         deThread thread = deThread_create(singletonTestThread, &initTimeMs, DE_NULL);
637*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(thread);
638*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deThreadArray_pushBack(threads, thread));
639*35238bceSAndroid Build Coastguard Worker     }
640*35238bceSAndroid Build Coastguard Worker 
641*35238bceSAndroid Build Coastguard Worker     /* All threads created - let them do initialization. */
642*35238bceSAndroid Build Coastguard Worker     deMemoryReadWriteFence();
643*35238bceSAndroid Build Coastguard Worker     s_singletonInitLock = true;
644*35238bceSAndroid Build Coastguard Worker     deMemoryReadWriteFence();
645*35238bceSAndroid Build Coastguard Worker 
646*35238bceSAndroid Build Coastguard Worker     for (threadNdx = 0; threadNdx < numThreads; threadNdx++)
647*35238bceSAndroid Build Coastguard Worker     {
648*35238bceSAndroid Build Coastguard Worker         deThread thread = deThreadArray_get(threads, threadNdx);
649*35238bceSAndroid Build Coastguard Worker         DE_TEST_ASSERT(deThread_join(thread));
650*35238bceSAndroid Build Coastguard Worker         deThread_destroy(thread);
651*35238bceSAndroid Build Coastguard Worker     }
652*35238bceSAndroid Build Coastguard Worker 
653*35238bceSAndroid Build Coastguard Worker     /* Verify results. */
654*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(s_testSingletonInitialized);
655*35238bceSAndroid Build Coastguard Worker     DE_TEST_ASSERT(s_testSingletonInitCount == 1);
656*35238bceSAndroid Build Coastguard Worker 
657*35238bceSAndroid Build Coastguard Worker     deMemPool_destroy(tmpPool);
658*35238bceSAndroid Build Coastguard Worker }
659*35238bceSAndroid Build Coastguard Worker 
deSingleton_selfTest(void)660*35238bceSAndroid Build Coastguard Worker void deSingleton_selfTest(void)
661*35238bceSAndroid Build Coastguard Worker {
662*35238bceSAndroid Build Coastguard Worker     const struct
663*35238bceSAndroid Build Coastguard Worker     {
664*35238bceSAndroid Build Coastguard Worker         int numThreads;
665*35238bceSAndroid Build Coastguard Worker         int initTimeMs;
666*35238bceSAndroid Build Coastguard Worker         int repeatCount;
667*35238bceSAndroid Build Coastguard Worker     } cases[] = {/*    #threads    time    #repeat    */
668*35238bceSAndroid Build Coastguard Worker                  {1, -1, 5}, {1, 1, 5}, {2, -1, 20}, {2, 1, 20}, {4, -1, 20}, {4, 1, 20}, {4, 5, 20}};
669*35238bceSAndroid Build Coastguard Worker     int caseNdx;
670*35238bceSAndroid Build Coastguard Worker 
671*35238bceSAndroid Build Coastguard Worker     for (caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
672*35238bceSAndroid Build Coastguard Worker     {
673*35238bceSAndroid Build Coastguard Worker         int numThreads  = cases[caseNdx].numThreads;
674*35238bceSAndroid Build Coastguard Worker         int initTimeMs  = cases[caseNdx].initTimeMs;
675*35238bceSAndroid Build Coastguard Worker         int repeatCount = cases[caseNdx].repeatCount;
676*35238bceSAndroid Build Coastguard Worker         int subCaseNdx;
677*35238bceSAndroid Build Coastguard Worker 
678*35238bceSAndroid Build Coastguard Worker         for (subCaseNdx = 0; subCaseNdx < repeatCount; subCaseNdx++)
679*35238bceSAndroid Build Coastguard Worker             runSingletonThreadedTest(numThreads, initTimeMs);
680*35238bceSAndroid Build Coastguard Worker     }
681*35238bceSAndroid Build Coastguard Worker }
682