From 2ba2b90b06b21ed0dbcf0fa29278104b7efc9d3c Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Mon, 5 Jan 2015 16:26:47 -0500 Subject: [PATCH] dbScan: add scanOnce3() w/ completion callback --- src/ioc/db/dbScan.c | 55 ++++++++++++++++++++++++++++++++------------- src/ioc/db/dbScan.h | 8 ++++--- 2 files changed, 44 insertions(+), 19 deletions(-) diff --git a/src/ioc/db/dbScan.c b/src/ioc/db/dbScan.c index 272b185b0..3cd93da1a 100644 --- a/src/ioc/db/dbScan.c +++ b/src/ioc/db/dbScan.c @@ -26,10 +26,9 @@ #include "ellLib.h" #include "epicsEvent.h" #include "epicsExit.h" -#include "epicsInterrupt.h" #include "epicsMutex.h" #include "epicsPrint.h" -#include "epicsRingPointer.h" +#include "epicsRingBytes.h" #include "epicsStdio.h" #include "epicsStdlib.h" #include "epicsString.h" @@ -64,7 +63,7 @@ static volatile enum ctl scanCtl; static int onceQueueSize = 1000; static epicsEventId onceSem; -static epicsRingPointerId onceQ; +static epicsRingBytesId onceQ; static epicsThreadId onceTaskId; static void *exitOnce; @@ -172,7 +171,7 @@ void scanShutdown(void) deletePeriodic(); ioscanDestroy(); - epicsRingPointerDelete(onceQ); + epicsRingBytesDelete(onceQ); epicsEventDestroy(startStopEvent); epicsEventDestroy(onceSem); @@ -609,15 +608,27 @@ void scanIoSetComplete(IOSCANPVT piosh, io_scan_complete cb, void *arg) piosh->arg = arg; } -void scanOnce(struct dbCommon *precord) +int scanOnce(struct dbCommon *precord) { + return scanOnce3(precord, NULL, NULL); +} + +typedef struct { + struct dbCommon *prec; + once_complete cb; + void *usr; +} onceEntry; + +int scanOnce3(struct dbCommon *precord, once_complete cb, void *usr) { static int newOverflow = TRUE; - int lockKey; + onceEntry ent; int pushOK; - lockKey = epicsInterruptLock(); - pushOK = epicsRingPointerPush(onceQ, precord); - epicsInterruptUnlock(lockKey); + ent.prec = precord; + ent.cb = cb; + ent.usr = usr; + + pushOK = epicsRingBytesPut(onceQ, (void*)&ent, sizeof(ent)); if (!pushOK) { if (newOverflow) errlogPrintf("scanOnce: Ring buffer overflow\n"); @@ -626,6 +637,8 @@ void scanOnce(struct dbCommon *precord) newOverflow = TRUE; } epicsEventSignal(onceSem); + + return !pushOK; } static void onceTask(void *arg) @@ -634,14 +647,24 @@ static void onceTask(void *arg) epicsEventSignal(startStopEvent); while (TRUE) { - void *precord; epicsEventMustWait(onceSem); - while ((precord = epicsRingPointerPop(onceQ))) { - if (precord == &exitOnce) goto shutdown; - dbScanLock(precord); - dbProcess(precord); - dbScanUnlock(precord); + while(1) { + onceEntry ent; + int bytes = epicsRingBytesGet(onceQ, (void*)&ent, sizeof(ent)); + if(bytes==0) + break; + if(bytes!=sizeof(ent)) { + errlogPrintf("onceTask: received incomplete %d of %u\n", + bytes, (unsigned)sizeof(ent)); + continue; /* what to do? */ + } else if (ent.prec == (void*)&exitOnce) goto shutdown; + + dbScanLock(ent.prec); + dbProcess(ent.prec); + dbScanUnlock(ent.prec); + if(ent.cb) + ent.cb(ent.usr, ent.prec); } } @@ -658,7 +681,7 @@ int scanOnceSetQueueSize(int size) static void initOnce(void) { - if ((onceQ = epicsRingPointerCreate(onceQueueSize)) == NULL) { + if ((onceQ = epicsRingBytesLockedCreate(sizeof(onceEntry)*onceQueueSize)) == NULL) { cantProceed("initOnce: Ring buffer create failed\n"); } onceSem = epicsEventMustCreate(epicsEventEmpty); diff --git a/src/ioc/db/dbScan.h b/src/ioc/db/dbScan.h index 8bd2bba22..fffae23d1 100644 --- a/src/ioc/db/dbScan.h +++ b/src/ioc/db/dbScan.h @@ -39,10 +39,11 @@ struct ioscan_head; typedef struct ioscan_head *IOSCANPVT; typedef struct event_list *EVENTPVT; -typedef void (*io_scan_complete)(void *usr, IOSCANPVT, int prio); - struct dbCommon; +typedef void (*io_scan_complete)(void *usr, IOSCANPVT, int prio); +typedef void (*once_complete)(void *usr, struct dbCommon*); + epicsShareFunc long scanInit(void); epicsShareFunc void scanRun(void); epicsShareFunc void scanPause(void); @@ -54,7 +55,8 @@ epicsShareFunc void post_event(int event) EPICS_DEPRECATED; epicsShareFunc void scanAdd(struct dbCommon *); epicsShareFunc void scanDelete(struct dbCommon *); epicsShareFunc double scanPeriod(int scan); -epicsShareFunc void scanOnce(struct dbCommon *); +epicsShareFunc int scanOnce(struct dbCommon *); +epicsShareFunc int scanOnce3(struct dbCommon *, once_complete cb, void *usr); epicsShareFunc int scanOnceSetQueueSize(int size); /*print periodic lists*/