Files
pcas/src/libCom/test/epicsAtomicTest.c
2011-08-05 11:14:37 -06:00

119 lines
3.9 KiB
C

#include <stdlib.h>
#include <assert.h>
#include "epicsAtomic.h"
#include "epicsTime.h"
#include "epicsThread.h"
#include "epicsUnitTest.h"
#include "testMain.h"
typedef struct TestDataIncrDecr {
size_t m_testValue;
size_t m_testIterations;
} TestDataIncrDecr;
static void incr ( void *arg )
{
TestDataIncrDecr * const pTestData = (TestDataIncrDecr *) arg;
epicsAtomicIncrSizeT ( & pTestData->m_testValue );
epicsAtomicIncrSizeT ( & pTestData->m_testIterations );
}
static void decr ( void *arg )
{
TestDataIncrDecr * const pTestData = (TestDataIncrDecr *) arg;
epicsAtomicDecrSizeT ( & pTestData->m_testValue );
epicsAtomicIncrSizeT ( & pTestData->m_testIterations );
}
typedef struct TestDataTNS {
unsigned m_testValue;
size_t m_testIterationsSet;
size_t m_testIterationsNotSet;
} TestDataTNS;
int isModulo ( size_t N, size_t n )
{
return ( n % N ) == 0u;
}
static void tns ( void *arg )
{
TestDataTNS * const pTestData = (TestDataTNS *) arg;
/*
* intentionally waste cpu and maximize
* contention for the shared data
*/
epicsAtomicIncrSizeT ( & pTestData->m_testIterationsNotSet );
while ( ! epicsAtomicTestAndSetUIntT ( & pTestData->m_testValue ) ) {
}
epicsAtomicDecrSizeT ( & pTestData->m_testIterationsNotSet );
epicsAtomicSetUIntT ( & pTestData->m_testValue, 0u );
epicsAtomicIncrSizeT ( & pTestData->m_testIterationsSet );
}
MAIN(osiAtomicTest)
{
const unsigned int stackSize =
epicsThreadGetStackSize ( epicsThreadStackSmall );
testPlan(8);
{
static const size_t N = 100;
size_t i;
TestDataIncrDecr testData = { 0, N };;
epicsAtomicSetSizeT ( & testData.m_testValue, N );
testOk ( epicsAtomicGetSizeT ( & testData.m_testValue ) == N,
"set/get %u", testData.m_testValue );
epicsAtomicSetSizeT ( & testData.m_testIterations, 0u );
testOk ( epicsAtomicGetSizeT ( & testData.m_testIterations ) == 0u,
"set/get %u", testData.m_testIterations );
for ( i = 0u; i < N; i++ ) {
epicsThreadCreate ( "incr",
50, stackSize, incr, & testData );
epicsThreadCreate ( "decr",
50, stackSize, decr, & testData );
}
while ( testData.m_testIterations < 2 * N ) {
epicsThreadSleep ( 0.01 );
}
testOk ( epicsAtomicGetSizeT ( & testData.m_testIterations ) == 2 * N,
"incr/decr iterations %u",
testData.m_testIterations );
testOk ( epicsAtomicGetSizeT ( & testData.m_testValue ) == N,
"incr/decr final value %u",
testData.m_testValue );
}
{
static const size_t N = 10;
size_t i;
TestDataTNS testData = { 1, N, N };
epicsAtomicSetSizeT ( & testData.m_testIterationsSet, 0u );
testOk ( epicsAtomicGetSizeT ( & testData.m_testIterationsSet ) == 0u,
"set/get %u", testData.m_testIterationsSet );
epicsAtomicSetSizeT ( & testData.m_testIterationsNotSet, 0u );
testOk ( epicsAtomicGetSizeT ( & testData.m_testIterationsNotSet ) == 0u,
"set/get %u", testData.m_testIterationsNotSet );
for ( i = 0u; i < N; i++ ) {
epicsThreadCreate ( "tns",
50, stackSize, tns, & testData );
}
epicsAtomicSetUIntT ( & testData.m_testValue, 0u );
while ( testData.m_testIterationsSet < N ) {
epicsThreadSleep ( 0.01 );
}
testOk ( epicsAtomicGetSizeT ( & testData.m_testIterationsSet ) == N,
"test and set iterations %u",
testData.m_testIterationsSet );
testOk ( epicsAtomicGetSizeT ( & testData.m_testIterationsNotSet ) == 0u,
"test and set not-set tracking = %u",
testData.m_testIterationsNotSet );
}
return testDone();
}