You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
692 lines
15 KiB
692 lines
15 KiB
/*-------------------------------------------------------------------------
|
|
* drawElements Thread Library
|
|
* ---------------------------
|
|
*
|
|
* Copyright 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*//*!
|
|
* \file
|
|
* \brief Thread library tests.
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "deThreadTest.h"
|
|
#include "deThread.h"
|
|
#include "deMutex.h"
|
|
#include "deSemaphore.h"
|
|
#include "deMemory.h"
|
|
#include "deRandom.h"
|
|
#include "deAtomic.h"
|
|
#include "deThreadLocal.h"
|
|
#include "deSingleton.h"
|
|
#include "deMemPool.h"
|
|
#include "dePoolArray.h"
|
|
|
|
static void threadTestThr1 (void* arg)
|
|
{
|
|
deInt32 val = *((deInt32*)arg);
|
|
DE_TEST_ASSERT(val == 123);
|
|
}
|
|
|
|
static void threadTestThr2 (void* arg)
|
|
{
|
|
DE_UNREF(arg);
|
|
deSleep(100);
|
|
}
|
|
|
|
typedef struct ThreadData3_s
|
|
{
|
|
deUint8 bytes[16];
|
|
} ThreadData3;
|
|
|
|
static void threadTestThr3 (void* arg)
|
|
{
|
|
ThreadData3* data = (ThreadData3*)arg;
|
|
int ndx;
|
|
|
|
for (ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(data->bytes); ndx++)
|
|
DE_TEST_ASSERT(data->bytes[ndx] == 0);
|
|
|
|
for (ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(data->bytes); ndx++)
|
|
data->bytes[ndx] = 0xff;
|
|
}
|
|
|
|
static void threadTestThr4 (void* arg)
|
|
{
|
|
deThreadLocal tls = *(deThreadLocal*)arg;
|
|
deThreadLocal_set(tls, DE_NULL);
|
|
}
|
|
|
|
#if defined(DE_THREAD_LOCAL)
|
|
|
|
static DE_THREAD_LOCAL int tls_testVar = 123;
|
|
|
|
static void tlsTestThr (void* arg)
|
|
{
|
|
DE_UNREF(arg);
|
|
DE_TEST_ASSERT(tls_testVar == 123);
|
|
tls_testVar = 104;
|
|
DE_TEST_ASSERT(tls_testVar == 104);
|
|
}
|
|
|
|
#endif
|
|
|
|
void deThread_selfTest (void)
|
|
{
|
|
/* Test sleep & yield. */
|
|
deSleep(0);
|
|
deSleep(100);
|
|
deYield();
|
|
|
|
/* Thread test 1. */
|
|
{
|
|
deInt32 val = 123;
|
|
deBool ret;
|
|
deThread thread = deThread_create(threadTestThr1, &val, DE_NULL);
|
|
DE_TEST_ASSERT(thread);
|
|
|
|
ret = deThread_join(thread);
|
|
DE_TEST_ASSERT(ret);
|
|
|
|
deThread_destroy(thread);
|
|
}
|
|
|
|
/* Thread test 2. */
|
|
{
|
|
deThread thread = deThread_create(threadTestThr2, DE_NULL, DE_NULL);
|
|
deInt32 ret;
|
|
DE_TEST_ASSERT(thread);
|
|
|
|
ret = deThread_join(thread);
|
|
DE_TEST_ASSERT(ret);
|
|
|
|
deThread_destroy(thread);
|
|
}
|
|
|
|
/* Thread test 3. */
|
|
{
|
|
ThreadData3 data;
|
|
deThread thread;
|
|
deBool ret;
|
|
int ndx;
|
|
|
|
deMemset(&data, 0, sizeof(ThreadData3));
|
|
|
|
thread = deThread_create(threadTestThr3, &data, DE_NULL);
|
|
DE_TEST_ASSERT(thread);
|
|
|
|
ret = deThread_join(thread);
|
|
DE_TEST_ASSERT(ret);
|
|
|
|
for (ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(data.bytes); ndx++)
|
|
DE_TEST_ASSERT(data.bytes[ndx] == 0xff);
|
|
|
|
deThread_destroy(thread);
|
|
}
|
|
|
|
/* Test tls. */
|
|
{
|
|
deThreadLocal tls;
|
|
deThread thread;
|
|
|
|
tls = deThreadLocal_create();
|
|
DE_TEST_ASSERT(tls);
|
|
|
|
deThreadLocal_set(tls, (void*)(deUintptr)0xff);
|
|
|
|
thread = deThread_create(threadTestThr4, &tls, DE_NULL);
|
|
deThread_join(thread);
|
|
deThread_destroy(thread);
|
|
|
|
DE_TEST_ASSERT((deUintptr)deThreadLocal_get(tls) == 0xff);
|
|
deThreadLocal_destroy(tls);
|
|
}
|
|
|
|
#if defined(DE_THREAD_LOCAL)
|
|
{
|
|
deThread thread;
|
|
|
|
DE_TEST_ASSERT(tls_testVar == 123);
|
|
tls_testVar = 1;
|
|
DE_TEST_ASSERT(tls_testVar == 1);
|
|
|
|
thread = deThread_create(tlsTestThr, DE_NULL, DE_NULL);
|
|
deThread_join(thread);
|
|
deThread_destroy(thread);
|
|
|
|
DE_TEST_ASSERT(tls_testVar == 1);
|
|
tls_testVar = 123;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void mutexTestThr1 (void* arg)
|
|
{
|
|
deMutex mutex = *((deMutex*)arg);
|
|
|
|
deMutex_lock(mutex);
|
|
deMutex_unlock(mutex);
|
|
}
|
|
|
|
typedef struct MutexData2_s
|
|
{
|
|
deMutex mutex;
|
|
deInt32 counter;
|
|
deInt32 counter2;
|
|
deInt32 maxVal;
|
|
} MutexData2;
|
|
|
|
static void mutexTestThr2 (void* arg)
|
|
{
|
|
MutexData2* data = (MutexData2*)arg;
|
|
deInt32 numIncremented = 0;
|
|
|
|
for (;;)
|
|
{
|
|
deInt32 localCounter;
|
|
deMutex_lock(data->mutex);
|
|
|
|
if (data->counter >= data->maxVal)
|
|
{
|
|
deMutex_unlock(data->mutex);
|
|
break;
|
|
}
|
|
|
|
localCounter = data->counter;
|
|
deYield();
|
|
|
|
DE_TEST_ASSERT(localCounter == data->counter);
|
|
localCounter += 1;
|
|
data->counter = localCounter;
|
|
|
|
deMutex_unlock(data->mutex);
|
|
|
|
numIncremented++;
|
|
}
|
|
|
|
deMutex_lock(data->mutex);
|
|
data->counter2 += numIncremented;
|
|
deMutex_unlock(data->mutex);
|
|
}
|
|
|
|
void mutexTestThr3 (void* arg)
|
|
{
|
|
deMutex mutex = *((deMutex*)arg);
|
|
deBool ret;
|
|
|
|
ret = deMutex_tryLock(mutex);
|
|
DE_TEST_ASSERT(!ret);
|
|
}
|
|
|
|
void deMutex_selfTest (void)
|
|
{
|
|
/* Default mutex from single thread. */
|
|
{
|
|
deMutex mutex = deMutex_create(DE_NULL);
|
|
deBool ret;
|
|
DE_TEST_ASSERT(mutex);
|
|
|
|
deMutex_lock(mutex);
|
|
deMutex_unlock(mutex);
|
|
|
|
/* Should succeed. */
|
|
ret = deMutex_tryLock(mutex);
|
|
DE_TEST_ASSERT(ret);
|
|
deMutex_unlock(mutex);
|
|
|
|
deMutex_destroy(mutex);
|
|
}
|
|
|
|
/* Recursive mutex. */
|
|
{
|
|
deMutexAttributes attrs;
|
|
deMutex mutex;
|
|
int ndx;
|
|
int numLocks = 10;
|
|
|
|
deMemset(&attrs, 0, sizeof(attrs));
|
|
|
|
attrs.flags = DE_MUTEX_RECURSIVE;
|
|
|
|
mutex = deMutex_create(&attrs);
|
|
DE_TEST_ASSERT(mutex);
|
|
|
|
for (ndx = 0; ndx < numLocks; ndx++)
|
|
deMutex_lock(mutex);
|
|
|
|
for (ndx = 0; ndx < numLocks; ndx++)
|
|
deMutex_unlock(mutex);
|
|
|
|
deMutex_destroy(mutex);
|
|
}
|
|
|
|
/* Mutex and threads. */
|
|
{
|
|
deMutex mutex;
|
|
deThread thread;
|
|
|
|
mutex = deMutex_create(DE_NULL);
|
|
DE_TEST_ASSERT(mutex);
|
|
|
|
deMutex_lock(mutex);
|
|
|
|
thread = deThread_create(mutexTestThr1, &mutex, DE_NULL);
|
|
DE_TEST_ASSERT(thread);
|
|
|
|
deSleep(100);
|
|
deMutex_unlock(mutex);
|
|
|
|
deMutex_lock(mutex);
|
|
deMutex_unlock(mutex);
|
|
|
|
deThread_join(thread);
|
|
|
|
deThread_destroy(thread);
|
|
deMutex_destroy(mutex);
|
|
}
|
|
|
|
/* A bit more complex mutex test. */
|
|
{
|
|
MutexData2 data;
|
|
deThread threads[2];
|
|
int ndx;
|
|
|
|
data.mutex = deMutex_create(DE_NULL);
|
|
DE_TEST_ASSERT(data.mutex);
|
|
|
|
data.counter = 0;
|
|
data.counter2 = 0;
|
|
data.maxVal = 1000;
|
|
|
|
deMutex_lock(data.mutex);
|
|
|
|
for (ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(threads); ndx++)
|
|
{
|
|
threads[ndx] = deThread_create(mutexTestThr2, &data, DE_NULL);
|
|
DE_TEST_ASSERT(threads[ndx]);
|
|
}
|
|
|
|
deMutex_unlock(data.mutex);
|
|
|
|
for (ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(threads); ndx++)
|
|
{
|
|
deBool ret = deThread_join(threads[ndx]);
|
|
DE_TEST_ASSERT(ret);
|
|
deThread_destroy(threads[ndx]);
|
|
}
|
|
|
|
DE_TEST_ASSERT(data.counter == data.counter2);
|
|
DE_TEST_ASSERT(data.maxVal == data.counter);
|
|
|
|
deMutex_destroy(data.mutex);
|
|
}
|
|
|
|
/* tryLock() deadlock test. */
|
|
{
|
|
deThread thread;
|
|
deMutex mutex = deMutex_create(DE_NULL);
|
|
deBool ret;
|
|
DE_TEST_ASSERT(mutex);
|
|
|
|
deMutex_lock(mutex);
|
|
|
|
thread = deThread_create(mutexTestThr3, &mutex, DE_NULL);
|
|
DE_TEST_ASSERT(mutex);
|
|
|
|
ret = deThread_join(thread);
|
|
DE_TEST_ASSERT(ret);
|
|
|
|
deMutex_unlock(mutex);
|
|
deMutex_destroy(mutex);
|
|
deThread_destroy(thread);
|
|
}
|
|
}
|
|
|
|
typedef struct TestBuffer_s
|
|
{
|
|
deUint32 buffer[32];
|
|
deSemaphore empty;
|
|
deSemaphore fill;
|
|
|
|
deUint32 producerHash;
|
|
deUint32 consumerHash;
|
|
} TestBuffer;
|
|
|
|
void producerThread (void* arg)
|
|
{
|
|
TestBuffer* buffer = (TestBuffer*)arg;
|
|
deRandom random;
|
|
int ndx;
|
|
int numToProduce = 10000;
|
|
int writePos = 0;
|
|
|
|
deRandom_init(&random, 123);
|
|
|
|
for (ndx = 0; ndx <= numToProduce; ndx++)
|
|
{
|
|
deUint32 val;
|
|
|
|
if (ndx == numToProduce)
|
|
{
|
|
val = 0u; /* End. */
|
|
}
|
|
else
|
|
{
|
|
val = deRandom_getUint32(&random);
|
|
val = val ? val : 1u;
|
|
}
|
|
|
|
deSemaphore_decrement(buffer->empty);
|
|
|
|
buffer->buffer[writePos] = val;
|
|
writePos = (writePos + 1) % DE_LENGTH_OF_ARRAY(buffer->buffer);
|
|
|
|
deSemaphore_increment(buffer->fill);
|
|
|
|
buffer->producerHash ^= val;
|
|
}
|
|
}
|
|
|
|
void consumerThread (void* arg)
|
|
{
|
|
TestBuffer* buffer = (TestBuffer*)arg;
|
|
int readPos = 0;
|
|
|
|
for (;;)
|
|
{
|
|
deInt32 val;
|
|
|
|
deSemaphore_decrement(buffer->fill);
|
|
|
|
val = buffer->buffer[readPos];
|
|
readPos = (readPos + 1) % DE_LENGTH_OF_ARRAY(buffer->buffer);
|
|
|
|
deSemaphore_increment(buffer->empty);
|
|
|
|
buffer->consumerHash ^= val;
|
|
|
|
if (val == 0)
|
|
break;
|
|
}
|
|
}
|
|
|
|
void deSemaphore_selfTest (void)
|
|
{
|
|
/* Basic test. */
|
|
{
|
|
deSemaphore semaphore = deSemaphore_create(1, DE_NULL);
|
|
DE_TEST_ASSERT(semaphore);
|
|
|
|
deSemaphore_increment(semaphore);
|
|
deSemaphore_decrement(semaphore);
|
|
deSemaphore_decrement(semaphore);
|
|
|
|
deSemaphore_destroy(semaphore);
|
|
}
|
|
|
|
/* Producer-consumer test. */
|
|
{
|
|
TestBuffer testBuffer;
|
|
deThread producer;
|
|
deThread consumer;
|
|
deBool ret;
|
|
|
|
deMemset(&testBuffer, 0, sizeof(testBuffer));
|
|
|
|
testBuffer.empty = deSemaphore_create(DE_LENGTH_OF_ARRAY(testBuffer.buffer), DE_NULL);
|
|
testBuffer.fill = deSemaphore_create(0, DE_NULL);
|
|
|
|
DE_TEST_ASSERT(testBuffer.empty && testBuffer.fill);
|
|
|
|
consumer = deThread_create(consumerThread, &testBuffer, DE_NULL);
|
|
producer = deThread_create(producerThread, &testBuffer, DE_NULL);
|
|
|
|
DE_TEST_ASSERT(consumer && producer);
|
|
|
|
ret = deThread_join(consumer) &&
|
|
deThread_join(producer);
|
|
DE_TEST_ASSERT(ret);
|
|
|
|
deThread_destroy(producer);
|
|
deThread_destroy(consumer);
|
|
|
|
deSemaphore_destroy(testBuffer.empty);
|
|
deSemaphore_destroy(testBuffer.fill);
|
|
DE_TEST_ASSERT(testBuffer.producerHash == testBuffer.consumerHash);
|
|
}
|
|
}
|
|
|
|
void deAtomic_selfTest (void)
|
|
{
|
|
/* Single-threaded tests. */
|
|
{
|
|
volatile deInt32 a = 11;
|
|
DE_TEST_ASSERT(deAtomicIncrementInt32(&a) == 12);
|
|
DE_TEST_ASSERT(a == 12);
|
|
DE_TEST_ASSERT(deAtomicIncrementInt32(&a) == 13);
|
|
DE_TEST_ASSERT(a == 13);
|
|
|
|
a = -2;
|
|
DE_TEST_ASSERT(deAtomicIncrementInt32(&a) == -1);
|
|
DE_TEST_ASSERT(a == -1);
|
|
DE_TEST_ASSERT(deAtomicIncrementInt32(&a) == 0);
|
|
DE_TEST_ASSERT(a == 0);
|
|
|
|
a = 11;
|
|
DE_TEST_ASSERT(deAtomicDecrementInt32(&a) == 10);
|
|
DE_TEST_ASSERT(a == 10);
|
|
DE_TEST_ASSERT(deAtomicDecrementInt32(&a) == 9);
|
|
DE_TEST_ASSERT(a == 9);
|
|
|
|
a = 0;
|
|
DE_TEST_ASSERT(deAtomicDecrementInt32(&a) == -1);
|
|
DE_TEST_ASSERT(a == -1);
|
|
DE_TEST_ASSERT(deAtomicDecrementInt32(&a) == -2);
|
|
DE_TEST_ASSERT(a == -2);
|
|
|
|
a = 0x7fffffff;
|
|
DE_TEST_ASSERT(deAtomicIncrementInt32(&a) == (int)0x80000000);
|
|
DE_TEST_ASSERT(a == (int)0x80000000);
|
|
DE_TEST_ASSERT(deAtomicDecrementInt32(&a) == (int)0x7fffffff);
|
|
DE_TEST_ASSERT(a == 0x7fffffff);
|
|
}
|
|
|
|
{
|
|
volatile deUint32 a = 11;
|
|
DE_TEST_ASSERT(deAtomicIncrementUint32(&a) == 12);
|
|
DE_TEST_ASSERT(a == 12);
|
|
DE_TEST_ASSERT(deAtomicIncrementUint32(&a) == 13);
|
|
DE_TEST_ASSERT(a == 13);
|
|
|
|
a = 0x7fffffff;
|
|
DE_TEST_ASSERT(deAtomicIncrementUint32(&a) == 0x80000000);
|
|
DE_TEST_ASSERT(a == 0x80000000);
|
|
DE_TEST_ASSERT(deAtomicDecrementUint32(&a) == 0x7fffffff);
|
|
DE_TEST_ASSERT(a == 0x7fffffff);
|
|
|
|
a = 0xfffffffe;
|
|
DE_TEST_ASSERT(deAtomicIncrementUint32(&a) == 0xffffffff);
|
|
DE_TEST_ASSERT(a == 0xffffffff);
|
|
DE_TEST_ASSERT(deAtomicDecrementUint32(&a) == 0xfffffffe);
|
|
DE_TEST_ASSERT(a == 0xfffffffe);
|
|
}
|
|
|
|
{
|
|
volatile deUint32 p;
|
|
|
|
p = 0;
|
|
DE_TEST_ASSERT(deAtomicCompareExchange32(&p, 0, 1) == 0);
|
|
DE_TEST_ASSERT(p == 1);
|
|
|
|
DE_TEST_ASSERT(deAtomicCompareExchange32(&p, 0, 2) == 1);
|
|
DE_TEST_ASSERT(p == 1);
|
|
|
|
p = 7;
|
|
DE_TEST_ASSERT(deAtomicCompareExchange32(&p, 6, 8) == 7);
|
|
DE_TEST_ASSERT(p == 7);
|
|
|
|
DE_TEST_ASSERT(deAtomicCompareExchange32(&p, 7, 8) == 7);
|
|
DE_TEST_ASSERT(p == 8);
|
|
}
|
|
|
|
#if (DE_PTR_SIZE == 8)
|
|
{
|
|
volatile deInt64 a = 11;
|
|
DE_TEST_ASSERT(deAtomicIncrementInt64(&a) == 12);
|
|
DE_TEST_ASSERT(a == 12);
|
|
DE_TEST_ASSERT(deAtomicIncrementInt64(&a) == 13);
|
|
DE_TEST_ASSERT(a == 13);
|
|
|
|
a = -2;
|
|
DE_TEST_ASSERT(deAtomicIncrementInt64(&a) == -1);
|
|
DE_TEST_ASSERT(a == -1);
|
|
DE_TEST_ASSERT(deAtomicIncrementInt64(&a) == 0);
|
|
DE_TEST_ASSERT(a == 0);
|
|
|
|
a = 11;
|
|
DE_TEST_ASSERT(deAtomicDecrementInt64(&a) == 10);
|
|
DE_TEST_ASSERT(a == 10);
|
|
DE_TEST_ASSERT(deAtomicDecrementInt64(&a) == 9);
|
|
DE_TEST_ASSERT(a == 9);
|
|
|
|
a = 0;
|
|
DE_TEST_ASSERT(deAtomicDecrementInt64(&a) == -1);
|
|
DE_TEST_ASSERT(a == -1);
|
|
DE_TEST_ASSERT(deAtomicDecrementInt64(&a) == -2);
|
|
DE_TEST_ASSERT(a == -2);
|
|
|
|
a = (deInt64)((1ull << 63) - 1ull);
|
|
DE_TEST_ASSERT(deAtomicIncrementInt64(&a) == (deInt64)(1ull << 63));
|
|
DE_TEST_ASSERT(a == (deInt64)(1ull << 63));
|
|
DE_TEST_ASSERT(deAtomicDecrementInt64(&a) == (deInt64)((1ull << 63) - 1));
|
|
DE_TEST_ASSERT(a == (deInt64)((1ull << 63) - 1));
|
|
}
|
|
#endif /* (DE_PTR_SIZE == 8) */
|
|
|
|
/* \todo [2012-10-26 pyry] Implement multi-threaded tests. */
|
|
}
|
|
|
|
/* Singleton self-test. */
|
|
|
|
DE_DECLARE_POOL_ARRAY(deThreadArray, deThread);
|
|
|
|
static volatile deSingletonState s_testSingleton = DE_SINGLETON_STATE_NOT_INITIALIZED;
|
|
static volatile int s_testSingletonInitCount = 0;
|
|
static deBool s_testSingletonInitialized = DE_FALSE;
|
|
static volatile deBool s_singletonInitLock = DE_FALSE;
|
|
|
|
static void waitForSingletonInitLock (void)
|
|
{
|
|
for (;;)
|
|
{
|
|
deMemoryReadWriteFence();
|
|
|
|
if (s_singletonInitLock)
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void initTestSingleton (void* arg)
|
|
{
|
|
int initTimeMs = *(const int*)arg;
|
|
|
|
if (initTimeMs >= 0)
|
|
deSleep((deUint32)initTimeMs);
|
|
|
|
deAtomicIncrement32(&s_testSingletonInitCount);
|
|
s_testSingletonInitialized = DE_TRUE;
|
|
}
|
|
|
|
static void singletonTestThread (void* arg)
|
|
{
|
|
waitForSingletonInitLock();
|
|
|
|
deInitSingleton(&s_testSingleton, initTestSingleton, arg);
|
|
DE_TEST_ASSERT(s_testSingletonInitialized);
|
|
}
|
|
|
|
static void resetTestState (void)
|
|
{
|
|
s_testSingleton = DE_SINGLETON_STATE_NOT_INITIALIZED;
|
|
s_testSingletonInitCount = 0;
|
|
s_testSingletonInitialized = DE_FALSE;
|
|
s_singletonInitLock = DE_FALSE;
|
|
}
|
|
|
|
static void runSingletonThreadedTest (int numThreads, int initTimeMs)
|
|
{
|
|
deMemPool* tmpPool = deMemPool_createRoot(DE_NULL, 0);
|
|
deThreadArray* threads = tmpPool ? deThreadArray_create(tmpPool) : DE_NULL;
|
|
int threadNdx;
|
|
|
|
resetTestState();
|
|
|
|
for (threadNdx = 0; threadNdx < numThreads; threadNdx++)
|
|
{
|
|
deThread thread = deThread_create(singletonTestThread, &initTimeMs, DE_NULL);
|
|
DE_TEST_ASSERT(thread);
|
|
DE_TEST_ASSERT(deThreadArray_pushBack(threads, thread));
|
|
}
|
|
|
|
/* All threads created - let them do initialization. */
|
|
deMemoryReadWriteFence();
|
|
s_singletonInitLock = DE_TRUE;
|
|
deMemoryReadWriteFence();
|
|
|
|
for (threadNdx = 0; threadNdx < numThreads; threadNdx++)
|
|
{
|
|
deThread thread = deThreadArray_get(threads, threadNdx);
|
|
DE_TEST_ASSERT(deThread_join(thread));
|
|
deThread_destroy(thread);
|
|
}
|
|
|
|
/* Verify results. */
|
|
DE_TEST_ASSERT(s_testSingletonInitialized);
|
|
DE_TEST_ASSERT(s_testSingletonInitCount == 1);
|
|
|
|
deMemPool_destroy(tmpPool);
|
|
}
|
|
|
|
void deSingleton_selfTest (void)
|
|
{
|
|
const struct
|
|
{
|
|
int numThreads;
|
|
int initTimeMs;
|
|
int repeatCount;
|
|
} cases[] =
|
|
{
|
|
/* #threads time #repeat */
|
|
{ 1, -1, 5 },
|
|
{ 1, 1, 5 },
|
|
{ 2, -1, 20 },
|
|
{ 2, 1, 20 },
|
|
{ 4, -1, 20 },
|
|
{ 4, 1, 20 },
|
|
{ 4, 5, 20 }
|
|
};
|
|
int caseNdx;
|
|
|
|
for (caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
|
|
{
|
|
int numThreads = cases[caseNdx].numThreads;
|
|
int initTimeMs = cases[caseNdx].initTimeMs;
|
|
int repeatCount = cases[caseNdx].repeatCount;
|
|
int subCaseNdx;
|
|
|
|
for (subCaseNdx = 0; subCaseNdx < repeatCount; subCaseNdx++)
|
|
runSingletonThreadedTest(numThreads, initTimeMs);
|
|
}
|
|
}
|