Merge vk-gl-cts/opengl-es-cts-3.2.3 into vk-gl-cts/opengl-es-cts-3.2.4
[platform/upstream/VK-GL-CTS.git] / framework / delibs / dethread / deThreadTest.c
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
36 static void threadTestThr1 (void* arg)
37 {
38         deInt32 val = *((deInt32*)arg);
39         DE_TEST_ASSERT(val == 123);
40 }
41
42 static void threadTestThr2 (void* arg)
43 {
44         DE_UNREF(arg);
45         deSleep(100);
46 }
47
48 typedef struct ThreadData3_s
49 {
50         deUint8         bytes[16];
51 } ThreadData3;
52
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
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
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
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                 deInt32         val             = 123;
95                 deBool          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                 deInt32         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                 deBool          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*)(deUintptr)0xff);
147
148                 thread = deThread_create(threadTestThr4, &tls, DE_NULL);
149                 deThread_join(thread);
150                 deThread_destroy(thread);
151
152                 DE_TEST_ASSERT((deUintptr)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
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         deInt32         counter;
186         deInt32         counter2;
187         deInt32         maxVal;
188 } MutexData2;
189
190 static void mutexTestThr2 (void* arg)
191 {
192         MutexData2* data = (MutexData2*)arg;
193         deInt32 numIncremented = 0;
194
195         for (;;)
196         {
197                 deInt32 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
223 void mutexTestThr3 (void* arg)
224 {
225         deMutex mutex = *((deMutex*)arg);
226         deBool  ret;
227
228         ret = deMutex_tryLock(mutex);
229         DE_TEST_ASSERT(!ret);
230 }
231
232 void deMutex_selfTest (void)
233 {
234         /* Default mutex from single thread. */
235         {
236                 deMutex mutex = deMutex_create(DE_NULL);
237                 deBool  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                         deBool 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                 deBool          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         deUint32                buffer[32];
359         deSemaphore             empty;
360         deSemaphore             fill;
361
362         deUint32                producerHash;
363         deUint32                consumerHash;
364 } TestBuffer;
365
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                 deUint32 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
401 void consumerThread (void* arg)
402 {
403         TestBuffer*     buffer  = (TestBuffer*)arg;
404         int                     readPos = 0;
405
406         for (;;)
407         {
408                 deInt32 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
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                 deBool          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) &&
458                           deThread_join(producer);
459                 DE_TEST_ASSERT(ret);
460
461                 deThread_destroy(producer);
462                 deThread_destroy(consumer);
463
464                 deSemaphore_destroy(testBuffer.empty);
465                 deSemaphore_destroy(testBuffer.fill);
466                 DE_TEST_ASSERT(testBuffer.producerHash == testBuffer.consumerHash);
467         }
468 }
469
470 void deAtomic_selfTest (void)
471 {
472         /* Single-threaded tests. */
473         {
474                 volatile deInt32 a = 11;
475                 DE_TEST_ASSERT(deAtomicIncrementInt32(&a) == 12);
476                 DE_TEST_ASSERT(a == 12);
477                 DE_TEST_ASSERT(deAtomicIncrementInt32(&a) == 13);
478                 DE_TEST_ASSERT(a == 13);
479
480                 a = -2;
481                 DE_TEST_ASSERT(deAtomicIncrementInt32(&a) == -1);
482                 DE_TEST_ASSERT(a == -1);
483                 DE_TEST_ASSERT(deAtomicIncrementInt32(&a) == 0);
484                 DE_TEST_ASSERT(a == 0);
485
486                 a = 11;
487                 DE_TEST_ASSERT(deAtomicDecrementInt32(&a) == 10);
488                 DE_TEST_ASSERT(a == 10);
489                 DE_TEST_ASSERT(deAtomicDecrementInt32(&a) == 9);
490                 DE_TEST_ASSERT(a == 9);
491
492                 a = 0;
493                 DE_TEST_ASSERT(deAtomicDecrementInt32(&a) == -1);
494                 DE_TEST_ASSERT(a == -1);
495                 DE_TEST_ASSERT(deAtomicDecrementInt32(&a) == -2);
496                 DE_TEST_ASSERT(a == -2);
497
498                 a = 0x7fffffff;
499                 DE_TEST_ASSERT(deAtomicIncrementInt32(&a) == (int)0x80000000);
500                 DE_TEST_ASSERT(a == (int)0x80000000);
501                 DE_TEST_ASSERT(deAtomicDecrementInt32(&a) == (int)0x7fffffff);
502                 DE_TEST_ASSERT(a == 0x7fffffff);
503         }
504
505         {
506                 volatile deUint32 a = 11;
507                 DE_TEST_ASSERT(deAtomicIncrementUint32(&a) == 12);
508                 DE_TEST_ASSERT(a == 12);
509                 DE_TEST_ASSERT(deAtomicIncrementUint32(&a) == 13);
510                 DE_TEST_ASSERT(a == 13);
511
512                 a = 0x7fffffff;
513                 DE_TEST_ASSERT(deAtomicIncrementUint32(&a) == 0x80000000);
514                 DE_TEST_ASSERT(a == 0x80000000);
515                 DE_TEST_ASSERT(deAtomicDecrementUint32(&a) == 0x7fffffff);
516                 DE_TEST_ASSERT(a == 0x7fffffff);
517
518                 a = 0xfffffffe;
519                 DE_TEST_ASSERT(deAtomicIncrementUint32(&a) == 0xffffffff);
520                 DE_TEST_ASSERT(a == 0xffffffff);
521                 DE_TEST_ASSERT(deAtomicDecrementUint32(&a) == 0xfffffffe);
522                 DE_TEST_ASSERT(a == 0xfffffffe);
523         }
524
525         {
526                 volatile deUint32 p;
527
528                 p = 0;
529                 DE_TEST_ASSERT(deAtomicCompareExchange32(&p, 0, 1) == 0);
530                 DE_TEST_ASSERT(p == 1);
531
532                 DE_TEST_ASSERT(deAtomicCompareExchange32(&p, 0, 2) == 1);
533                 DE_TEST_ASSERT(p == 1);
534
535                 p = 7;
536                 DE_TEST_ASSERT(deAtomicCompareExchange32(&p, 6, 8) == 7);
537                 DE_TEST_ASSERT(p == 7);
538
539                 DE_TEST_ASSERT(deAtomicCompareExchange32(&p, 7, 8) == 7);
540                 DE_TEST_ASSERT(p == 8);
541         }
542
543 #if (DE_PTR_SIZE == 8)
544         {
545                 volatile deInt64 a = 11;
546                 DE_TEST_ASSERT(deAtomicIncrementInt64(&a) == 12);
547                 DE_TEST_ASSERT(a == 12);
548                 DE_TEST_ASSERT(deAtomicIncrementInt64(&a) == 13);
549                 DE_TEST_ASSERT(a == 13);
550
551                 a = -2;
552                 DE_TEST_ASSERT(deAtomicIncrementInt64(&a) == -1);
553                 DE_TEST_ASSERT(a == -1);
554                 DE_TEST_ASSERT(deAtomicIncrementInt64(&a) == 0);
555                 DE_TEST_ASSERT(a == 0);
556
557                 a = 11;
558                 DE_TEST_ASSERT(deAtomicDecrementInt64(&a) == 10);
559                 DE_TEST_ASSERT(a == 10);
560                 DE_TEST_ASSERT(deAtomicDecrementInt64(&a) == 9);
561                 DE_TEST_ASSERT(a == 9);
562
563                 a = 0;
564                 DE_TEST_ASSERT(deAtomicDecrementInt64(&a) == -1);
565                 DE_TEST_ASSERT(a == -1);
566                 DE_TEST_ASSERT(deAtomicDecrementInt64(&a) == -2);
567                 DE_TEST_ASSERT(a == -2);
568
569                 a = (deInt64)((1ull << 63) - 1ull);
570                 DE_TEST_ASSERT(deAtomicIncrementInt64(&a) == (deInt64)(1ull << 63));
571                 DE_TEST_ASSERT(a == (deInt64)(1ull << 63));
572                 DE_TEST_ASSERT(deAtomicDecrementInt64(&a) == (deInt64)((1ull << 63) - 1));
573                 DE_TEST_ASSERT(a == (deInt64)((1ull << 63) - 1));
574         }
575 #endif /* (DE_PTR_SIZE == 8) */
576
577         /* \todo [2012-10-26 pyry] Implement multi-threaded tests. */
578 }
579
580 /* Singleton self-test. */
581
582 DE_DECLARE_POOL_ARRAY(deThreadArray, deThread);
583
584 static volatile deSingletonState        s_testSingleton                         = DE_SINGLETON_STATE_NOT_INITIALIZED;
585 static volatile int                                     s_testSingletonInitCount        = 0;
586 static deBool                                           s_testSingletonInitialized      = DE_FALSE;
587 static volatile deBool                          s_singletonInitLock                     = DE_FALSE;
588
589 static void waitForSingletonInitLock (void)
590 {
591         for (;;)
592         {
593                 deMemoryReadWriteFence();
594
595                 if (s_singletonInitLock)
596                         break;
597         }
598 }
599
600 static void initTestSingleton (void* arg)
601 {
602         int initTimeMs = *(const int*)arg;
603
604         if (initTimeMs >= 0)
605                 deSleep((deUint32)initTimeMs);
606
607         deAtomicIncrement32(&s_testSingletonInitCount);
608         s_testSingletonInitialized = DE_TRUE;
609 }
610
611 static void singletonTestThread (void* arg)
612 {
613         waitForSingletonInitLock();
614
615         deInitSingleton(&s_testSingleton, initTestSingleton, arg);
616         DE_TEST_ASSERT(s_testSingletonInitialized);
617 }
618
619 static void resetTestState (void)
620 {
621         s_testSingleton                         = DE_SINGLETON_STATE_NOT_INITIALIZED;
622         s_testSingletonInitCount        = 0;
623         s_testSingletonInitialized      = DE_FALSE;
624         s_singletonInitLock                     = DE_FALSE;
625 }
626
627 static void runSingletonThreadedTest (int numThreads, int initTimeMs)
628 {
629         deMemPool*              tmpPool         = deMemPool_createRoot(DE_NULL, 0);
630         deThreadArray*  threads         = tmpPool ? deThreadArray_create(tmpPool) : DE_NULL;
631         int                             threadNdx;
632
633         resetTestState();
634
635         for (threadNdx = 0; threadNdx < numThreads; threadNdx++)
636         {
637                 deThread thread = deThread_create(singletonTestThread, &initTimeMs, DE_NULL);
638                 DE_TEST_ASSERT(thread);
639                 DE_TEST_ASSERT(deThreadArray_pushBack(threads, thread));
640         }
641
642         /* All threads created - let them do initialization. */
643         deMemoryReadWriteFence();
644         s_singletonInitLock = DE_TRUE;
645         deMemoryReadWriteFence();
646
647         for (threadNdx = 0; threadNdx < numThreads; threadNdx++)
648         {
649                 deThread thread = deThreadArray_get(threads, threadNdx);
650                 DE_TEST_ASSERT(deThread_join(thread));
651                 deThread_destroy(thread);
652         }
653
654         /* Verify results. */
655         DE_TEST_ASSERT(s_testSingletonInitialized);
656         DE_TEST_ASSERT(s_testSingletonInitCount == 1);
657
658         deMemPool_destroy(tmpPool);
659 }
660
661 void deSingleton_selfTest (void)
662 {
663         const struct
664         {
665                 int             numThreads;
666                 int             initTimeMs;
667                 int             repeatCount;
668         } cases[] =
669         {
670         /*      #threads        time    #repeat */
671                 { 1,            -1,             5       },
672                 { 1,            1,              5       },
673                 { 2,            -1,             20      },
674                 { 2,            1,              20      },
675                 { 4,            -1,             20      },
676                 { 4,            1,              20      },
677                 { 4,            5,              20      }
678         };
679         int caseNdx;
680
681         for (caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
682         {
683                 int             numThreads              = cases[caseNdx].numThreads;
684                 int             initTimeMs              = cases[caseNdx].initTimeMs;
685                 int             repeatCount             = cases[caseNdx].repeatCount;
686                 int             subCaseNdx;
687
688                 for (subCaseNdx = 0; subCaseNdx < repeatCount; subCaseNdx++)
689                         runSingletonThreadedTest(numThreads, initTimeMs);
690         }
691 }