From f110f470119b22366ebebe92c6717b444fefa280 Mon Sep 17 00:00:00 2001 From: Marty Kraimer Date: Fri, 15 Dec 2000 15:05:48 +0000 Subject: [PATCH] replace osiRing with epicsRingPointer --- src/db/callback.c | 26 ++--- src/db/dbScan.c | 17 ++-- src/libCom/Makefile | 9 +- src/libCom/ring/epicsRingPointer.cpp | 78 +++++++++++++++ src/libCom/ring/epicsRingPointer.h | 136 +++++++++++++++++++++++++++ 5 files changed, 237 insertions(+), 29 deletions(-) create mode 100644 src/libCom/ring/epicsRingPointer.cpp create mode 100644 src/libCom/ring/epicsRingPointer.h diff --git a/src/db/callback.c b/src/db/callback.c index ed56b86b3..c9349c864 100644 --- a/src/db/callback.c +++ b/src/db/callback.c @@ -22,7 +22,7 @@ of this distribution. #include "osiThread.h" #include "osiInterrupt.h" #include "osiTimer.h" -#include "osiRing.h" +#include "epicsRingPointer.h" #include "tsStamp.h" #include "errlog.h" #include "dbStaticLib.h" @@ -41,7 +41,7 @@ of this distribution. int callbackQueueSize = 2000; static semBinaryId callbackSem[NUM_CALLBACK_PRIORITIES]; -static ringId callbackQ[NUM_CALLBACK_PRIORITIES]; +static epicsRingPointerId callbackQ[NUM_CALLBACK_PRIORITIES]; static threadId callbackTaskId[NUM_CALLBACK_PRIORITIES]; static int ringOverflow[NUM_CALLBACK_PRIORITIES]; static void callbackInitPvt(void *); @@ -92,7 +92,7 @@ void epicsShareAPI callbackInit() void epicsShareAPI callbackRequest(CALLBACK *pcallback) { int priority = pcallback->priority; - int nput; + int pushOK; int lockKey; if(priority<0 || priority>=(NUM_CALLBACK_PRIORITIES)) { @@ -101,9 +101,9 @@ void epicsShareAPI callbackRequest(CALLBACK *pcallback) } if(ringOverflow[priority]) return; lockKey = interruptLock(); - nput = ringPut(callbackQ[priority],(void *)&pcallback,sizeof(pcallback)); + pushOK = epicsRingPointerPush(callbackQ[priority],(void *)pcallback); interruptUnlock(lockKey); - if(nput!=sizeof(pcallback)){ + if(!pushOK) { epicsPrintf("callbackRequest ring buffer full\n"); ringOverflow[priority] = TRUE; } @@ -116,20 +116,14 @@ static void callbackTask(int *ppriority) { int priority = *ppriority; CALLBACK *pcallback; - int nget; ringOverflow[priority] = FALSE; while(TRUE) { /* wait for somebody to wake us up */ semBinaryMustTake(callbackSem[priority]); while(TRUE) { - nget = ringGet(callbackQ[priority], - (void *)&pcallback,sizeof(pcallback)); - if(nget==0) break; - if(nget!=sizeof(pcallback)) { - errMessage(0,"ringGet failed in callbackTask"); - threadSuspendSelf(); - } + if(!(pcallback = (CALLBACK *) + epicsRingPointerPop(callbackQ[priority]))) break; ringOverflow[priority] = FALSE; (*pcallback->callback)(pcallback); } @@ -150,8 +144,8 @@ static void start(int ind) errMessage(0,"callback start called with illegal priority\n"); return; } - if((callbackQ[ind]=ringCreate(sizeof(CALLBACK *)*callbackQueueSize)) == 0) - errMessage(0,"ringCreate failed while starting a callback task"); + if((callbackQ[ind]=epicsRingPointerCreate(callbackQueueSize)) == 0) + errMessage(0,"epicsRingPointerCreate failed while starting a callback task"); sprintf(taskName,"cb%s",priorityName[ind]); callbackTaskId[ind] = threadCreate(taskName,priority, threadGetStackSize(threadStackBig),(THREADFUNC)callbackTask, @@ -170,7 +164,7 @@ static void wdCallback(void *pind) taskwdRemove(callbackTaskId[ind]); if(!callbackRestart)return; semBinaryDestroy(callbackSem[ind]); - ringDelete(callbackQ[ind]); + epicsRingPointerDelete(callbackQ[ind]); start(ind); } diff --git a/src/db/dbScan.c b/src/db/dbScan.c index dd78ef1c6..7c87eb008 100644 --- a/src/db/dbScan.c +++ b/src/db/dbScan.c @@ -57,7 +57,7 @@ #include "osiThread.h" #include "tsStamp.h" #include "cantProceed.h" -#include "osiRing.h" +#include "epicsRingPointer.h" #include "epicsPrint.h" #include "dbBase.h" #include "dbStaticLib.h" @@ -77,7 +77,7 @@ /* SCAN ONCE */ int onceQueueSize = 1000; static semBinaryId onceSem; -static ringId onceQ; +static epicsRingPointerId onceQ; static threadId onceTaskId; /*all other scan types */ @@ -442,12 +442,12 @@ void epicsShareAPI scanOnce(void *precord) { static int newOverflow=TRUE; int lockKey; - int nput; + int pushOK; lockKey = interruptLock(); - nput = ringPut(onceQ,(char *)&precord,sizeof(precord)); + pushOK = epicsRingPointerPush(onceQ,precord); interruptUnlock(lockKey); - if(nput!=sizeof(precord)) { + if(!pushOK) { if(newOverflow)errMessage(0,"rngBufPut overflow in scanOnce"); newOverflow = FALSE; }else { @@ -464,10 +464,7 @@ static void onceTask(void) if(semBinaryTake(onceSem)!=semTakeOK) errlogPrintf("dbScan: semBinaryTake returned error in onceTask"); while(TRUE) { - int nbytes = ringGet(onceQ,(void *)&precord,sizeof(precord)); - if(nbytes==0) break; - if(nbytes!=sizeof(precord)) - errMessage(0,"dbScan: rngBufGet returned error in onceTask"); + if(!(precord = epicsRingPointerPop(onceQ))) break; dbScanLock(precord); dbProcess(precord); dbScanUnlock(precord); @@ -483,7 +480,7 @@ int epicsShareAPI scanOnceSetQueueSize(int size) static void initOnce(void) { - if((onceQ = ringCreate(sizeof(void *) * onceQueueSize))==NULL){ + if((onceQ = epicsRingPointerCreate(onceQueueSize))==NULL){ cantProceed("dbScan: initOnce failed"); } onceSem=semBinaryMustCreate(semEmpty); diff --git a/src/libCom/Makefile b/src/libCom/Makefile index 09f6fea55..6ec9a7bac 100644 --- a/src/libCom/Makefile +++ b/src/libCom/Makefile @@ -12,6 +12,12 @@ SRC_DIRS += $(LIBCOM)/bucketLib INC += bucketLib.h SRCS += bucketLib.c +SRC_DIRS += $(LIBCOM)/ring +#following needed for locating epicsRingPointer.h +USR_CFLAGS += -I$(LIBCOM)/ring +INC += epicsRingPointer.h +SRCS += epicsRingPointer.cpp + SRC_DIRS += $(LIBCOM)/calc #following needed for locating postfixPvt.h and sCalcPostfixPvt.h USR_CFLAGS += -I$(LIBCOM)/calc @@ -110,8 +116,6 @@ INC += osiSock.h INC += osdSock.h INC += osiInterrupt.h INC += osdInterrupt.h -INC += osiRing.h -INC += osdRing.h INC += osiSem.h INC += osdSem.h INC += epicsAssert.h @@ -138,7 +142,6 @@ SRCS += osdAssert.c SRCS += osdFindGlobalSymbol.c SRCS += osdInterrupt.c SRCS += osdPoolStatus.c -SRCS += osdRing.c SRCS += osdSem.c SRCS += osdThread.c SRCS += osiThread.cpp diff --git a/src/libCom/ring/epicsRingPointer.cpp b/src/libCom/ring/epicsRingPointer.cpp new file mode 100644 index 000000000..ed47782b6 --- /dev/null +++ b/src/libCom/ring/epicsRingPointer.cpp @@ -0,0 +1,78 @@ +/*epicsRingPointer.cpp*/ +/* Author: Marty Kraimer Date: 13OCT2000 */ + +/********************COPYRIGHT NOTIFICATION********************************** +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +****************************************************************************/ +#include +#include +#include +#include +#include + +#define epicsExportSharedSymbols +#include "epicsRingPointer.h" +typedef epicsRingPointer voidPointer; + + +epicsShareFunc epicsRingPointerId epicsShareAPI epicsRingPointerCreate(int size) +{ + voidPointer *pvoidPointer = new voidPointer(size); + return(reinterpret_cast(pvoidPointer)); +} + +epicsShareFunc void epicsShareAPI epicsRingPointerDelete(epicsRingPointerId id) +{ + voidPointer *pvoidPointer = reinterpret_cast(id); + delete pvoidPointer; +} + +epicsShareFunc void* epicsShareAPI epicsRingPointerPop(epicsRingPointerId id) +{ + voidPointer *pvoidPointer = reinterpret_cast(id); + return((void *)(pvoidPointer->pop())); +} + +epicsShareFunc int epicsShareAPI epicsRingPointerPush(epicsRingPointerId id, void *p) +{ + voidPointer *pvoidPointer = reinterpret_cast(id); + return((pvoidPointer->push(p) ? 1 : 0)); +} + +epicsShareFunc void epicsShareAPI epicsRingPointerFlush(epicsRingPointerId id) +{ + voidPointer *pvoidPointer = reinterpret_cast(id); + pvoidPointer->flush(); +} + +epicsShareFunc int epicsShareAPI epicsRingPointerGetFree(epicsRingPointerId id) +{ + voidPointer *pvoidPointer = reinterpret_cast(id); + return(pvoidPointer->getFree()); +} + +epicsShareFunc int epicsShareAPI epicsRingPointerGetUsed(epicsRingPointerId id) +{ + voidPointer *pvoidPointer = reinterpret_cast(id); + return(pvoidPointer->getUsed()); +} + +epicsShareFunc int epicsShareAPI epicsRingPointerSize(epicsRingPointerId id) +{ + voidPointer *pvoidPointer = reinterpret_cast(id); + return(pvoidPointer->getSize()); +} + +epicsShareFunc int epicsShareAPI epicsRingPointerIsEmpty(epicsRingPointerId id) +{ + voidPointer *pvoidPointer = reinterpret_cast(id); + return((pvoidPointer->isEmpty()) ? 1 : 0); +} + +epicsShareFunc int epicsShareAPI epicsRingPointerIsFull(epicsRingPointerId id) +{ + voidPointer *pvoidPointer = reinterpret_cast(id); + return((pvoidPointer->isFull()) ? 1 : 0); +} diff --git a/src/libCom/ring/epicsRingPointer.h b/src/libCom/ring/epicsRingPointer.h new file mode 100644 index 000000000..ff0254417 --- /dev/null +++ b/src/libCom/ring/epicsRingPointer.h @@ -0,0 +1,136 @@ +/*epicsRingPointer.h */ + +/* Author: Marty Kraimer Date: 15JUL99 */ + +/********************COPYRIGHT NOTIFICATION********************************** +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +****************************************************************************/ + +#ifndef INCepicsRingPointerh +#define INCepicsRingPointerh + +/* NOTES + If there is only one writer it is not necessary to lock push + If there is a single reader it is not necessary to lock pop +*/ + +#include "shareLib.h" + +#ifdef __cplusplus +template class epicsRingPointer +{ +public: + epicsRingPointer(int size); + ~epicsRingPointer(); + bool push(T *p); + T* pop(); + void flush(); + int getFree() const; + int getUsed() const; + int getSize() const; + bool isEmpty() const; + bool isFull() const; +private: + int nextPush; + int nextPop; + int size; + T **buffer; + // copy constructor and assignment operator not allowed + epicsRingPointer(const epicsRingPointer &); + epicsRingPointer& operator=(const epicsRingPointer &); +}; +#endif /*__cplusplus */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void *epicsRingPointerId; + +epicsShareFunc epicsRingPointerId epicsShareAPI epicsRingPointerCreate(int size); +epicsShareFunc void epicsShareAPI epicsRingPointerDelete(epicsRingPointerId id); +/*ringPointerPush returns (0,1) if p (was not, was) put on ring*/ +epicsShareFunc int epicsShareAPI epicsRingPointerPush(epicsRingPointerId id,void *p); +/*ringPointerPop returns 0 if ring is empty*/ +epicsShareFunc void* epicsShareAPI epicsRingPointerPop(epicsRingPointerId id) ; +epicsShareFunc void epicsShareAPI epicsRingPointerFlush(epicsRingPointerId id); +epicsShareFunc int epicsShareAPI epicsRingPointerGetFree(epicsRingPointerId id); +epicsShareFunc int epicsShareAPI epicsRingPointerGetUsed(epicsRingPointerId id); +epicsShareFunc int epicsShareAPI epicsRingPointerGetSize(epicsRingPointerId id); +epicsShareFunc int epicsShareAPI epicsRingPointerIsEmpty(epicsRingPointerId id); +epicsShareFunc int epicsShareAPI epicsRingPointerIsFull(epicsRingPointerId id); + +#ifdef __cplusplus +} +#endif + +/* Following is implementation */ +/* Algorithm note +* Space is allocated for one additional element. +* A put request is rejected if the it would cause nextPush to equal nextPop +* The algorithm does not require locking puts for a single writer +* or locking of gets for a single reader +*/ +#ifdef __cplusplus + +template inline epicsRingPointer::epicsRingPointer(int sz) +: nextPush(0), nextPop(0), size(sz+1), buffer(new T* [sz+1]) {} + +template inline epicsRingPointer::~epicsRingPointer() +{delete [] buffer;} + +template inline bool epicsRingPointer::push(T *p) +{ + int newNext = nextPush +1; + if(newNext>=size) newNext=0; + if(newNext==nextPop) return(false); + buffer[nextPush] = p; + nextPush = newNext; + return(true); +} + +template inline T* epicsRingPointer::pop() +{ + if(nextPop == nextPush) return(0); + T*p = buffer[nextPop]; + int newNext= nextPop; + ++newNext; + if(newNext >=size) newNext = 0; + nextPop = newNext; + return(p); +} + +template inline void epicsRingPointer::flush() +{ nextPop = nextPush = 0;} + +template inline int epicsRingPointer::getFree() const +{ + int n = nextPop - nextPush - 1; + if (n < 0) n += size; + return n; +} + +template inline int epicsRingPointer::getUsed() const +{ + int n = nextPush - nextPop; + if (n < 0) n += size; + return n; +} + +template inline int epicsRingPointer::getSize() const +{return(size-1);} + +template inline bool epicsRingPointer::isEmpty() const +{return(nextPush==nextPop);} + +template inline bool epicsRingPointer::isFull() const +{ + int count = nextPush - nextPop +1; + return((count == 0) || (count == size)); +} + +#endif /* __cplusplus */ + +#endif /* INCepicsRingPointerh */