1 /*-------------------------------------------------------------------------
2 * drawElements Thread Library
3 * ---------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Thread library tests.
22 *//*--------------------------------------------------------------------*/
24 #include "deThreadTest.h"
27 #include "deSemaphore.h"
31 #include "deThreadLocal.h"
32 #include "deSingleton.h"
33 #include "deMemPool.h"
34 #include "dePoolArray.h"
36 static void threadTestThr1 (void* arg)
38 deInt32 val = *((deInt32*)arg);
39 DE_TEST_ASSERT(val == 123);
42 static void threadTestThr2 (void* arg)
48 typedef struct ThreadData3_s
53 static void threadTestThr3 (void* arg)
55 ThreadData3* data = (ThreadData3*)arg;
58 for (ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(data->bytes); ndx++)
59 DE_TEST_ASSERT(data->bytes[ndx] == 0);
61 for (ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(data->bytes); ndx++)
62 data->bytes[ndx] = 0xff;
65 static void threadTestThr4 (void* arg)
67 deThreadLocal tls = *(deThreadLocal*)arg;
68 deThreadLocal_set(tls, DE_NULL);
71 #if defined(DE_THREAD_LOCAL)
73 static DE_THREAD_LOCAL int tls_testVar = 123;
75 static void tlsTestThr (void* arg)
78 DE_TEST_ASSERT(tls_testVar == 123);
80 DE_TEST_ASSERT(tls_testVar == 104);
85 void deThread_selfTest (void)
87 /* Test sleep & yield. */
96 deThread thread = deThread_create(threadTestThr1, &val, DE_NULL);
97 DE_TEST_ASSERT(thread);
99 ret = deThread_join(thread);
102 deThread_destroy(thread);
107 deThread thread = deThread_create(threadTestThr2, DE_NULL, DE_NULL);
109 DE_TEST_ASSERT(thread);
111 ret = deThread_join(thread);
114 deThread_destroy(thread);
124 deMemset(&data, 0, sizeof(ThreadData3));
126 thread = deThread_create(threadTestThr3, &data, DE_NULL);
127 DE_TEST_ASSERT(thread);
129 ret = deThread_join(thread);
132 for (ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(data.bytes); ndx++)
133 DE_TEST_ASSERT(data.bytes[ndx] == 0xff);
135 deThread_destroy(thread);
143 tls = deThreadLocal_create();
146 deThreadLocal_set(tls, (void*)(deUintptr)0xff);
148 thread = deThread_create(threadTestThr4, &tls, DE_NULL);
149 deThread_join(thread);
150 deThread_destroy(thread);
152 DE_TEST_ASSERT((deUintptr)deThreadLocal_get(tls) == 0xff);
153 deThreadLocal_destroy(tls);
156 #if defined(DE_THREAD_LOCAL)
160 DE_TEST_ASSERT(tls_testVar == 123);
162 DE_TEST_ASSERT(tls_testVar == 1);
164 thread = deThread_create(tlsTestThr, DE_NULL, DE_NULL);
165 deThread_join(thread);
166 deThread_destroy(thread);
168 DE_TEST_ASSERT(tls_testVar == 1);
174 static void mutexTestThr1 (void* arg)
176 deMutex mutex = *((deMutex*)arg);
179 deMutex_unlock(mutex);
182 typedef struct MutexData2_s
190 static void mutexTestThr2 (void* arg)
192 MutexData2* data = (MutexData2*)arg;
193 deInt32 numIncremented = 0;
197 deInt32 localCounter;
198 deMutex_lock(data->mutex);
200 if (data->counter >= data->maxVal)
202 deMutex_unlock(data->mutex);
206 localCounter = data->counter;
209 DE_TEST_ASSERT(localCounter == data->counter);
211 data->counter = localCounter;
213 deMutex_unlock(data->mutex);
218 deMutex_lock(data->mutex);
219 data->counter2 += numIncremented;
220 deMutex_unlock(data->mutex);
223 void mutexTestThr3 (void* arg)
225 deMutex mutex = *((deMutex*)arg);
228 ret = deMutex_tryLock(mutex);
229 DE_TEST_ASSERT(!ret);
232 void deMutex_selfTest (void)
234 /* Default mutex from single thread. */
236 deMutex mutex = deMutex_create(DE_NULL);
238 DE_TEST_ASSERT(mutex);
241 deMutex_unlock(mutex);
243 /* Should succeed. */
244 ret = deMutex_tryLock(mutex);
246 deMutex_unlock(mutex);
248 deMutex_destroy(mutex);
251 /* Recursive mutex. */
253 deMutexAttributes attrs;
258 deMemset(&attrs, 0, sizeof(attrs));
260 attrs.flags = DE_MUTEX_RECURSIVE;
262 mutex = deMutex_create(&attrs);
263 DE_TEST_ASSERT(mutex);
265 for (ndx = 0; ndx < numLocks; ndx++)
268 for (ndx = 0; ndx < numLocks; ndx++)
269 deMutex_unlock(mutex);
271 deMutex_destroy(mutex);
274 /* Mutex and threads. */
279 mutex = deMutex_create(DE_NULL);
280 DE_TEST_ASSERT(mutex);
284 thread = deThread_create(mutexTestThr1, &mutex, DE_NULL);
285 DE_TEST_ASSERT(thread);
288 deMutex_unlock(mutex);
291 deMutex_unlock(mutex);
293 deThread_join(thread);
295 deThread_destroy(thread);
296 deMutex_destroy(mutex);
299 /* A bit more complex mutex test. */
305 data.mutex = deMutex_create(DE_NULL);
306 DE_TEST_ASSERT(data.mutex);
312 deMutex_lock(data.mutex);
314 for (ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(threads); ndx++)
316 threads[ndx] = deThread_create(mutexTestThr2, &data, DE_NULL);
317 DE_TEST_ASSERT(threads[ndx]);
320 deMutex_unlock(data.mutex);
322 for (ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(threads); ndx++)
324 deBool ret = deThread_join(threads[ndx]);
326 deThread_destroy(threads[ndx]);
329 DE_TEST_ASSERT(data.counter == data.counter2);
330 DE_TEST_ASSERT(data.maxVal == data.counter);
332 deMutex_destroy(data.mutex);
335 /* tryLock() deadlock test. */
338 deMutex mutex = deMutex_create(DE_NULL);
340 DE_TEST_ASSERT(mutex);
344 thread = deThread_create(mutexTestThr3, &mutex, DE_NULL);
345 DE_TEST_ASSERT(mutex);
347 ret = deThread_join(thread);
350 deMutex_unlock(mutex);
351 deMutex_destroy(mutex);
352 deThread_destroy(thread);
356 typedef struct TestBuffer_s
366 void producerThread (void* arg)
368 TestBuffer* buffer = (TestBuffer*)arg;
371 int numToProduce = 10000;
374 deRandom_init(&random, 123);
376 for (ndx = 0; ndx <= numToProduce; ndx++)
380 if (ndx == numToProduce)
386 val = (deInt32)deRandom_getUint32(&random);
390 deSemaphore_decrement(buffer->empty);
392 buffer->buffer[writePos] = val;
393 writePos = (writePos + 1) % DE_LENGTH_OF_ARRAY(buffer->buffer);
395 deSemaphore_increment(buffer->fill);
397 buffer->producerSum += val;
401 void consumerThread (void* arg)
403 TestBuffer* buffer = (TestBuffer*)arg;
410 deSemaphore_decrement(buffer->fill);
412 val = buffer->buffer[readPos];
413 readPos = (readPos + 1) % DE_LENGTH_OF_ARRAY(buffer->buffer);
415 deSemaphore_increment(buffer->empty);
417 buffer->consumerSum += val;
424 void deSemaphore_selfTest (void)
428 deSemaphore semaphore = deSemaphore_create(1, DE_NULL);
429 DE_TEST_ASSERT(semaphore);
431 deSemaphore_increment(semaphore);
432 deSemaphore_decrement(semaphore);
433 deSemaphore_decrement(semaphore);
435 deSemaphore_destroy(semaphore);
438 /* Producer-consumer test. */
440 TestBuffer testBuffer;
445 deMemset(&testBuffer, 0, sizeof(testBuffer));
447 testBuffer.empty = deSemaphore_create(DE_LENGTH_OF_ARRAY(testBuffer.buffer), DE_NULL);
448 testBuffer.fill = deSemaphore_create(0, DE_NULL);
450 DE_TEST_ASSERT(testBuffer.empty && testBuffer.fill);
452 consumer = deThread_create(consumerThread, &testBuffer, DE_NULL);
453 producer = deThread_create(producerThread, &testBuffer, DE_NULL);
455 DE_TEST_ASSERT(consumer && producer);
457 ret = deThread_join(consumer) &&
458 deThread_join(producer);
461 deThread_destroy(producer);
462 deThread_destroy(consumer);
464 deSemaphore_destroy(testBuffer.empty);
465 deSemaphore_destroy(testBuffer.fill);
466 DE_TEST_ASSERT(testBuffer.producerSum == testBuffer.consumerSum);
470 void deAtomic_selfTest (void)
472 /* Single-threaded tests. */
475 DE_TEST_ASSERT(deAtomicIncrement32(&a) == 12);
476 DE_TEST_ASSERT(a == 12);
477 DE_TEST_ASSERT(deAtomicIncrement32(&a) == 13);
478 DE_TEST_ASSERT(a == 13);
480 DE_TEST_ASSERT(deAtomicDecrement32(&a) == 12);
481 DE_TEST_ASSERT(a == 12);
482 DE_TEST_ASSERT(deAtomicDecrement32(&a) == 11);
483 DE_TEST_ASSERT(a == 11);
490 DE_TEST_ASSERT(deAtomicCompareExchange32(&p, 0, 1) == 0);
491 DE_TEST_ASSERT(p == 1);
493 DE_TEST_ASSERT(deAtomicCompareExchange32(&p, 0, 2) == 1);
494 DE_TEST_ASSERT(p == 1);
497 DE_TEST_ASSERT(deAtomicCompareExchange32(&p, 6, 8) == 7);
498 DE_TEST_ASSERT(p == 7);
500 DE_TEST_ASSERT(deAtomicCompareExchange32(&p, 7, 8) == 7);
501 DE_TEST_ASSERT(p == 8);
504 /* \todo [2012-10-26 pyry] Implement multi-threaded tests. */
507 /* Singleton self-test. */
509 DE_DECLARE_POOL_ARRAY(deThreadArray, deThread);
511 static volatile deSingletonState s_testSingleton = DE_SINGLETON_STATE_NOT_INITIALIZED;
512 static volatile int s_testSingletonInitCount = 0;
513 static deBool s_testSingletonInitialized = DE_FALSE;
514 static volatile deBool s_singletonInitLock = DE_FALSE;
516 static void waitForSingletonInitLock (void)
520 deMemoryReadWriteFence();
522 if (s_singletonInitLock)
527 static void initTestSingleton (void* arg)
529 int initTimeMs = *(const int*)arg;
532 deSleep((deUint32)initTimeMs);
534 deAtomicIncrement32(&s_testSingletonInitCount);
535 s_testSingletonInitialized = DE_TRUE;
538 static void singletonTestThread (void* arg)
540 waitForSingletonInitLock();
542 deInitSingleton(&s_testSingleton, initTestSingleton, arg);
543 DE_TEST_ASSERT(s_testSingletonInitialized);
546 static void resetTestState (void)
548 s_testSingleton = DE_SINGLETON_STATE_NOT_INITIALIZED;
549 s_testSingletonInitCount = 0;
550 s_testSingletonInitialized = DE_FALSE;
551 s_singletonInitLock = DE_FALSE;
554 static void runSingletonThreadedTest (int numThreads, int initTimeMs)
556 deMemPool* tmpPool = deMemPool_createRoot(DE_NULL, 0);
557 deThreadArray* threads = tmpPool ? deThreadArray_create(tmpPool) : DE_NULL;
562 for (threadNdx = 0; threadNdx < numThreads; threadNdx++)
564 deThread thread = deThread_create(singletonTestThread, &initTimeMs, DE_NULL);
565 DE_TEST_ASSERT(thread);
566 DE_TEST_ASSERT(deThreadArray_pushBack(threads, thread));
569 /* All threads created - let them do initialization. */
570 deMemoryReadWriteFence();
571 s_singletonInitLock = DE_TRUE;
572 deMemoryReadWriteFence();
574 for (threadNdx = 0; threadNdx < numThreads; threadNdx++)
576 deThread thread = deThreadArray_get(threads, threadNdx);
577 DE_TEST_ASSERT(deThread_join(thread));
578 deThread_destroy(thread);
581 /* Verify results. */
582 DE_TEST_ASSERT(s_testSingletonInitialized);
583 DE_TEST_ASSERT(s_testSingletonInitCount == 1);
585 deMemPool_destroy(tmpPool);
588 void deSingleton_selfTest (void)
597 /* #threads time #repeat */
608 for (caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
610 int numThreads = cases[caseNdx].numThreads;
611 int initTimeMs = cases[caseNdx].initTimeMs;
612 int repeatCount = cases[caseNdx].repeatCount;
615 for (subCaseNdx = 0; subCaseNdx < repeatCount; subCaseNdx++)
616 runSingletonThreadedTest(numThreads, initTimeMs);