Improved recWaitCaTask and associated record code
This commit is contained in:
+39
-20
@@ -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;i<ARG_MAX; i++, paddrValid++, piointInc++) {
|
||||
/* store current value in private array */
|
||||
pcbst->inpMonFlag[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;i<ARG_MAX; i++, paddrValid++) {
|
||||
if(!(*paddrValid)) {
|
||||
if(recWaitDebug) printf("deleting monitor\n");
|
||||
status = recWaitCaDelete(&(((struct cbStruct *)pwait->cbst)->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;i<ARG_MAX; i++, paddrValid++) {
|
||||
if(!(*paddrValid)) {
|
||||
if(recWaitDebug) printf("adding monitor on input %d\n", i);
|
||||
status = recWaitCaAdd(&(((struct cbStruct *)pwait->cbst)->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);
|
||||
|
||||
+22
-18
@@ -5,7 +5,6 @@
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <rngLib.h>
|
||||
#include <ellLib.h>
|
||||
#include <vxLib.h>
|
||||
#include <dbDefs.h>
|
||||
#include <taskwd.h>
|
||||
@@ -15,26 +14,23 @@
|
||||
#include <caeventmask.h>
|
||||
#include <calink.h>
|
||||
#include <task_params.h>
|
||||
#include <freeList.h>
|
||||
#include <recWaitCa.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user