Added libCom/test code for epicsThreadOnce() implementations.

Also fixed subsystems that were not using epicsThreadOnce correctly.
This commit is contained in:
Andrew Johnson
2010-04-26 15:48:42 -05:00
parent c5a27fa32e
commit 6ece3235c9
5 changed files with 127 additions and 22 deletions

View File

@@ -445,7 +445,7 @@ epicsShareFunc int epicsShareAPI errlogInit2(int bufsize, int maxMsgSize)
static epicsThreadOnceId errlogOnceFlag = EPICS_THREAD_ONCE_INIT;
struct initArgs config;
if (errlogOnceFlag > 0 && pvtData.atExit)
if (pvtData.atExit)
return 0;
if (bufsize < BUFFER_SIZE) bufsize = BUFFER_SIZE;

View File

@@ -3,8 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
@@ -16,7 +15,7 @@
#include "osiPoolStatus.h"
/*
* It turns out that memPartInfoGet() nad memFindMax() are very CPU intensive on vxWorks
* It turns out that memPartInfoGet() and memFindMax() are very CPU intensive on vxWorks
* so we must spawn off a thread that periodically polls. Although this isnt 100% safe, I
* dont see what else to do.
*
@@ -32,19 +31,15 @@ static size_t osdMaxBlockSize = 0;
static void osdSufficentSpaceInPoolQuery ()
{
int temp = memFindMax ();
if ( temp > 0 ) {
osdMaxBlockSize = (size_t) temp;
}
else {
osdMaxBlockSize = 0;
}
osdMaxBlockSize = ( temp > 0 ) ? (size_t) temp : 0;
}
static void osdSufficentSpaceInPoolPoll ( void *pArgIn )
{
while ( 1 ) {
osdSufficentSpaceInPoolQuery ();
epicsThreadSleep ( 1.0 );
osdSufficentSpaceInPoolQuery ();
}
}
@@ -54,14 +49,9 @@ static void osdSufficentSpaceInPoolInit ( void *pArgIn )
osdSufficentSpaceInPoolQuery ();
id = epicsShareAPI epicsThreadCreate ( "poolPoll", epicsThreadPriorityMedium,
epicsThreadGetStackSize ( epicsThreadStackSmall ), osdSufficentSpaceInPoolPoll, 0 );
if ( id ) {
osdMaxBlockOnceler = 1;
}
else {
epicsThreadSleep ( 0.1 );
}
id = epicsThreadCreate ( "poolPoll", epicsThreadPriorityMedium,
epicsThreadGetStackSize ( epicsThreadStackSmall ),
osdSufficentSpaceInPoolPoll, 0 );
}
/*

View File

@@ -57,6 +57,11 @@ epicsThreadTest_SRCS += epicsThreadTest.cpp
testHarness_SRCS += epicsThreadTest.cpp
TESTS += epicsThreadTest
TESTPROD_HOST += epicsThreadOnceTest
epicsThreadOnceTest_SRCS += epicsThreadOnceTest.c
testHarness_SRCS += epicsThreadOnceTest.c
TESTS += epicsThreadOnceTest
TESTPROD_HOST += epicsThreadPriorityTest
epicsThreadPriorityTest_SRCS += epicsThreadPriorityTest.cpp
testHarness_SRCS += epicsThreadPriorityTest.cpp

View File

@@ -7,9 +7,6 @@
/*
* Run libCom tests as a batch
*
* This is part of the work being done to provide a unified set of automated
* tests for EPICS. Many more changes will be forthcoming.
*/
#include <stdio.h>
#include <epicsThread.h>
@@ -27,6 +24,7 @@ int epicsMessageQueueTest(void);
int epicsMutexTest(void);
int epicsStdioTest(void);
int epicsStringTest(void);
int epicsThreadOnceTest(void);
int epicsThreadPriorityTest(void);
int epicsThreadPrivateTest(void);
int epicsTimeTest(void);
@@ -73,6 +71,8 @@ void epicsRunLibComTests(void)
runTest(epicsStringTest);
runTest(epicsThreadOnceTest);
runTest(epicsThreadPriorityTest);
runTest(epicsThreadPrivateTest);

View File

@@ -0,0 +1,110 @@
/*************************************************************************\
* Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* $Id$ */
#include <stdio.h>
#include <string.h>
#include "epicsEvent.h"
#include "epicsExit.h"
#include "epicsMutex.h"
#include "epicsThread.h"
#include "epicsUnitTest.h"
#include "testMain.h"
#define NUM_ONCE_THREADS 8
epicsThreadOnceId onceFlag = EPICS_THREAD_ONCE_INIT;
epicsThreadOnceId twiceFlag = EPICS_THREAD_ONCE_INIT;
epicsMutexId lock;
epicsEventId go;
int runCount = 0;
int initCount = 0;
char initBy[20];
int doneCount = 0;
void onceInit(void *ctx)
{
initCount++;
strcpy(initBy, epicsThreadGetNameSelf());
}
void onceThread(void *ctx)
{
epicsMutexMustLock(lock);
runCount++;
epicsMutexUnlock(lock);
epicsEventMustWait(go);
epicsEventSignal(go);
epicsThreadOnce(&onceFlag, onceInit, ctx);
testOk(initCount == 1, "%s: initCount = %d",
epicsThreadGetNameSelf(), initCount);
epicsMutexMustLock(lock);
doneCount++;
epicsMutexUnlock(lock);
}
void recurseInit(void);
void onceRecurse(void *ctx)
{
recurseInit();
}
void recurseInit(void)
{
epicsThreadOnce(&twiceFlag, onceRecurse, 0);
}
void recurseThread(void *ctx)
{
recurseInit();
testFail("Recursive epicsThreadOnce() not detected");
}
MAIN(epicsThreadOnceTest)
{
int i;
epicsThreadId tid;
testPlan(3 + NUM_ONCE_THREADS);
go = epicsEventMustCreate(epicsEventEmpty);
lock = epicsMutexMustCreate();
for (i = 0; i < NUM_ONCE_THREADS; i++) {
char name[20];
sprintf(name, "once-%d", i);
epicsThreadCreate(name, epicsThreadPriorityMedium,
epicsThreadGetStackSize(epicsThreadStackSmall),
onceThread, 0);
}
epicsThreadSleep(0.1);
testOk(runCount == NUM_ONCE_THREADS, "runCount = %d", runCount);
epicsEventSignal(go);
epicsThreadSleep(0.1);
testOk(doneCount == NUM_ONCE_THREADS, "doneCount = %d", doneCount);
testDiag("init was run by %s", initBy);
tid = epicsThreadCreate("recurse", epicsThreadPriorityMedium,
epicsThreadGetStackSize(epicsThreadStackSmall),
recurseThread, 0);
do {
epicsThreadSleep(0.1);
} while (!epicsThreadIsSuspended(tid));
testPass("Recursive epicsThreadOnce() detected");
return testDone();
}