diff --git a/src/libCom/error/errlog.c b/src/libCom/error/errlog.c index bfae98fc4..40cbb7bc1 100644 --- a/src/libCom/error/errlog.c +++ b/src/libCom/error/errlog.c @@ -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; diff --git a/src/libCom/osi/os/vxWorks/osdPoolStatus.c b/src/libCom/osi/os/vxWorks/osdPoolStatus.c index f60aedb07..c8418a236 100644 --- a/src/libCom/osi/os/vxWorks/osdPoolStatus.c +++ b/src/libCom/osi/os/vxWorks/osdPoolStatus.c @@ -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 ); } /* diff --git a/src/libCom/test/Makefile b/src/libCom/test/Makefile index d348b8ae8..255d07fd1 100644 --- a/src/libCom/test/Makefile +++ b/src/libCom/test/Makefile @@ -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 diff --git a/src/libCom/test/epicsRunLibComTests.c b/src/libCom/test/epicsRunLibComTests.c index a27dd6bc0..9445c99cb 100644 --- a/src/libCom/test/epicsRunLibComTests.c +++ b/src/libCom/test/epicsRunLibComTests.c @@ -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 #include @@ -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); diff --git a/src/libCom/test/epicsThreadOnceTest.c b/src/libCom/test/epicsThreadOnceTest.c new file mode 100644 index 000000000..0b1398a34 --- /dev/null +++ b/src/libCom/test/epicsThreadOnceTest.c @@ -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 +#include + +#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(); +}