/*************************************************************************\ * Copyright (c) 2002 The University of Chicago, 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 Versions 3.13.7 * and higher are distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ /* epicsEventTest.cpp */ /* Author: Marty Kraimer Date: 26JAN2000 */ /* timeout accuracy tests by Jeff Hill */ #include #include #include #include #include #include #include #include #include "epicsThread.h" #include "epicsEvent.h" #include "epicsMutex.h" #include "epicsRingPointer.h" #include "epicsTime.h" #include "errlog.h" typedef struct info { epicsEventId event; epicsMutexId lockRing; int quit; epicsRingPointerId ring; }info; extern "C" { static void consumer(void *arg) { info *pinfo = (info *)arg; time_t tp; epicsThreadId idSelf = epicsThreadGetIdSelf(); printf("consumer %p starting time %ld\n",idSelf,time(&tp)); while(1) { epicsEventWaitStatus status; if(pinfo->quit) { printf("consumer %p returning time %ld\n", idSelf,time(&tp)); return; } status = epicsEventWait(pinfo->event); if(status!=epicsEventWaitOK) { printf("task %p epicsEventWait returned %d time %ld\n", idSelf,(int)status,time(&tp)); } while(epicsRingPointerGetUsed(pinfo->ring)>=2) { epicsRingPointerId message[2]; int i; for(i=0; i<2; i++) { if(!(message[i]=epicsRingPointerPop(pinfo->ring))) printf("consumer error\n"); } if(message[0]!=message[1]) { printf("consumer error message %p %p\n",message[0],message[1]); } else { printf("consumer message from %p\n",message[0]); } } } } static void producer(void *arg) { info *pinfo = (info *)arg; time_t tp; epicsThreadId idSelf = epicsThreadGetIdSelf(); int ntimes=0; printf("producer %p starting time %ld\n",idSelf,time(&tp)); while(1) { epicsMutexLockStatus status; ++ntimes; if(pinfo->quit) { printf("producer %p returning time %ld\n", idSelf,time(&tp)); return; } status = epicsMutexLock(pinfo->lockRing); if(status!=epicsMutexLockOK) { printf("producer %p epicsMutexLock returned %d time %ld\n", idSelf,(int)status,time(&tp)); } if(epicsRingPointerGetFree(pinfo->ring)>=2) { int i; for(i=0; i<2; i++) { if(!epicsRingPointerPush(pinfo->ring,idSelf)) printf("producer %p error\n",idSelf); if(i==0 && (ntimes%4==0)) epicsThreadSleep(.1); } printf("producer %p sending\n",idSelf); } else { printf("producer %p ring buffer is full\n",idSelf); } epicsMutexUnlock(pinfo->lockRing); epicsThreadSleep(1.0); epicsEventSignal(pinfo->event); } } } // extern "C" static double eventWaitMeasureDelayError( const epicsEventId &id, const double & delay ) { epicsTime beg = epicsTime::getCurrent(); epicsEventWaitWithTimeout ( id, delay ); epicsTime end = epicsTime::getCurrent(); double meas = end - beg; double error = fabs ( delay - meas ); printf ( "epicsEventWaitWithTimeout ( %10f ) tmo delay err %10f sec\n", delay, error ); return error; } static void eventWaitTest() { double errorSum = 0.0; epicsEventId event = epicsEventMustCreate ( epicsEventEmpty ); int i; for ( i = 0u; i < 20; i++ ) { double delay = ldexp ( 1.0 , -i ); errorSum += eventWaitMeasureDelayError ( event, delay ); } errorSum += eventWaitMeasureDelayError ( event, 0.0 ); epicsEventDestroy ( event ); printf ( "Average error %f sec\n", errorSum / ( i + 1 ) ); } extern "C" void epicsEventTest(int nthreads,int verbose) { unsigned int stackSize; epicsThreadId *id; char **name; int i; info *pinfo; epicsEventId event; int status; time_t tp; int errVerboseSave = errVerbose; eventWaitTest(); errVerbose = verbose; event = epicsEventMustCreate(epicsEventEmpty); printf("calling epicsEventWaitWithTimeout(event,2.0) time %ld\n",time(&tp)); status = epicsEventWaitWithTimeout(event,2.0); if(status!=epicsEventWaitTimeout) printf("status %d\n",status); printf("calling epicsEventTryWait(event) time %ld\n",time(&tp)); status = epicsEventTryWait(event); if(status!=epicsEventWaitTimeout) printf("status %d\n",status); printf("calling epicsEventSignal() time %ld\n",time(&tp)); epicsEventSignal(event); printf("calling epicsEventWaitWithTimeout(event,2.0) time %ld\n",time(&tp)); status = epicsEventWaitWithTimeout(event,2.0); if(status) printf("status %d\n",status); printf("calling epicsEventSignal() time %ld\n",time(&tp)); epicsEventSignal(event); printf("calling epicsEventTryWait(event) time %ld\n",time(&tp)); status = epicsEventTryWait(event); if(status) printf("status %d\n",status); if(nthreads<=0) { errVerbose = errVerboseSave; return; } pinfo = (info *)calloc(1,sizeof(info)); pinfo->event = event; pinfo->lockRing = epicsMutexCreate(); pinfo->ring = epicsRingPointerCreate(1024*2); stackSize = epicsThreadGetStackSize(epicsThreadStackSmall); epicsThreadCreate("consumer",50,stackSize,consumer,pinfo); id = (epicsThreadId *)calloc(nthreads,sizeof(epicsThreadId)); name = (char **)calloc(nthreads,sizeof(char *)); for(i=0; iquit = 1; epicsThreadSleep(2.0); epicsEventSignal(pinfo->event); epicsThreadSleep(1.0); printf("semTest returning time %ld\n",time(&tp)); errVerbose = errVerboseSave; }