From 062e3d6d32a4f974c59a9ef6a445f036dd4d11aa Mon Sep 17 00:00:00 2001 From: Ned Arnold Date: Thu, 16 Feb 1995 20:18:22 +0000 Subject: [PATCH] changed names of caMonitor stuff to recWaitCa stuff. Also added individual flags for IO_INTR processing of inputs --- src/rec/recWait.c | 157 ++++++++++++++++++++++++++------------------ src/rec/recWaitCa.c | 154 +++++++++++++++++++++++++++++++++++++++++++ src/rec/recWaitCa.h | 9 +++ 3 files changed, 255 insertions(+), 65 deletions(-) create mode 100644 src/rec/recWaitCa.c create mode 100644 src/rec/recWaitCa.h diff --git a/src/rec/recWait.c b/src/rec/recWait.c index 3a7be39f5..38eaf027a 100644 --- a/src/rec/recWait.c +++ b/src/rec/recWait.c @@ -39,11 +39,13 @@ * .06 08-19-94 nda added Output data option of VAL or DOL * .07 09-14-94 nda corrected bug that caused SCAN_DISABLE to lock up the record forever * .08 02-01-95 nda added VERS and ODLY (output execution delay) + * .09 02-15-95 nda addedd INxP to determine which inputs should cause the record + * to process when in I/O INTR mode. * * */ -#define VERSION 1.08 +#define VERSION 1.09 @@ -74,7 +76,7 @@ #include #include -#include +#include /* Create RSET - Record Support Entry Table*/ @@ -162,7 +164,7 @@ struct cbStruct { struct waitRecord *pwait; /* pointer to wait record which needs work done */ WDOG_ID wd_id; /* Watchdog used for delays */ IOSCANPVT ioscanpvt; /* used for IO_EVENT scanning */ - CAMONITOR inpMonitor[12]; /* required structures for each input variable */ + RECWAITCA inpMonitor[12]; /* required structures for each input variable */ int procPending; /* flag to indicate record processing is pending */ }; @@ -185,9 +187,10 @@ static long init_record(pwait,pass) long status = 0; int i; - char *ppvn[PVN_SIZE]; - struct dbAddr **ppdbAddr; /* ptr to a ptr to dbAddr */ - long *paddrValid; + char *ppvn[PVN_SIZE]; + struct dbAddr **ppdbAddr; /* ptr to a ptr to dbAddr */ + long *paddrValid; + unsigned short *piointInc; /* include for IO_INT ? */ char rpbuf[184]; short error_number; @@ -258,12 +261,14 @@ static long init_record(pwait,pass) /* MON_ALWAYS if(pwait->scan == SCAN_IO_EVENT) { */ if(1) { paddrValid = &pwait->inav; + piointInc = &pwait->inap; - for(i=0;icbst)->inpMonitor[i])); - if(status) errMessage(status,"caMonitorAdd error"); + for(i=0;icbst)->inpMonitor[i])); + if(status) errMessage(status,"recWaitCaAdd error"); } } } @@ -372,43 +377,43 @@ static long special(paddr,after) char *ppvn[PVN_SIZE]; struct dbAddr **ppdbAddr; /* ptr to a ptr to dbAddr */ long *paddrValid; + unsigned short *piointInc; /* include for IO_INT ? */ int i; long status; long odbv =0; short error_number; char rpbuf[184]; - if(waitRecDebug) printf("entering special \n"); - if(!after) { /* this is called before ca changes the field */ - switch(special_type) { - case(SPC_SCAN): /* about to change SCAN mechanism ... */ - if(pwait->scan == SCAN_IO_EVENT) { - /* Leaving IO_EVENT, delete monitors */ - paddrValid = &pwait->inav; - for(i=0;icbst)->inpMonitor[i])); - if(status) errMessage(status,"caMonitorDelete error"); - } - } - } - break; + if(waitRecDebug) printf("entering special %d \n",after); - case(SPC_MOD): /* check if changing any PV names while monitored */ -/* MON_ALWAYS if(pwait->scan == SCAN_IO_EVENT) { */ - if(1) { - *ppvn = &pwait->inan[0]; - paddrValid = &pwait->inav; - for(i=0;ipfield==*ppvn) && !(*paddrValid)) { - if(waitRecDebug) printf("deleting monitor\n"); - status = caMonitorDelete(&(((struct cbStruct *)pwait->cbst)->inpMonitor[i])); - if(status) errMessage(status,"caMonitorDelete error"); - } - } - } - break; + if(!after) { /* this is called before ca changes the field */ + /* MON_ALWAYS This case doesn't currently happen */ + if((special_type == SPC_SCAN) && (pwait->scan == SCAN_IO_EVENT)) { + /* Leaving IO_EVENT, delete monitors */ + paddrValid = &pwait->inav; + for(i=0;icbst)->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 */ + 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(waitRecDebug) printf("deleting monitor on input %d\n",i); + status = recWaitCaDelete(&(((struct cbStruct *)pwait->cbst)->inpMonitor[i])); + if(status) errMessage(status,"recWaitCaDelete error"); + } } return(0); } @@ -416,38 +421,58 @@ static long special(paddr,after) /* this is executed after ca changed the field */ switch(special_type) { case(SPC_SCAN): /* Changed SCAN mechanism, set monitors on input links */ + /* MON_ALWAYS This case currently doesn't happen */ if(pwait->scan == SCAN_IO_EVENT) { paddrValid = &pwait->inav; for(i=0;icbst)->inpMonitor[i])); - if(status) errMessage(status,"caMonitorAdd error"); + if(waitRecDebug) printf("adding monitor on input %d\n", i); + status = recWaitCaAdd(&(((struct cbStruct *)pwait->cbst)->inpMonitor[i])); + if(status) errMessage(status,"recWaitCaAdd error"); } } } return(0); - case(SPC_MOD): /* check if changing any PV names */ - *ppvn = &pwait->inan[0]; - ppdbAddr = (struct dbAddr **)&pwait->inaa; - paddrValid = &pwait->inav; + break; + + case(REC_WAIT_A): /* check if changing any input PV's or flags */ + case(REC_WAIT_B): + case(REC_WAIT_C): + case(REC_WAIT_D): + case(REC_WAIT_E): + case(REC_WAIT_F): + case(REC_WAIT_G): + case(REC_WAIT_H): + case(REC_WAIT_I): + case(REC_WAIT_J): + case(REC_WAIT_K): + case(REC_WAIT_L): + + i = special_type - REC_WAIT_A; /* index of input */ + paddrValid = &pwait->inav + i; /* pointer arithmetic */ + ppdbAddr = (struct dbAddr **)&pwait->inaa + i; /* pointer arithmetic */ + *ppvn = &pwait->inan[0] + (i*PVN_SIZE); - for(i=0;ipfield==*ppvn) { - odbv = *paddrValid; - *paddrValid = dbNameToAddr(*ppvn, *ppdbAddr); - if (odbv != *paddrValid) { - db_post_events(pwait,paddrValid,DBE_VALUE); - } -/* MON_ALWAYS if((pwait->scan == SCAN_IO_EVENT) && !(*paddrValid)) { */ - if((1) && !(*paddrValid)) { - if(waitRecDebug) printf("adding monitor\n"); - status = caMonitorAdd(&(((struct cbStruct *)pwait->cbst)->inpMonitor[i])); - if(status) errMessage(status,"caMonitorAdd error"); - } - return(0); - } - } + /* If the PV Name changing, do dbNameToAddr */ + if(paddr->pfield==*ppvn) { + odbv = *paddrValid; + *paddrValid = dbNameToAddr(*ppvn, *ppdbAddr); + 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 */ + piointInc = &pwait->inap + i; /* pointer arithmetic */ + if(!(*paddrValid) && (*piointInc)) { + if(waitRecDebug) printf("adding monitor on input %d\n", i); + status = recWaitCaAdd(&(((struct cbStruct *)pwait->cbst)->inpMonitor[i])); + if(status) errMessage(status,"recWaitCaAdd error"); + } + return(0); + break; + + case(SPC_MOD): /* check if changing any other SPC_MOD fields */ if(paddr->pfield==pwait->outn) { /* this is the output link */ odbv = pwait->outv; pwait->outv = dbNameToAddr(pwait->outn,(struct dbAddr *)pwait->outa); @@ -467,6 +492,7 @@ static long special(paddr,after) } return(0); + break; case(SPC_CALC): pwait->clcv=postfix(pwait->calc,rpbuf,&error_number); @@ -481,6 +507,7 @@ static long special(paddr,after) db_post_events(pwait,pwait->calc,DBE_VALUE); db_post_events(pwait,pwait->clcv,DBE_VALUE); return(0); + break; default: recGblDbaddrError(S_db_badChoice,paddr,"wait: special"); return(S_db_badChoice); @@ -725,7 +752,7 @@ static double oldDold; -static void inputChanged(struct caMonitor *pcamonitor) +static void inputChanged(struct recWaitCa *pcamonitor) { struct waitRecord *pwait = (struct waitRecord *)pcamonitor->userPvt; diff --git a/src/rec/recWaitCa.c b/src/rec/recWaitCa.c new file mode 100644 index 000000000..e8335a9c5 --- /dev/null +++ b/src/rec/recWaitCa.c @@ -0,0 +1,154 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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; + struct dbr_sts_double rtndata; /*Not currently used */ +} CAPVT; + +void recWaitCaTask(void); + +LOCAL void eventCallback(struct event_handler_args eha) +{ + struct dbr_sts_double *pdata = eha.dbr; + CAPVT *pcapvt; + RECWAITCA *pcamonitor; + + pcapvt = (CAPVT *)eha.usr; + pcamonitor = pcapvt->pcamonitor; + (pcamonitor->callback)(pcamonitor); +} + +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) { + errMessage(0,"recWaitCaStart: taskSpawn Failure\n"); + } +} + +long recWaitCaAdd(RECWAITCA *pcamonitor) +{ + CAPVT *pcapvt; + + if(!taskid) recWaitCaStart(); + FASTLOCK(&lock); + pcapvt = freeListCalloc(freeListPvt); + 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); +} + +long recWaitCaDelete(RECWAITCA *pcamonitor) +{ + CAPVT *pcapvt = pcamonitor->recWaitCaPvt; + + FASTLOCK(&lock); + pcapvt->cmd = cmdRemove; + if(rngBufPut(ringQ,(void *)&pcapvt,sizeof(pcapvt)) + !=sizeof(pcamonitor)) errMessage(0,"recWaitCaDelete: rngBufPut error"); + FASTUNLOCK(&lock); +} + +/*LOCAL */ +void recWaitCaTask(void) +{ + CAPVT *pcapvt; + RECWAITCA *pcamonitor; + int status; + + taskwdInsert(taskIdSelf(),NULL,NULL); + SEVCHK(ca_task_initialize(),"ca_task_initialize"); + while(TRUE) { + while (rngNBytes(ringQ)>=sizeof(pcapvt) && interruptAccept){ + if(rngBufGet(ringQ,(void *)&pcapvt,sizeof(pcapvt)) + !=sizeof(pcapvt)) { + errMessage(0,"recWaitCaTask: rngBufGet error"); + continue; + } + FASTLOCK(&lock); + pcamonitor = pcapvt->pcamonitor; + if(pcapvt->cmd==cmdAdd) { + 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*/ + SEVCHK(ca_clear_channel(pcapvt->chid),"ca_clear_channel"); + pcapvt->cmd=cmdNone; + ellDelete(&capvtList,(void *)pcapvt); + freeListFree(freeListPvt,pcapvt); + } + pcapvt->cmd=cmdNone; + FASTUNLOCK(&lock); + } + status = ca_pend_event(.1); + if(status!=ECA_NORMAL && status!=ECA_TIMEOUT) + SEVCHK(status,"ca_pend_event"); + } +} + +static void myCallback(struct recWaitCa *pcamonitor) +{ + printf("myCallback: %s\n",pcamonitor->channame); +} + +int testCaMonitor(char *name) +{ + RECWAITCA *pcamonitor; + long status; + + pcamonitor = calloc(1,sizeof(RECWAITCA)); + pcamonitor->channame = calloc(1,strlen(name)+1); + pcamonitor->callback = myCallback; + strcpy(pcamonitor->channame,name); + status = recWaitCaAdd(pcamonitor); + if(status) errMessage(status,"testCaMonitor error"); + return(0); +} diff --git a/src/rec/recWaitCa.h b/src/rec/recWaitCa.h new file mode 100644 index 000000000..d92c31cfc --- /dev/null +++ b/src/rec/recWaitCa.h @@ -0,0 +1,9 @@ +typedef struct recWaitCa{ + char *channame; + void (*callback)(struct recWaitCa *pcamonitor); + void *userPvt; + void *recWaitCaPvt; +} RECWAITCA; + +long recWaitCaAdd(RECWAITCA *pcamonitor); +long recWaitCaDelete(RECWAITCA *pcamonitor);