cleanup Attributes; no calls to ca while holding locks
This commit is contained in:
358
src/db/dbCa.c
358
src/db/dbCa.c
@@ -54,11 +54,13 @@ epicsShareFunc void * epicsShareAPI dbCalloc(size_t nobj,size_t size);
|
||||
#include "dbCa.h"
|
||||
#include "dbCaPvt.h"
|
||||
|
||||
static ELLLIST workList; /* Work list for dbCaTask */
|
||||
static epicsMutexId workListLock; /*Mutual exclusions semaphores for workList*/
|
||||
static epicsEventId workListEvent; /*wakeup event for dbCaTask*/
|
||||
static int removesOutstanding = 0;
|
||||
static int removesOutstandingWarning = 10000;
|
||||
#define STATIC static
|
||||
|
||||
STATIC ELLLIST workList; /* Work list for dbCaTask */
|
||||
STATIC epicsMutexId workListLock; /*Mutual exclusions semaphores for workList*/
|
||||
STATIC epicsEventId workListEvent; /*wakeup event for dbCaTask*/
|
||||
STATIC int removesOutstanding = 0;
|
||||
STATIC int removesOutstandingWarning = 10000;
|
||||
|
||||
void dbCaTask(void); /*The Channel Access Task*/
|
||||
extern void dbServiceIOInit();
|
||||
@@ -100,8 +102,8 @@ extern void dbServiceIOInit();
|
||||
* epicsMutexMustLock(pca->lock);
|
||||
* pca->plink = 0;
|
||||
* plink->value.pv_link.pvt = 0;
|
||||
* addAction(pca,CA_CLEAR_CHANNEL);
|
||||
* epicsMutexUnlock(pca->lock);
|
||||
* addAction(pca,CA_CLEAR_CHANNEL);
|
||||
*
|
||||
* dbCaTask issues a ca_clear_channel and then frees the caLink.
|
||||
*
|
||||
@@ -111,7 +113,7 @@ extern void dbServiceIOInit();
|
||||
*
|
||||
*/
|
||||
|
||||
static void addAction(caLink *pca, short link_action)
|
||||
STATIC void addAction(caLink *pca, short link_action)
|
||||
{
|
||||
int callAdd = FALSE;
|
||||
|
||||
@@ -125,13 +127,18 @@ static void addAction(caLink *pca, short link_action)
|
||||
}
|
||||
if(link_action&CA_CLEAR_CHANNEL) {
|
||||
if(++removesOutstanding>=removesOutstandingWarning) {
|
||||
printf("dbCa: Warning removesOutstanding %d\n",removesOutstanding);
|
||||
errlogPrintf("dbCa: Warning removesOutstanding %d\n",removesOutstanding);
|
||||
}
|
||||
while(removesOutstanding>=removesOutstandingWarning) {
|
||||
epicsMutexUnlock(workListLock);
|
||||
epicsThreadSleep(1.0);
|
||||
epicsMutexMustLock(workListLock);
|
||||
}
|
||||
}
|
||||
pca->link_action |= link_action;
|
||||
if(callAdd) ellAdd(&workList,&pca->node);
|
||||
if(callAdd) epicsEventSignal(workListEvent);
|
||||
epicsMutexUnlock(workListLock); /*Give it back immediately*/
|
||||
if(callAdd) epicsEventSignal(workListEvent);
|
||||
}
|
||||
|
||||
void epicsShareAPI dbCaLinkInit(void)
|
||||
@@ -150,6 +157,7 @@ void epicsShareAPI dbCaAddLink( struct link *plink)
|
||||
caLink *pca;
|
||||
char *pvname;
|
||||
|
||||
assert(!plink->value.pv_link.pvt);
|
||||
pca = (caLink*)dbCalloc(1,sizeof(caLink));
|
||||
pca->lock = epicsMutexMustCreate();
|
||||
epicsMutexMustLock(pca->lock);
|
||||
@@ -172,8 +180,9 @@ void epicsShareAPI dbCaRemoveLink( struct link *plink)
|
||||
epicsMutexMustLock(pca->lock);
|
||||
pca->plink = 0;
|
||||
plink->value.pv_link.pvt = 0;
|
||||
addAction(pca,CA_CLEAR_CHANNEL);
|
||||
/*Must unlock before addAction. Otherwise dbCaTask might free first*/
|
||||
epicsMutexUnlock(pca->lock);
|
||||
addAction(pca,CA_CLEAR_CHANNEL);
|
||||
}
|
||||
|
||||
long epicsShareAPI dbCaGetLink(struct link *plink,short dbrType, void *pdest,
|
||||
@@ -215,6 +224,7 @@ long epicsShareAPI dbCaGetLink(struct link *plink,short dbrType, void *pdest,
|
||||
}
|
||||
if(!nelements || *nelements == 1){
|
||||
pconvert= dbFastGetConvertRoutine[dbDBRoldToDBFnew[pca->dbrType]][dbrType];
|
||||
assert(pca->pgetNative);
|
||||
(*(pconvert))(pca->pgetNative, pdest, 0);
|
||||
} else {
|
||||
unsigned long ntoget = *nelements;
|
||||
@@ -225,6 +235,7 @@ long epicsShareAPI dbCaGetLink(struct link *plink,short dbrType, void *pdest,
|
||||
pconvert = dbGetConvertRoutine[dbDBRoldToDBFnew[pca->dbrType]][dbrType];
|
||||
memset((void *)&dbAddr,0,sizeof(dbAddr));
|
||||
dbAddr.pfield = pca->pgetNative;
|
||||
assert(dbAddr.pfield);
|
||||
/*Following will only be used for pca->dbrType == DBR_STRING*/
|
||||
dbAddr.field_size = MAX_STRING_SIZE;
|
||||
/*Ignore error return*/
|
||||
@@ -294,119 +305,25 @@ long epicsShareAPI dbCaPutLink(struct link *plink,short dbrType,
|
||||
return(status);
|
||||
}
|
||||
|
||||
long epicsShareAPI dbCaGetAttributes(const struct link *plink,
|
||||
void (*callback)(void *usrPvt),void *usrPvt)
|
||||
{
|
||||
caLink *pca;
|
||||
long status = 0;
|
||||
short link_action = 0;
|
||||
caAttributes *pcaAttributes;
|
||||
#define pcaGetCheck \
|
||||
assert(plink); \
|
||||
if(plink->type!=CA_LINK) return(-1); \
|
||||
pca = (caLink *)plink->value.pv_link.pvt; \
|
||||
assert(pca); \
|
||||
epicsMutexMustLock(pca->lock); \
|
||||
if(!pca->isConnected) { \
|
||||
epicsMutexUnlock(pca->lock); \
|
||||
return(-1); \
|
||||
}
|
||||
|
||||
assert(plink);
|
||||
if(plink->type!=CA_LINK) return(-1);
|
||||
pca = (caLink *)plink->value.pv_link.pvt;
|
||||
assert(pca);
|
||||
epicsMutexMustLock(pca->lock);
|
||||
if(!pca->isConnected || !pca->hasWriteAccess) {
|
||||
epicsMutexUnlock(pca->lock);
|
||||
return(-1);
|
||||
}
|
||||
if(pca->pcaAttributes) {
|
||||
epicsMutexUnlock(pca->lock);
|
||||
return(-1);
|
||||
}
|
||||
pcaAttributes = dbCalloc(1,sizeof(caAttributes));
|
||||
pcaAttributes->callback = callback;
|
||||
pcaAttributes->usrPvt = usrPvt;
|
||||
pca->pcaAttributes = pcaAttributes;
|
||||
link_action |= CA_GET_ATTRIBUTES;
|
||||
addAction(pca,link_action);
|
||||
epicsMutexUnlock(pca->lock);
|
||||
return(status);
|
||||
}
|
||||
|
||||
caAttributes *getpcaAttributes(const struct link *plink)
|
||||
{
|
||||
caLink *pca;
|
||||
|
||||
if(!plink || (plink->type!=CA_LINK)) return(NULL);
|
||||
pca = (caLink *)plink->value.pv_link.pvt;
|
||||
if(!pca->isConnected) return(NULL);
|
||||
return(pca->pcaAttributes);
|
||||
}
|
||||
|
||||
long epicsShareAPI dbCaGetControlLimits(
|
||||
const struct link *plink,double *low, double *high)
|
||||
{
|
||||
caAttributes *pcaAttributes;
|
||||
|
||||
pcaAttributes = getpcaAttributes(plink);
|
||||
if(!pcaAttributes) return(-1);
|
||||
*low = pcaAttributes->data.lower_ctrl_limit;
|
||||
*high = pcaAttributes->data.upper_ctrl_limit;
|
||||
return(0);
|
||||
}
|
||||
|
||||
long epicsShareAPI dbCaGetGraphicLimits(
|
||||
const struct link *plink,double *low, double *high)
|
||||
{
|
||||
caAttributes *pcaAttributes;
|
||||
|
||||
pcaAttributes = getpcaAttributes(plink);
|
||||
if(!pcaAttributes) return(-1);
|
||||
*low = pcaAttributes->data.lower_disp_limit;
|
||||
*high = pcaAttributes->data.upper_disp_limit;
|
||||
return(0);
|
||||
}
|
||||
|
||||
long epicsShareAPI dbCaGetAlarmLimits(
|
||||
const struct link *plink,
|
||||
double *lolo, double *low, double *high, double *hihi)
|
||||
{
|
||||
caAttributes *pcaAttributes;
|
||||
|
||||
pcaAttributes = getpcaAttributes(plink);
|
||||
if(!pcaAttributes) return(-1);
|
||||
*lolo = pcaAttributes->data.lower_alarm_limit;
|
||||
*low = pcaAttributes->data.lower_warning_limit;
|
||||
*high = pcaAttributes->data.upper_warning_limit;
|
||||
*hihi = pcaAttributes->data.upper_alarm_limit;
|
||||
return(0);
|
||||
}
|
||||
|
||||
long epicsShareAPI dbCaGetPrecision(
|
||||
const struct link *plink,short *precision)
|
||||
{
|
||||
caAttributes *pcaAttributes;
|
||||
|
||||
pcaAttributes = getpcaAttributes(plink);
|
||||
if(!pcaAttributes) return(-1);
|
||||
*precision = pcaAttributes->data.precision;
|
||||
return(0);
|
||||
}
|
||||
|
||||
long epicsShareAPI dbCaGetUnits(
|
||||
const struct link *plink,char *units,int unitsSize)
|
||||
{
|
||||
caAttributes *pcaAttributes;
|
||||
|
||||
pcaAttributes = getpcaAttributes(plink);
|
||||
if(!pcaAttributes) return(-1);
|
||||
strncpy(units,pcaAttributes->data.units,unitsSize);
|
||||
units[unitsSize-1] = 0;
|
||||
return(0);
|
||||
}
|
||||
|
||||
long epicsShareAPI dbCaGetNelements(
|
||||
const struct link *plink,long *nelements)
|
||||
{
|
||||
caLink *pca;
|
||||
|
||||
if(!plink) return(-1);
|
||||
if(plink->type != CA_LINK) return(-1);
|
||||
pca = (caLink *)plink->value.pv_link.pvt;
|
||||
if(!pca->isConnected) return(-1);
|
||||
pcaGetCheck
|
||||
*nelements = pca->nelements;
|
||||
epicsMutexUnlock(pca->lock);
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -415,11 +332,9 @@ long epicsShareAPI dbCaGetSevr(
|
||||
{
|
||||
caLink *pca;
|
||||
|
||||
if(!plink) return(-1);
|
||||
if(plink->type != CA_LINK) return(-1);
|
||||
pca = (caLink *)plink->value.pv_link.pvt;
|
||||
if(!pca->isConnected) return(-1);
|
||||
pcaGetCheck
|
||||
*severity = pca->sevr;
|
||||
epicsMutexUnlock(pca->lock);
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -428,11 +343,9 @@ long epicsShareAPI dbCaGetTimeStamp(
|
||||
{
|
||||
caLink *pca;
|
||||
|
||||
if(!plink) return(-1);
|
||||
if(plink->type != CA_LINK) return(-1);
|
||||
pca = (caLink *)plink->value.pv_link.pvt;
|
||||
if(!pca->isConnected) return(-1);
|
||||
pcaGetCheck
|
||||
memcpy(pstamp,&pca->timeStamp,sizeof(epicsTimeStamp));
|
||||
epicsMutexUnlock(pca->lock);
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -454,19 +367,113 @@ int epicsShareAPI dbCaGetLinkDBFtype(
|
||||
const struct link *plink)
|
||||
{
|
||||
caLink *pca;
|
||||
short type;
|
||||
|
||||
if(!plink) return(-1);
|
||||
if(plink->type != CA_LINK) return(-1);
|
||||
pcaGetCheck
|
||||
type = dbDBRoldToDBFnew[pca->dbrType];
|
||||
epicsMutexUnlock(pca->lock);
|
||||
return(type);
|
||||
}
|
||||
|
||||
long epicsShareAPI dbCaGetAttributes(const struct link *plink,
|
||||
void (*callback)(void *usrPvt),void *usrPvt)
|
||||
{
|
||||
caLink *pca;
|
||||
int gotAttributes;
|
||||
|
||||
assert(plink);
|
||||
if(plink->type!=CA_LINK) return(-1);
|
||||
pca = (caLink *)plink->value.pv_link.pvt;
|
||||
if(!pca) return(-1);
|
||||
if(!pca->chid) return(-1);
|
||||
if(pca->isConnected)
|
||||
return(dbDBRoldToDBFnew[ca_field_type(pca->chid)]);
|
||||
return(-1);
|
||||
assert(pca);
|
||||
epicsMutexMustLock(pca->lock);
|
||||
pca->callback = callback;
|
||||
pca->userPvt = usrPvt;
|
||||
gotAttributes = pca->gotAttributes;
|
||||
epicsMutexUnlock(pca->lock);
|
||||
if(gotAttributes) (*pca->callback)(pca->userPvt);
|
||||
return(0);
|
||||
}
|
||||
|
||||
long epicsShareAPI dbCaGetControlLimits(
|
||||
const struct link *plink,double *low, double *high)
|
||||
{
|
||||
caLink *pca;
|
||||
int gotAttributes;
|
||||
|
||||
pcaGetCheck
|
||||
gotAttributes = pca->gotAttributes;
|
||||
if(gotAttributes) {
|
||||
*low = pca->controlLimits[0];
|
||||
*high = pca->controlLimits[1];
|
||||
}
|
||||
epicsMutexUnlock(pca->lock);
|
||||
return(gotAttributes ? 0 : -1);
|
||||
}
|
||||
|
||||
long epicsShareAPI dbCaGetGraphicLimits(
|
||||
const struct link *plink,double *low, double *high)
|
||||
{
|
||||
caLink *pca;
|
||||
int gotAttributes;
|
||||
|
||||
pcaGetCheck
|
||||
gotAttributes = pca->gotAttributes;
|
||||
if(gotAttributes) {
|
||||
*low = pca->displayLimits[0];
|
||||
*high = pca->displayLimits[1];
|
||||
}
|
||||
epicsMutexUnlock(pca->lock);
|
||||
return(gotAttributes ? 0 : -1);
|
||||
}
|
||||
|
||||
static void exceptionCallback(struct exception_handler_args args)
|
||||
long epicsShareAPI dbCaGetAlarmLimits(
|
||||
const struct link *plink,
|
||||
double *lolo, double *low, double *high, double *hihi)
|
||||
{
|
||||
caLink *pca;
|
||||
int gotAttributes;
|
||||
|
||||
pcaGetCheck
|
||||
gotAttributes = pca->gotAttributes;
|
||||
if(gotAttributes) {
|
||||
*lolo = pca->alarmLimits[0];
|
||||
*low = pca->alarmLimits[1];
|
||||
*high = pca->alarmLimits[2];
|
||||
*hihi = pca->alarmLimits[3];
|
||||
}
|
||||
epicsMutexUnlock(pca->lock);
|
||||
return(gotAttributes ? 0 : -1);
|
||||
}
|
||||
|
||||
long epicsShareAPI dbCaGetPrecision(
|
||||
const struct link *plink,short *precision)
|
||||
{
|
||||
caLink *pca;
|
||||
int gotAttributes;
|
||||
|
||||
pcaGetCheck
|
||||
gotAttributes = pca->gotAttributes;
|
||||
if(gotAttributes) *precision = pca->precision;
|
||||
epicsMutexUnlock(pca->lock);
|
||||
return(gotAttributes ? 0 : -1);
|
||||
}
|
||||
|
||||
long epicsShareAPI dbCaGetUnits(
|
||||
const struct link *plink,char *units,int unitsSize)
|
||||
{
|
||||
caLink *pca;
|
||||
int gotAttributes;
|
||||
|
||||
pcaGetCheck
|
||||
gotAttributes = pca->gotAttributes;
|
||||
if(unitsSize>sizeof(pca->units)) unitsSize = sizeof(pca->units);
|
||||
if(gotAttributes) strncpy(units,pca->units,unitsSize);
|
||||
units[unitsSize-1] = 0;
|
||||
epicsMutexUnlock(pca->lock);
|
||||
return(gotAttributes ? 0 : -1);
|
||||
}
|
||||
|
||||
STATIC void exceptionCallback(struct exception_handler_args args)
|
||||
{
|
||||
chid chid = args.chid;
|
||||
long stat = args.stat; /* Channel access status code*/
|
||||
@@ -500,7 +507,7 @@ static void exceptionCallback(struct exception_handler_args args)
|
||||
(writeAccess ? "writeAccess" : "noWriteAccess"));
|
||||
}
|
||||
|
||||
static void eventCallback(struct event_handler_args arg)
|
||||
STATIC void eventCallback(struct event_handler_args arg)
|
||||
{
|
||||
caLink *pca = (caLink *)arg.usr;
|
||||
DBLINK *plink;
|
||||
@@ -527,6 +534,7 @@ static void eventCallback(struct event_handler_args arg)
|
||||
assert(arg.dbr);
|
||||
size = arg.count * dbr_value_size[arg.type];
|
||||
if((arg.type==DBR_TIME_STRING) && (ca_field_type(pca->chid)==DBR_ENUM)) {
|
||||
assert(pca->pgetString);
|
||||
memcpy(pca->pgetString,dbr_value_ptr(arg.dbr,arg.type),size);
|
||||
pca->gotInString = TRUE;
|
||||
} else switch (arg.type){
|
||||
@@ -537,6 +545,7 @@ static void eventCallback(struct event_handler_args arg)
|
||||
case DBR_TIME_CHAR:
|
||||
case DBR_TIME_LONG:
|
||||
case DBR_TIME_DOUBLE:
|
||||
assert(pca->pgetNative);
|
||||
memcpy(pca->pgetNative,dbr_value_ptr(arg.dbr,arg.type),size);
|
||||
pca->gotInNative = TRUE;
|
||||
break;
|
||||
@@ -558,29 +567,37 @@ done:
|
||||
epicsMutexUnlock(pca->lock);
|
||||
}
|
||||
|
||||
static void getAttribEventCallback(struct event_handler_args arg)
|
||||
STATIC void getAttribEventCallback(struct event_handler_args arg)
|
||||
{
|
||||
caLink *pca = (caLink *)arg.usr;
|
||||
struct link *plink;
|
||||
const struct dbr_ctrl_double *dbr;
|
||||
caAttributes *pcaAttributes = NULL;
|
||||
struct dbr_ctrl_double *pdbr;
|
||||
|
||||
assert(pca);
|
||||
epicsMutexMustLock(pca->lock);
|
||||
plink = pca->plink;
|
||||
if(!plink) goto done;
|
||||
if(!plink) {
|
||||
epicsMutexUnlock(pca->lock);
|
||||
return;
|
||||
}
|
||||
assert(arg.dbr);
|
||||
dbr = arg.dbr;
|
||||
pcaAttributes = pca->pcaAttributes;
|
||||
if(!pcaAttributes) goto done;
|
||||
pcaAttributes->data = *dbr; /*copy entire structure*/
|
||||
pcaAttributes->gotData = TRUE;
|
||||
(pcaAttributes->callback)(pcaAttributes->usrPvt);
|
||||
done:
|
||||
pdbr = (struct dbr_ctrl_double *)arg.dbr;
|
||||
pca->gotAttributes = TRUE;
|
||||
pca->controlLimits[0] = pdbr->lower_ctrl_limit;
|
||||
pca->controlLimits[1] = pdbr->upper_ctrl_limit;
|
||||
pca->displayLimits[0] = pdbr->lower_disp_limit;
|
||||
pca->displayLimits[1] = pdbr->upper_disp_limit;
|
||||
pca->alarmLimits[0] = pdbr->lower_alarm_limit;
|
||||
pca->alarmLimits[1] = pdbr->lower_warning_limit;
|
||||
pca->alarmLimits[2] = pdbr->upper_warning_limit;
|
||||
pca->alarmLimits[3] = pdbr->upper_alarm_limit;
|
||||
pca->precision = pdbr->precision;
|
||||
memcpy(pca->units,pdbr->units,MAX_UNITS_SIZE);
|
||||
epicsMutexUnlock(pca->lock);
|
||||
if(pca->callback) (*pca->callback)(pca->userPvt);
|
||||
}
|
||||
|
||||
static void accessRightsCallback(struct access_rights_handler_args arg)
|
||||
STATIC void accessRightsCallback(struct access_rights_handler_args arg)
|
||||
{
|
||||
caLink *pca = (caLink *)ca_puser(arg.chid);
|
||||
struct link *plink;
|
||||
@@ -606,7 +623,7 @@ done:
|
||||
epicsMutexUnlock(pca->lock);
|
||||
}
|
||||
|
||||
static void connectionCallback(struct connection_handler_args arg)
|
||||
STATIC void connectionCallback(struct connection_handler_args arg)
|
||||
{
|
||||
caLink *pca;
|
||||
short link_action = 0;
|
||||
@@ -665,7 +682,8 @@ static void connectionCallback(struct connection_handler_args arg)
|
||||
if((plink->value.pv_link.pvlMask & pvlOptOutString) && (pca->gotOutString)){
|
||||
link_action |= CA_WRITE_STRING;
|
||||
}
|
||||
if(pca->pcaAttributes) link_action |= CA_GET_ATTRIBUTES;
|
||||
pca->gotAttributes = 0;
|
||||
link_action |= CA_GET_ATTRIBUTES;
|
||||
done:
|
||||
if(link_action) addAction(pca,link_action);
|
||||
epicsMutexUnlock(pca->lock);
|
||||
@@ -698,25 +716,18 @@ void dbCaTask()
|
||||
pca->link_action = 0;
|
||||
if(link_action&CA_CLEAR_CHANNEL) --removesOutstanding;
|
||||
epicsMutexUnlock(workListLock); /*Give it back immediately*/
|
||||
epicsMutexMustLock(pca->lock);
|
||||
if(link_action&CA_CLEAR_CHANNEL) {/*This must be first*/
|
||||
/*must lock/unlock so that dbCaRemove can unlock*/
|
||||
epicsMutexUnlock(pca->lock);
|
||||
if(pca->chid) ca_clear_channel(pca->chid);
|
||||
epicsMutexMustLock(pca->lock);
|
||||
free(pca->pgetNative);
|
||||
free(pca->pputNative);
|
||||
free(pca->pgetString);
|
||||
free(pca->pputString);
|
||||
free(pca->pcaAttributes);
|
||||
free(pca->pvname);
|
||||
epicsMutexUnlock(pca->lock);
|
||||
epicsMutexDestroy(pca->lock);
|
||||
free(pca);
|
||||
continue; /*No other link_action makes sense*/
|
||||
}
|
||||
if(link_action&CA_CONNECT) {
|
||||
epicsMutexUnlock(pca->lock);
|
||||
status = ca_create_channel(
|
||||
pca->pvname,connectionCallback,(void *)pca,
|
||||
CA_PRIORITY_DB_LINKS, &(pca->chid));
|
||||
@@ -732,40 +743,51 @@ void dbCaTask()
|
||||
ca_message(status));
|
||||
continue; /*Other options must wait until connect*/
|
||||
}
|
||||
if(ca_state(pca->chid) != cs_conn) {
|
||||
epicsMutexUnlock(pca->lock);
|
||||
continue;
|
||||
}
|
||||
if(ca_state(pca->chid) != cs_conn) continue;
|
||||
if(link_action&CA_WRITE_NATIVE) {
|
||||
epicsMutexUnlock(pca->lock);
|
||||
assert(pca->pputNative);
|
||||
status = ca_array_put(
|
||||
pca->dbrType,pca->nelements,
|
||||
pca->chid,pca->pputNative);
|
||||
epicsMutexMustLock(pca->lock);
|
||||
if(status==ECA_NORMAL) pca->newOutNative = FALSE;
|
||||
epicsMutexUnlock(pca->lock);
|
||||
}
|
||||
if(link_action&CA_WRITE_STRING) {
|
||||
epicsMutexUnlock(pca->lock);
|
||||
assert(pca->pputString);
|
||||
status = ca_array_put(
|
||||
DBR_STRING,1,
|
||||
pca->chid,pca->pputString);
|
||||
epicsMutexMustLock(pca->lock);
|
||||
if(status==ECA_NORMAL) pca->newOutString = FALSE;
|
||||
epicsMutexUnlock(pca->lock);
|
||||
}
|
||||
/*CA_GET_ATTRIBUTES before CA_MONITOR so that attributes available
|
||||
* before the first monitor callback */
|
||||
if(link_action&CA_GET_ATTRIBUTES) {
|
||||
status = ca_get_callback(DBR_CTRL_DOUBLE,
|
||||
pca->chid,getAttribEventCallback,pca);
|
||||
if(status!=ECA_NORMAL)
|
||||
errlogPrintf("dbCaTask ca_add_array_event %s\n",
|
||||
ca_message(status));
|
||||
}
|
||||
if(link_action&CA_MONITOR_NATIVE) {
|
||||
short element_size;
|
||||
|
||||
element_size = dbr_value_size[ca_field_type(pca->chid)];
|
||||
epicsMutexMustLock(pca->lock);
|
||||
pca->pgetNative = dbCalloc(pca->nelements,element_size);
|
||||
epicsMutexUnlock(pca->lock);
|
||||
status = ca_add_array_event(
|
||||
ca_field_type(pca->chid)+DBR_TIME_STRING,
|
||||
ca_element_count(pca->chid),
|
||||
pca->chid, eventCallback,pca,0.0,0.0,0.0,
|
||||
0);
|
||||
ca_field_type(pca->chid)+DBR_TIME_STRING,
|
||||
ca_element_count(pca->chid),
|
||||
pca->chid, eventCallback,pca,0.0,0.0,0.0,0);
|
||||
if(status!=ECA_NORMAL)
|
||||
errlogPrintf("dbCaTask ca_add_array_event %s\n",
|
||||
ca_message(status));
|
||||
}
|
||||
if(link_action&CA_MONITOR_STRING) {
|
||||
epicsMutexMustLock(pca->lock);
|
||||
pca->pgetString = dbCalloc(MAX_STRING_SIZE,sizeof(char));
|
||||
epicsMutexUnlock(pca->lock);
|
||||
status = ca_add_array_event(DBR_TIME_STRING,1,
|
||||
@@ -775,14 +797,6 @@ void dbCaTask()
|
||||
errlogPrintf("dbCaTask ca_add_array_event %s\n",
|
||||
ca_message(status));
|
||||
}
|
||||
if(link_action&CA_GET_ATTRIBUTES) {
|
||||
epicsMutexUnlock(pca->lock);
|
||||
status = ca_get_callback(DBR_CTRL_DOUBLE,
|
||||
pca->chid,getAttribEventCallback,pca);
|
||||
if(status!=ECA_NORMAL)
|
||||
errlogPrintf("dbCaTask ca_add_array_event %s\n",
|
||||
ca_message(status));
|
||||
}
|
||||
}
|
||||
SEVCHK(ca_flush_io(),"dbCaTask");
|
||||
}
|
||||
|
||||
@@ -23,6 +23,17 @@ epicsShareFunc long epicsShareAPI dbCaGetLink(
|
||||
unsigned short *psevr,long *nRequest);
|
||||
epicsShareFunc long epicsShareAPI dbCaPutLink(
|
||||
struct link *plink,short dbrType,const void *pbuffer,long nRequest);
|
||||
|
||||
epicsShareFunc int epicsShareAPI dbCaIsLinkConnected(const struct link *plink);
|
||||
/* The following are available after the link is connected*/
|
||||
epicsShareFunc long epicsShareAPI dbCaGetNelements(
|
||||
const struct link *plink,long *nelements);
|
||||
epicsShareFunc long epicsShareAPI dbCaGetSevr(
|
||||
const struct link *plink,short *severity);
|
||||
epicsShareFunc long epicsShareAPI dbCaGetTimeStamp(
|
||||
const struct link *plink,epicsTimeStamp *pstamp);
|
||||
epicsShareFunc int epicsShareAPI dbCaGetLinkDBFtype(const struct link *plink);
|
||||
/*The following are available after attribute request is complete*/
|
||||
epicsShareFunc long epicsShareAPI dbCaGetAttributes(
|
||||
const struct link *plink,void (*callback)(void *usrPvt),void *usrPvt);
|
||||
epicsShareFunc long epicsShareAPI dbCaGetControlLimits(
|
||||
@@ -35,13 +46,5 @@ epicsShareFunc long epicsShareAPI dbCaGetPrecision(
|
||||
const struct link *plink,short *precision);
|
||||
epicsShareFunc long epicsShareAPI dbCaGetUnits(
|
||||
const struct link *plink,char *units,int unitsSize);
|
||||
epicsShareFunc long epicsShareAPI dbCaGetNelements(
|
||||
const struct link *plink,long *nelements);
|
||||
epicsShareFunc long epicsShareAPI dbCaGetSevr(
|
||||
const struct link *plink,short *severity);
|
||||
epicsShareFunc long epicsShareAPI dbCaGetTimeStamp(
|
||||
const struct link *plink,epicsTimeStamp *pstamp);
|
||||
epicsShareFunc int epicsShareAPI dbCaIsLinkConnected(const struct link *plink);
|
||||
epicsShareFunc int epicsShareAPI dbCaGetLinkDBFtype(const struct link *plink);
|
||||
|
||||
#endif /*INCdbCah*/
|
||||
|
||||
@@ -35,14 +35,6 @@ of this distribution.
|
||||
#define CA_MONITOR_STRING 0x20
|
||||
#define CA_GET_ATTRIBUTES 0x40
|
||||
|
||||
typedef struct caAttributes
|
||||
{
|
||||
void (*callback)(void *usrPvt);
|
||||
struct dbr_ctrl_double data;
|
||||
void *usrPvt;
|
||||
int gotData;
|
||||
}caAttributes;
|
||||
|
||||
typedef struct caLink
|
||||
{
|
||||
ELLNODE node;
|
||||
@@ -51,25 +43,38 @@ typedef struct caLink
|
||||
char *pvname;
|
||||
chid chid;
|
||||
short link_action;
|
||||
/* The following have new values after each data event*/
|
||||
unsigned short sevr;
|
||||
epicsTimeStamp timeStamp;
|
||||
/* The following have values after connection*/
|
||||
short dbrType;
|
||||
long nelements;
|
||||
char hasReadAccess;
|
||||
char hasWriteAccess;
|
||||
char isConnected;
|
||||
char gotFirstConnection;
|
||||
/* The following are for access to additional attributes*/
|
||||
char gotAttributes;
|
||||
void (*callback)(void *usrPvt);
|
||||
void *userPvt;
|
||||
/* The following have values after getAttribEventCallback*/
|
||||
double controlLimits[2];
|
||||
double displayLimits[2];
|
||||
double alarmLimits[4];
|
||||
short precision;
|
||||
char units[MAX_UNITS_SIZE]; /* units of value */
|
||||
/* The following are for handling data*/
|
||||
void *pgetNative;
|
||||
void *pputNative;
|
||||
char *pgetString;
|
||||
void *pputNative;
|
||||
char *pputString;
|
||||
caAttributes *pcaAttributes;
|
||||
char gotInNative;
|
||||
char gotOutNative;
|
||||
char gotInString;
|
||||
char gotOutNative;
|
||||
char gotOutString;
|
||||
char newOutNative;
|
||||
char newOutString;
|
||||
int isConnected;
|
||||
short dbrType;
|
||||
long nelements;
|
||||
short hasReadAccess;
|
||||
short hasWriteAccess;
|
||||
char gotFirstConnection;
|
||||
/* The following are for dbcar*/
|
||||
unsigned long nDisconnect;
|
||||
unsigned long nNoWrite; /*only modified by dbCaPutLink*/
|
||||
}caLink;
|
||||
|
||||
Reference in New Issue
Block a user