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