/*************************************************************************\ * Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ /* epicsThreadTest.cpp */ #include #include #include #include #include #include #include #include #include "epicsThread.h" #include "epicsTime.h" #include "errlog.h" #include "epicsUnitTest.h" #include "testMain.h" static epicsThreadPrivate privateKey; class myThread: public epicsThreadRunable { public: myThread(int arg,const char *name); virtual ~myThread(); virtual void run(); epicsThread thread; epicsEvent startEvt; private: int *argvalue; }; myThread::myThread(int arg,const char *name) : thread(*this,name,epicsThreadGetStackSize(epicsThreadStackSmall),50+arg), argvalue(0) { argvalue = new int; *argvalue = arg; thread.start(); } myThread::~myThread() {delete argvalue;} void myThread::run() { startEvt.signal(); int *pset = argvalue; privateKey.set(argvalue); int *pget = privateKey.get(); testOk1(pget == pset); epicsThreadId self = epicsThreadGetIdSelf(); testOk1(thread.getPriority() == epicsThreadGetPriority(self)); } typedef struct info { int isOkToBlock; int didSomething; } info; extern "C" { static void thread(void *arg) { info *pinfo = (info *)arg; epicsThreadSetOkToBlock(pinfo->isOkToBlock); testOk(epicsThreadIsOkToBlock() == pinfo->isOkToBlock, "%s epicsThreadIsOkToBlock() = %d", epicsThreadGetNameSelf(), pinfo->isOkToBlock); pinfo->didSomething = 1; } } MAIN(epicsThreadTest) { testPlan(11); unsigned int ncpus = epicsThreadGetCPUs(); testDiag("System has %u CPUs", ncpus); testOk1(ncpus > 0); const int ntasks = 3; myThread *myThreads[ntasks]; int startPriority = 0; for (int i = 0; i < ntasks; i++) { char name[10]; sprintf(name, "t%d", i); myThreads[i] = new myThread(i, name); if (i == 0) startPriority = myThreads[i]->thread.getPriority(); myThreads[i]->thread.setPriority(startPriority + i); } for (int i = 0; i < ntasks; i++) { myThreads[i]->startEvt.wait(); myThreads[i]->thread.exitWait(); delete myThreads[i]; } epicsThreadOpts opts; epicsThreadOptsDefaults(&opts); opts.priority = 50; opts.joinable = 1; info infoA = {0, 0}; epicsThreadId threadA = epicsThreadCreateOpt("threadA", thread, &infoA, &opts); info infoB = {1, 0}; epicsThreadId threadB = epicsThreadCreateOpt("threadB", thread, &infoB, &opts); // join B first to better our chance of detecting if it never runs. epicsThreadMustJoin(threadB); testOk1(infoB.didSomething); epicsThreadMustJoin(threadA); testOk1(infoA.didSomething); return testDone(); }