diff --git a/src/rec/recWait.c b/src/rec/recWait.c index f21e03629..5364ed92a 100644 --- a/src/rec/recWait.c +++ b/src/rec/recWait.c @@ -158,11 +158,13 @@ struct cbStruct { CALLBACK ioProcCb; /* callback structure for io_event scanning */ struct waitRecord *pwait; /* pointer to wait record which needs work done */ WDOG_ID wd_id; /* Watchdog used for delays */ - RECWAITCA inpMonitor[12]; /* required structures for each input variable */ + RECWAITCA inpMonitor[ARG_MAX]; /* required structures for each input variable */ RING_ID monitorQ; /* queue to store ca callback data */ + unsigned short inpMonFlag[ARG_MAX]; IOSCANPVT ioscanpvt; /* used for IO_EVENT scanning */ int outputWait; /* flag to indicate waiting to do output */ int procPending; /* flag to indicate record processing is pending */ + unsigned long tickStart; /* used for timing */ }; @@ -292,6 +294,8 @@ static long init_record(pwait,pass) piointInc = &pwait->inap; for(i=0;iinpMonFlag[i] = *piointInc; /* if valid PV AND input include flag is true ... */ if(!(*paddrValid) && (*piointInc)) { if(recWaitDebug) printf("adding monitor on input %d\n", i); @@ -402,6 +406,7 @@ static long special(paddr,after) int after; { struct waitRecord *pwait = (struct waitRecord *)(paddr->precord); + struct cbStruct *pcbst = (struct cbStruct *)pwait->cbst; int special_type = paddr->special; char *ppvn[PVN_SIZE]; struct dbAddr **ppdbAddr; /* ptr to a ptr to dbAddr */ @@ -423,24 +428,24 @@ static long special(paddr,after) for(i=0;icbst)->inpMonitor[i])); + status = recWaitCaDelete(&pcbst->inpMonitor[i]); if(status) errMessage(status,"recWaitCaDelete error"); } } return(0); } - /* check if changing any Input PV names/flags while monitored */ - if((special_type >= REC_WAIT_A) && (special_type <= REC_WAIT_L)) { - /* MON_ALWAYS if(pwait->scan == SCAN_IO_EVENT) */ - /* About to change a PV or flag, delete that particular monitor */ + /* check if changing any Input PV names while monitored */ + if((paddr->pfield >= (void *)pwait->inan) && + (paddr->pfield <= (void *)pwait->inln)) { + /* About to change a PV, delete that particular monitor */ i = special_type - REC_WAIT_A; /* index of input */ paddrValid = &pwait->inav + i; /* pointer arithmetic */ piointInc = &pwait->inap + i; /* pointer arithmetic */ /* If PV name is valid and the INxP flag is true, ... */ if(!(*paddrValid) && (*piointInc)) { if(recWaitDebug) printf("deleting monitor on input %d\n",i); - status = recWaitCaDelete(&(((struct cbStruct *)pwait->cbst)->inpMonitor[i])); + status = recWaitCaDelete(&pcbst->inpMonitor[i]); if(status) errMessage(status,"recWaitCaDelete error"); } } @@ -456,7 +461,7 @@ static long special(paddr,after) for(i=0;icbst)->inpMonitor[i])); + status = recWaitCaAdd(&pcbst->inpMonitor[i]); if(status) errMessage(status,"recWaitCaAdd error"); } } @@ -481,6 +486,7 @@ static long special(paddr,after) paddrValid = &pwait->inav + i; /* pointer arithmetic */ ppdbAddr = (struct dbAddr **)&pwait->inaa + i; /* pointer arithmetic */ *ppvn = &pwait->inan[0] + (i*PVN_SIZE); + piointInc = &pwait->inap + i; /* pointer arithmetic */ /* If the PV Name changing, do dbNameToAddr */ if(paddr->pfield==*ppvn) { @@ -489,14 +495,27 @@ static long special(paddr,after) if (odbv != *paddrValid) { db_post_events(pwait,paddrValid,DBE_VALUE); } + /* MON_ALWAYS: Should only do if SCAN_IO_EVENT), but can't now */ + /* If the INxP flag is set, add a monitor */ + if(!(*paddrValid) && (*piointInc)) { + if(recWaitDebug) printf("adding monitor on input %d\n", i); + status = recWaitCaAdd(&pcbst->inpMonitor[i]); + if(status) errMessage(status,"recWaitCaAdd error"); + } } - /* MON_ALWAYS: Should only do if SCAN_IO_EVENT), but can't now */ - /* If the INxP flag is set, add a monitor */ - piointInc = &pwait->inap + i; /* pointer arithmetic */ - if(!(*paddrValid) && (*piointInc)) { - if(recWaitDebug) printf("adding monitor on input %d\n", i); - status = recWaitCaAdd(&(((struct cbStruct *)pwait->cbst)->inpMonitor[i])); - if(status) errMessage(status,"recWaitCaAdd error"); + /* Must be the I/O INTR flag that changed. Compare to previous value */ + else { + if(!(*paddrValid) && (*piointInc) && !(pcbst->inpMonFlag[i])) { + if(recWaitDebug) printf("adding monitor on input %d\n", i); + status = recWaitCaAdd(&pcbst->inpMonitor[i]); + if(status) errMessage(status,"recWaitCaAdd error"); + } + else if(!(*paddrValid) && !(*piointInc) && (pcbst->inpMonFlag[i])) { + if(recWaitDebug) printf("deleting monitor on input %d\n", i); + status = recWaitCaDelete(&pcbst->inpMonitor[i]); + if(status) errMessage(status,"recWaitCaDelete error"); + } + pcbst->inpMonFlag[i] = *piointInc; /* keep track of current val */ } return(0); break; @@ -804,7 +823,7 @@ static void inputChanged(struct recWaitCa *pcamonitor, char inputIndex, double m if(recWaitCacheMode) { /* if record hasn't been processed or is DISABLED, don't set procPending yet */ if((pwait->stat == DISABLE_ALARM) || pwait->udf) { - if(recWaitDebug) printf("queuing monitor (cached)\n"); + if(recWaitDebug>=5) printf("queuing monitor (cached)\n"); callbackRequest(&pcbst->ioProcCb); } else if(pcbst->procPending) { /* if(recWaitDebug) printf("discarding monitor\n"); */ @@ -812,12 +831,12 @@ static void inputChanged(struct recWaitCa *pcamonitor, char inputIndex, double m return; } else { pcbst->procPending = 1; - if(recWaitDebug) printf("queuing monitor (cached)\n"); + if(recWaitDebug>=5) printf("queuing monitor (cached)\n"); callbackRequest(&pcbst->ioProcCb); } } else { /* put input index and monitored data on processing queue */ - if(recWaitDebug) printf("queuing monitor on %d = %lf\n", inputIndex, monData); + if(recWaitDebug>=5) printf("queuing monitor on %d = %lf\n", inputIndex, monData); if(rngBufPut(pcbst->monitorQ, (void *)&inputIndex, sizeof(char)) != sizeof(char)) errMessage(0,"recWait rngBufPut error"); if(rngBufPut(pcbst->monitorQ, (void *)&monData, sizeof(double)) @@ -853,7 +872,7 @@ static void ioIntProcess(CALLBACK *pioProcCb) if(rngBufGet(pcbst->monitorQ, (void *)&monData, sizeof(double)) != sizeof(double)) errMessage(0, "recWait: rngBufGet error"); - if(recWaitDebug) printf("processing on %d = %lf (%lf)\n", inputIndex, monData,pwait->val); + if(recWaitDebug>=5) printf("processing on %d = %lf (%lf)\n", inputIndex, monData,pwait->val); pInput += inputIndex; /* pointer arithmetic to choose appropriate input */ dbScanLock((struct dbCommon *)pwait); @@ -870,7 +889,7 @@ static void ioIntProcess(CALLBACK *pioProcCb) dbScanUnlock((struct dbCommon *)pwait); } else { - if(recWaitDebug) printf("processing (cached)\n"); + if(recWaitDebug>=5) printf("processing (cached)\n"); dbScanLock((struct dbCommon *)pwait); dbProcess((struct dbCommon *)pwait); /* process the record */ dbScanUnlock((struct dbCommon *)pwait); diff --git a/src/rec/recWaitCa.c b/src/rec/recWaitCa.c index 506448841..5be911071 100644 --- a/src/rec/recWaitCa.c +++ b/src/rec/recWaitCa.c @@ -5,7 +5,6 @@ #include #include #include -#include #include #include #include @@ -15,26 +14,23 @@ #include #include #include -#include #include extern int interruptAccept; #define QUEUE_SIZE 256 LOCAL int taskid=0; -LOCAL ELLLIST capvtList; LOCAL RING_ID ringQ;; LOCAL FAST_LOCK lock; -LOCAL void *freeListPvt; typedef enum {cmdNone,cmdAdd,cmdRemove} COMMAND; typedef struct { - ELLNODE node; RECWAITCA *pcamonitor; chid chid; evid evid; COMMAND cmd; + int hasMonitor; struct dbr_sts_double rtndata; /*Not currently used */ } CAPVT; @@ -54,12 +50,10 @@ LOCAL void eventCallback(struct event_handler_args eha) LOCAL void recWaitCaStart(void) { FASTLOCKINIT(&lock); - freeListInitPvt(&freeListPvt,sizeof(CAPVT),1); if((ringQ = rngCreate(sizeof(void *) * QUEUE_SIZE)) == NULL) { errMessage(0,"recWaitCaStart failed"); exit(1); } - ellInit(&capvtList); taskid = taskSpawn("recWaitCaTask",CA_CLIENT_PRI-1,VX_FP_TASK, CA_CLIENT_STACK,(FUNCPTR)recWaitCaTask,0,0,0,0,0,0,0,0,0,0); if(taskid==ERROR) { @@ -73,13 +67,15 @@ long recWaitCaAdd(RECWAITCA *pcamonitor) if(!taskid) recWaitCaStart(); FASTLOCK(&lock); - pcapvt = freeListCalloc(freeListPvt); - pcamonitor->recWaitCaPvt = pcapvt; - pcapvt->pcamonitor = pcamonitor; + pcapvt = pcamonitor->recWaitCaPvt; + if(pcapvt == NULL) { + pcapvt = calloc(1,sizeof(CAPVT)); + pcamonitor->recWaitCaPvt = pcapvt; + pcapvt->pcamonitor = pcamonitor; + } pcapvt->cmd = cmdAdd; if(rngBufPut(ringQ,(void *)&pcapvt,sizeof(pcapvt)) !=sizeof(pcamonitor)) errMessage(0,"recWaitCaAdd: rngBufPut error"); - ellAdd(&capvtList,(void *)pcapvt); FASTUNLOCK(&lock); } @@ -112,20 +108,18 @@ void recWaitCaTask(void) } FASTLOCK(&lock); pcamonitor = pcapvt->pcamonitor; - if(pcapvt->cmd==cmdAdd) { + if(pcapvt->cmd==cmdAdd && !pcapvt->hasMonitor) { SEVCHK(ca_build_and_connect(pcamonitor->channame,TYPENOTCONN,0, &pcapvt->chid,0,NULL,pcapvt), "ca_build_and_connect"); SEVCHK(ca_add_event(DBR_STS_DOUBLE,pcapvt->chid, eventCallback,pcapvt,&pcapvt->evid), "ca_add_event"); - } else {/*must be cmdRemove*/ + pcapvt->hasMonitor = TRUE; + } else if (pcapvt->cmd==cmdRemove && pcapvt->hasMonitor) { SEVCHK(ca_clear_channel(pcapvt->chid),"ca_clear_channel"); - pcapvt->cmd=cmdNone; - ellDelete(&capvtList,(void *)pcapvt); - freeListFree(freeListPvt,pcapvt); + pcapvt->hasMonitor = FALSE; } - pcapvt->cmd=cmdNone; FASTUNLOCK(&lock); } status = ca_pend_event(.1); @@ -139,7 +133,7 @@ static void myCallback(struct recWaitCa *pcamonitor, char inputIndex, double mon printf("myCallback: %s\n",pcamonitor->channame); } -int testCaMonitor(char *name) +int testCaMonitor(char *name,int delay) { RECWAITCA *pcamonitor; long status; @@ -150,5 +144,15 @@ int testCaMonitor(char *name) strcpy(pcamonitor->channame,name); status = recWaitCaAdd(pcamonitor); if(status) errMessage(status,"testCaMonitor error"); + if(delay>0) taskDelay(delay); + status = recWaitCaDelete(pcamonitor); + if(status) errMessage(status,"testCaMonitor error"); + if(delay>0) taskDelay(delay); + status = recWaitCaAdd(pcamonitor); + if(status) errMessage(status,"testCaMonitor error"); + if(delay>0) taskDelay(delay); + status = recWaitCaDelete(pcamonitor); + if(status) errMessage(status,"testCaMonitor error"); + if(delay>0) taskDelay(delay); return(0); }