diff --git a/src/db/dbCa.c b/src/db/dbCa.c index dc467d58f..1198dc8b6 100644 --- a/src/db/dbCa.c +++ b/src/db/dbCa.c @@ -13,15 +13,15 @@ of this distribution. /**************************************************************** * -* Current Author: Bob Dalesio -* Contributing Author: Marty Kraimer -* Date: 26MAR96 +* Current Author: Bob Dalesio +* Contributing Author: Marty Kraimer +* Date: 26MAR96 * -* Complete replacement for dbCaDblink.c dbCaLink.c (Nicholas T. Karonis) +* Complete replacement for dbCaDblink.c dbCaLink.c (Nicholas T. Karonis) * * Modification Log: * ----------------- -* .01 26MAR96 lrd rewritten for simplicity, robustness and flexibility +* .01 26MAR96 lrd rewritten for simplicity, robustness and flexibility ****************************************************************/ #include @@ -43,6 +43,7 @@ of this distribution. #include "epicsPrint.h" #include "dbCommon.h" #include "cadef.h" +#include "epicsAssert.h" /*following because we cant include dbStaticLib.h*/ epicsShareFunc void * epicsShareAPI dbCalloc(size_t nobj,size_t size); #define epicsExportSharedSymbols @@ -52,7 +53,7 @@ epicsShareFunc void * epicsShareAPI dbCalloc(size_t nobj,size_t size); #include "dbCa.h" #include "dbCaPvt.h" -static ELLLIST caList; /* Work list for dbCaTask */ +static ELLLIST caList; /* Work list for dbCaTask */ static epicsMutexId caListSem; /*Mutual exclusions semaphores for caList*/ static epicsEventId caWakeupSem; /*wakeup semaphore for dbCaTask*/ void dbCaTask(void); /*The Channel Access Task*/ @@ -82,29 +83,32 @@ static void addAction(caLink *pca, short link_action) void epicsShareAPI dbCaLinkInit(void) { dbServiceIOInit(); - ellInit(&caList); - caListSem = epicsMutexMustCreate(); - caWakeupSem = epicsEventMustCreate(epicsEventEmpty); - epicsThreadCreate("dbCaLink", epicsThreadPriorityMedium, - epicsThreadGetStackSize(epicsThreadStackBig), (EPICSTHREADFUNC) dbCaTask,0); + ellInit(&caList); + caListSem = epicsMutexMustCreate(); + caWakeupSem = epicsEventMustCreate(epicsEventEmpty); + epicsThreadCreate("dbCaLink", epicsThreadPriorityMedium, + epicsThreadGetStackSize(epicsThreadStackBig), + (EPICSTHREADFUNC) dbCaTask,0); } void epicsShareAPI dbCaAddLink( struct link *plink) { - caLink *pca; + caLink *pca; - pca = (caLink*)dbCalloc(1,sizeof(caLink)); - pca->plink = plink; - plink->type = CA_LINK; - plink->value.pv_link.pvt = pca; - pca->lock = epicsMutexMustCreate(); - addAction(pca,CA_CONNECT); - return; + pca = (caLink*)dbCalloc(1,sizeof(caLink)); + pca->lock = epicsMutexMustCreate(); + epicsMutexMustLock(pca->lock); + pca->plink = plink; + plink->type = CA_LINK; + plink->value.pv_link.pvt = pca; + epicsMutexUnlock(pca->lock); + addAction(pca,CA_CONNECT); + return; } void epicsShareAPI dbCaRemoveLink( struct link *plink) { - caLink *pca = (caLink *)plink->value.pv_link.pvt; + caLink *pca = (caLink *)plink->value.pv_link.pvt; if(!pca) return; epicsMutexMustLock(pca->lock); @@ -116,67 +120,67 @@ void epicsShareAPI dbCaRemoveLink( struct link *plink) long epicsShareAPI dbCaGetLink(struct link *plink,short dbrType, void *pdest, - unsigned short *psevr,long *nelements) + unsigned short *psevr,long *nelements) { - caLink *pca = (caLink *)plink->value.pv_link.pvt; - long status = 0; - long (*pconvert)(); - short link_action = 0; + caLink *pca = (caLink *)plink->value.pv_link.pvt; + long status = 0; + long (*pconvert)(); + short link_action = 0; if(!pca) { - errlogPrintf("dbCaGetLink: record %s pv_link.pvt is NULL\n", - plink->value.pv_link.precord); - return(-1); + errlogPrintf("dbCaGetLink: record %s pv_link.pvt is NULL\n", + plink->value.pv_link.precord); + return(-1); } epicsMutexMustLock(pca->lock); if(!pca->chid || ca_state(pca->chid) != cs_conn) { - pca->sevr = INVALID_ALARM; - goto done; + pca->sevr = INVALID_ALARM; + goto done; } if(!ca_read_access(pca->chid)) { - pca->sevr = INVALID_ALARM; - goto done; + pca->sevr = INVALID_ALARM; + goto done; } if((pca->dbrType == DBR_ENUM) && (dbDBRnewToDBRold[dbrType] == DBR_STRING)){ - /*Must ask server for DBR_STRING*/ - if(!pca->pgetString) { - plink->value.pv_link.pvlMask |= pvlOptInpString; - link_action |= CA_MONITOR_STRING; - } - if(!pca->gotInString) { - pca->sevr = INVALID_ALARM; - goto done; - } - if(nelements) *nelements = 1; - pconvert=dbFastGetConvertRoutine[dbDBRoldToDBFnew[DBR_STRING]][dbrType]; - status = (*(pconvert))(pca->pgetString, pdest, 0); - goto done; + /*Must ask server for DBR_STRING*/ + if(!pca->pgetString) { + plink->value.pv_link.pvlMask |= pvlOptInpString; + link_action |= CA_MONITOR_STRING; + } + if(!pca->gotInString) { + pca->sevr = INVALID_ALARM; + goto done; + } + if(nelements) *nelements = 1; + pconvert=dbFastGetConvertRoutine[dbDBRoldToDBFnew[DBR_STRING]][dbrType]; + status = (*(pconvert))(pca->pgetString, pdest, 0); + goto done; } if(!pca->pgetNative) { - plink->value.pv_link.pvlMask |= pvlOptInpNative; - link_action |= CA_MONITOR_NATIVE; + plink->value.pv_link.pvlMask |= pvlOptInpNative; + link_action |= CA_MONITOR_NATIVE; } if(!pca->gotInNative){ - pca->sevr = INVALID_ALARM; - goto done; + pca->sevr = INVALID_ALARM; + goto done; } if(!nelements || *nelements == 1){ - pconvert= - dbFastGetConvertRoutine[dbDBRoldToDBFnew[pca->dbrType]][dbrType]; - (*(pconvert))(pca->pgetNative, pdest, 0); + pconvert= + dbFastGetConvertRoutine[dbDBRoldToDBFnew[pca->dbrType]][dbrType]; + (*(pconvert))(pca->pgetNative, pdest, 0); }else{ - unsigned long ntoget = *nelements; - struct dbAddr dbAddr; + unsigned long ntoget = *nelements; + struct dbAddr dbAddr; - if(ntoget > pca->nelements) ntoget = pca->nelements; - *nelements = ntoget; - pconvert = dbGetConvertRoutine[dbDBRoldToDBFnew[pca->dbrType]][dbrType]; - memset((void *)&dbAddr,0,sizeof(dbAddr)); - dbAddr.pfield = pca->pgetNative; - /*Following will only be used for pca->dbrType == DBR_STRING*/ - dbAddr.field_size = MAX_STRING_SIZE; - /*Ignore error return*/ - (*(pconvert))(&dbAddr,pdest,ntoget,ntoget,0); + if(ntoget > pca->nelements) ntoget = pca->nelements; + *nelements = ntoget; + pconvert = dbGetConvertRoutine[dbDBRoldToDBFnew[pca->dbrType]][dbrType]; + memset((void *)&dbAddr,0,sizeof(dbAddr)); + dbAddr.pfield = pca->pgetNative; + /*Following will only be used for pca->dbrType == DBR_STRING*/ + dbAddr.field_size = MAX_STRING_SIZE; + /*Ignore error return*/ + (*(pconvert))(&dbAddr,pdest,ntoget,ntoget,0); } done: if(psevr) *psevr = pca->sevr; @@ -186,60 +190,60 @@ done: } long epicsShareAPI dbCaPutLink(struct link *plink,short dbrType, - const void *psource,long nelements) + const void *psource,long nelements) { - caLink *pca = (caLink *)plink->value.pv_link.pvt; - long (*pconvert)(); - long status = 0; - short link_action = 0; + caLink *pca = (caLink *)plink->value.pv_link.pvt; + long (*pconvert)(); + long status = 0; + short link_action = 0; if(!pca) { - errlogPrintf("dbCaPutLink: record %s pv_link.pvt is NULL\n", - plink->value.pv_link.precord); - return(-1); + errlogPrintf("dbCaPutLink: record %s pv_link.pvt is NULL\n", + plink->value.pv_link.precord); + return(-1); } /* put the new value in */ epicsMutexMustLock(pca->lock); if(!pca->chid || ca_state(pca->chid) != cs_conn) { - epicsMutexUnlock(pca->lock); - return(-1); + epicsMutexUnlock(pca->lock); + return(-1); } if((pca->dbrType == DBR_ENUM) && (dbDBRnewToDBRold[dbrType] == DBR_STRING)){ - /*Must send DBR_STRING*/ - if(!pca->pputString) { - pca->pputString = dbCalloc(MAX_STRING_SIZE,sizeof(char)); - plink->value.pv_link.pvlMask |= pvlOptOutString; - } - pconvert=dbFastPutConvertRoutine[dbrType][dbDBRoldToDBFnew[DBR_STRING]]; - status = (*(pconvert))(psource,pca->pputString, 0); - link_action |= CA_WRITE_STRING; - pca->gotOutString = TRUE; - if(pca->newOutString) pca->nNoWrite++; - pca->newOutString = TRUE; + /*Must send DBR_STRING*/ + if(!pca->pputString) { + pca->pputString = dbCalloc(MAX_STRING_SIZE,sizeof(char)); + plink->value.pv_link.pvlMask |= pvlOptOutString; + } + pconvert=dbFastPutConvertRoutine[dbrType][dbDBRoldToDBFnew[DBR_STRING]]; + status = (*(pconvert))(psource,pca->pputString, 0); + link_action |= CA_WRITE_STRING; + pca->gotOutString = TRUE; + if(pca->newOutString) pca->nNoWrite++; + pca->newOutString = TRUE; } else { - if(!pca->pputNative) { - pca->pputNative = dbCalloc(pca->nelements, - dbr_value_size[ca_field_type(pca->chid)]); - plink->value.pv_link.pvlMask |= pvlOptOutString; - } - if(nelements == 1){ - pconvert = dbFastPutConvertRoutine - [dbrType][dbDBRoldToDBFnew[pca->dbrType]]; - status = (*(pconvert))(psource,pca->pputNative, 0); - }else{ - struct dbAddr dbAddr; - pconvert = dbPutConvertRoutine - [dbrType][dbDBRoldToDBFnew[pca->dbrType]]; - memset((void *)&dbAddr,0,sizeof(dbAddr)); - dbAddr.pfield = pca->pputNative; - /*Following only used for DBF_STRING*/ - dbAddr.field_size = MAX_STRING_SIZE; - status = (*(pconvert))(&dbAddr,psource,nelements,pca->nelements,0); - } - link_action |= CA_WRITE_NATIVE; - pca->gotOutNative = TRUE; - if(pca->newOutNative) pca->nNoWrite++; - pca->newOutNative = TRUE; + if(!pca->pputNative) { + pca->pputNative = dbCalloc(pca->nelements, + dbr_value_size[ca_field_type(pca->chid)]); + plink->value.pv_link.pvlMask |= pvlOptOutString; + } + if(nelements == 1){ + pconvert = dbFastPutConvertRoutine + [dbrType][dbDBRoldToDBFnew[pca->dbrType]]; + status = (*(pconvert))(psource,pca->pputNative, 0); + }else{ + struct dbAddr dbAddr; + pconvert = dbPutConvertRoutine + [dbrType][dbDBRoldToDBFnew[pca->dbrType]]; + memset((void *)&dbAddr,0,sizeof(dbAddr)); + dbAddr.pfield = pca->pputNative; + /*Following only used for DBF_STRING*/ + dbAddr.field_size = MAX_STRING_SIZE; + status = (*(pconvert))(&dbAddr,psource,nelements,pca->nelements,0); + } + link_action |= CA_WRITE_NATIVE; + pca->gotOutNative = TRUE; + if(pca->newOutNative) pca->nNoWrite++; + pca->newOutNative = TRUE; } epicsMutexUnlock(pca->lock); addAction(pca,link_action); @@ -247,27 +251,27 @@ long epicsShareAPI dbCaPutLink(struct link *plink,short dbrType, } long epicsShareAPI dbCaGetAttributes(const struct link *plink, - void (*callback)(void *usrPvt),void *usrPvt) + void (*callback)(void *usrPvt),void *usrPvt) { - caLink *pca; - long status = 0; - short link_action = 0; + caLink *pca; + long status = 0; + short link_action = 0; caAttributes *pcaAttributes; if(!plink || (plink->type!=CA_LINK)) { - errlogPrintf("dbCaGetAttributes: called for non CA_LINK\n"); - return(-1); + errlogPrintf("dbCaGetAttributes: called for non CA_LINK\n"); + return(-1); } pca = (caLink *)plink->value.pv_link.pvt; if(!pca) { - errlogPrintf("dbCaGetAttributes: record %s pv_link.pvt is NULL\n", - plink->value.pv_link.precord); - return(-1); + errlogPrintf("dbCaGetAttributes: record %s pv_link.pvt is NULL\n", + plink->value.pv_link.precord); + return(-1); } if(pca->pcaAttributes) { - errlogPrintf("dbCaGetAttributes: record %s duplicate call\n", - plink->value.pv_link.precord); - return(-1); + errlogPrintf("dbCaGetAttributes: record %s duplicate call\n", + plink->value.pv_link.precord); + return(-1); } pcaAttributes = dbCalloc(1,sizeof(caAttributes)); pcaAttributes->callback = callback; @@ -282,7 +286,7 @@ long epicsShareAPI dbCaGetAttributes(const struct link *plink, caAttributes *getpcaAttributes(const struct link *plink) { - caLink *pca; + caLink *pca; if(!plink || (plink->type!=CA_LINK)) return(NULL); pca = (caLink *)plink->value.pv_link.pvt; @@ -355,7 +359,7 @@ long epicsShareAPI dbCaGetUnits( long epicsShareAPI dbCaGetNelements( const struct link *plink,long *nelements) { - caLink *pca; + caLink *pca; if(!plink) return(-1); if(plink->type != CA_LINK) return(-1); @@ -368,7 +372,7 @@ long epicsShareAPI dbCaGetNelements( long epicsShareAPI dbCaGetSevr( const struct link *plink,short *severity) { - caLink *pca; + caLink *pca; if(!plink) return(-1); if(plink->type != CA_LINK) return(-1); @@ -381,7 +385,7 @@ long epicsShareAPI dbCaGetSevr( long epicsShareAPI dbCaGetTimeStamp( const struct link *plink,epicsTimeStamp *pstamp) { - caLink *pca; + caLink *pca; if(!plink) return(-1); if(plink->type != CA_LINK) return(-1); @@ -394,7 +398,7 @@ long epicsShareAPI dbCaGetTimeStamp( int epicsShareAPI dbCaIsLinkConnected( const struct link *plink) { - caLink *pca; + caLink *pca; if(!plink) return(FALSE); if(plink->type != CA_LINK) return(FALSE); @@ -404,10 +408,11 @@ int epicsShareAPI dbCaIsLinkConnected( if(ca_state(pca->chid)==cs_conn) return(TRUE); return(FALSE); } + int epicsShareAPI dbCaGetLinkDBFtype( const struct link *plink) { - caLink *pca; + caLink *pca; if(!plink) return(-1); if(plink->type != CA_LINK) return(-1); @@ -415,16 +420,16 @@ int epicsShareAPI dbCaGetLinkDBFtype( if(!pca) return(-1); if(!pca->chid) return(-1); if(ca_state(pca->chid)==cs_conn) - return(dbDBRoldToDBFnew[ca_field_type(pca->chid)]); + return(dbDBRoldToDBFnew[ca_field_type(pca->chid)]); return(-1); } static void exceptionCallback(struct exception_handler_args args) { - chid chid = args.chid; + chid chid = args.chid; long stat = args.stat; /* Channel access status code*/ - const char *channel; + const char *channel; const char *context; static char *unknown = "unknown"; const char *nativeType; @@ -453,7 +458,7 @@ static void exceptionCallback(struct exception_handler_args args) (readAccess ? "readAccess" : "noReadAccess"), (writeAccess ? "writeAccess" : "noWriteAccess")); } - + static void eventCallback(struct event_handler_args arg) { caLink *pca = (caLink *)arg.usr; @@ -474,10 +479,10 @@ static void eventCallback(struct event_handler_args arg) if(precord) { if((arg.status!=ECA_NORDACCESS) && (arg.status!=ECA_GETFAIL)) errlogPrintf("dbCa: eventCallback record %s error %s\n", - precord->name,ca_message(arg.status)); + precord->name,ca_message(arg.status)); } else { errlogPrintf("dbCa: eventCallback error %s\n", - ca_message(arg.status)); + ca_message(arg.status)); } goto done; } @@ -515,69 +520,69 @@ static void eventCallback(struct event_handler_args arg) scanOnce(precord); } done: - epicsMutexUnlock(pca->lock); + epicsMutexUnlock(pca->lock); } static void getAttribEventCallback(struct event_handler_args arg) { - caLink *pca = (caLink *)arg.usr; - struct link *plink; + caLink *pca = (caLink *)arg.usr; + struct link *plink; const struct dbr_ctrl_double *dbr; - caAttributes *pcaAttributes = NULL; + caAttributes *pcaAttributes = NULL; - if(!pca) { - errlogPrintf("getAttribEventCallback why was arg.usr NULL\n"); - return; - } - epicsMutexMustLock(pca->lock); - plink = pca->plink; - if(!plink) goto done; - if(!arg.dbr) { - errlogPrintf("getAttribEventCallback why was arg.dbr NULL\n"); - goto done; - } - dbr = arg.dbr; - pcaAttributes = pca->pcaAttributes; - if(!pcaAttributes) goto done; - pcaAttributes->data = *dbr; /*copy entire structure*/ - pcaAttributes->gotData = TRUE; - (pcaAttributes->callback)(pcaAttributes->usrPvt); + if(!pca) { + errlogPrintf("getAttribEventCallback why was arg.usr NULL\n"); + return; + } + epicsMutexMustLock(pca->lock); + plink = pca->plink; + if(!plink) goto done; + if(!arg.dbr) { + errlogPrintf("getAttribEventCallback why was arg.dbr NULL\n"); + goto done; + } + dbr = arg.dbr; + pcaAttributes = pca->pcaAttributes; + if(!pcaAttributes) goto done; + pcaAttributes->data = *dbr; /*copy entire structure*/ + pcaAttributes->gotData = TRUE; + (pcaAttributes->callback)(pcaAttributes->usrPvt); done: - epicsMutexUnlock(pca->lock); + epicsMutexUnlock(pca->lock); } static void accessRightsCallback(struct access_rights_handler_args arg) { - caLink *pca = (caLink *)ca_puser(arg.chid); - struct link *plink; + caLink *pca = (caLink *)ca_puser(arg.chid); + struct link *plink; - if(!pca) { - errlogPrintf("accessRightsCallback why was arg.usr NULL\n"); - return; - } - if(ca_state(pca->chid) != cs_conn) return;/*connectionCallback will handle*/ - epicsMutexMustLock(pca->lock); - if(ca_read_access(arg.chid) || ca_write_access(arg.chid)) goto done; - plink = pca->plink; - if(plink) { - struct pv_link *ppv_link = &(plink->value.pv_link); - dbCommon *precord = ppv_link->precord; + if(!pca) { + errlogPrintf("accessRightsCallback why was arg.usr NULL\n"); + return; + } + if(ca_state(pca->chid) != cs_conn) return;/*connectionCallback will handle*/ + epicsMutexMustLock(pca->lock); + if(ca_read_access(arg.chid) || ca_write_access(arg.chid)) goto done; + plink = pca->plink; + if(plink) { + struct pv_link *ppv_link = &(plink->value.pv_link); + dbCommon *precord = ppv_link->precord; - if(precord) { - if((ppv_link->pvlMask&pvlOptCP) - || ((ppv_link->pvlMask&pvlOptCPP)&&(precord->scan==0))) - scanOnce(precord); - } - } + if(precord) { + if((ppv_link->pvlMask&pvlOptCP) + || ((ppv_link->pvlMask&pvlOptCPP)&&(precord->scan==0))) + scanOnce(precord); + } + } done: - epicsMutexUnlock(pca->lock); + epicsMutexUnlock(pca->lock); } static void connectionCallback(struct connection_handler_args arg) { - caLink *pca; - short link_action = 0; - struct link *plink; + caLink *pca; + short link_action = 0; + struct link *plink; pca = ca_puser(arg.chid); if(!pca) return; @@ -585,44 +590,44 @@ static void connectionCallback(struct connection_handler_args arg) plink = pca->plink; if(!plink) goto done; if(ca_state(arg.chid) != cs_conn){ - struct pv_link *ppv_link = &(plink->value.pv_link); - dbCommon *precord = ppv_link->precord; + struct pv_link *ppv_link = &(plink->value.pv_link); + dbCommon *precord = ppv_link->precord; - pca->nDisconnect++; - if(precord) { - if((ppv_link->pvlMask&pvlOptCP) - || ((ppv_link->pvlMask&pvlOptCPP)&&(precord->scan==0))) - scanOnce(precord); - } - goto done; + pca->nDisconnect++; + if(precord) { + if((ppv_link->pvlMask&pvlOptCP) + || ((ppv_link->pvlMask&pvlOptCPP)&&(precord->scan==0))) + scanOnce(precord); + } + goto done; } if(pca->gotFirstConnection) { - if((pca->nelements != ca_element_count(arg.chid)) - || (pca->dbrType != ca_field_type(arg.chid))){ - /* field type or nelements changed */ - /*Only safe thing is to delete old caLink and allocate a new one*/ - pca->plink = 0; - plink->value.pv_link.pvt = 0; - epicsMutexUnlock(pca->lock); - addAction(pca,CA_DELETE); - dbCaAddLink(plink); - return; - } + if((pca->nelements != ca_element_count(arg.chid)) + || (pca->dbrType != ca_field_type(arg.chid))){ + /* field type or nelements changed */ + /*Only safe thing is to delete old caLink and allocate a new one*/ + pca->plink = 0; + plink->value.pv_link.pvt = 0; + epicsMutexUnlock(pca->lock); + addAction(pca,CA_DELETE); + dbCaAddLink(plink); + return; + } } pca->gotFirstConnection = TRUE; pca->nelements = ca_element_count(arg.chid); pca->dbrType = ca_field_type(arg.chid); if((plink->value.pv_link.pvlMask & pvlOptInpNative) && (!pca->pgetNative)){ - link_action |= CA_MONITOR_NATIVE; + link_action |= CA_MONITOR_NATIVE; } if((plink->value.pv_link.pvlMask & pvlOptInpString) && (!pca->pgetString)){ - link_action |= CA_MONITOR_STRING; + link_action |= CA_MONITOR_STRING; } if((plink->value.pv_link.pvlMask & pvlOptOutNative) && (pca->gotOutNative)){ - link_action |= CA_WRITE_NATIVE; + link_action |= CA_WRITE_NATIVE; } if((plink->value.pv_link.pvlMask & pvlOptOutString) && (pca->gotOutString)){ - link_action |= CA_WRITE_STRING; + link_action |= CA_WRITE_STRING; } if(pca->pcaAttributes) link_action |= CA_GET_ATTRIBUTES; done: @@ -633,103 +638,103 @@ done: void dbCaTask() { static const int enablePreemption = 1u; - caLink *pca; - short link_action; - int status; + caLink *pca; + short link_action; + int status; taskwdInsert(epicsThreadGetIdSelf(),NULL,NULL); SEVCHK(ca_context_create(enablePreemption), "dbCaTask calling ca_context_create"); SEVCHK(ca_add_exception_event(exceptionCallback,NULL), - "ca_add_exception_event"); + "ca_add_exception_event"); /*Dont do anything until iocInit initializes database*/ while(!interruptAccept) epicsThreadSleep(.1); /* channel access event loop */ while (TRUE){ - epicsEventMustWait(caWakeupSem); - while(TRUE) { /* process all requests in caList*/ - epicsMutexMustLock(caListSem); - if((pca = (caLink *)ellFirst(&caList))){/*Take off list head*/ - ellDelete(&caList,&pca->node); - link_action = pca->link_action; - pca->link_action = 0; - epicsMutexUnlock(caListSem); /*Give it back immediately*/ - if(link_action&CA_DELETE) {/*This must be first*/ - if(pca->chid) ca_clear_channel(pca->chid); - free(pca->pgetNative); - free(pca->pputNative); - free(pca->pgetString); - free(pca->pputString); - free(pca->pcaAttributes); - epicsMutexDestroy(pca->lock); - free(pca); - continue; /*No other link_action makes sense*/ - } - if(link_action&CA_CONNECT) { - status = ca_search_and_connect( - pca->plink->value.pv_link.pvname, - &(pca->chid), - connectionCallback,(void *)pca); - if(status!=ECA_NORMAL) { - errlogPrintf("dbCaTask ca_search_and_connect %s\n", - ca_message(status)); - continue; - } - status = ca_replace_access_rights_event(pca->chid, - accessRightsCallback); - if(status!=ECA_NORMAL) - errlogPrintf("dbCaTask replace_access_rights_event %s\n", - ca_message(status)); - continue; /*Other options must wait until connect*/ - } - if(ca_state(pca->chid) != cs_conn) continue; - if(link_action&CA_WRITE_NATIVE) { - status = ca_array_put( - pca->dbrType,pca->nelements, - pca->chid,pca->pputNative); - if(status==ECA_NORMAL) pca->newOutNative = FALSE; - } - if(link_action&CA_WRITE_STRING) { - status = ca_array_put( - DBR_STRING,1, - pca->chid,pca->pputString); - if(status==ECA_NORMAL) pca->newOutString = FALSE; - } - if(link_action&CA_MONITOR_NATIVE) { - short element_size; - - element_size = dbr_value_size[ca_field_type(pca->chid)]; - pca->pgetNative = dbCalloc(pca->nelements,element_size); - 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); - if(status!=ECA_NORMAL) - errlogPrintf("dbCaTask ca_add_array_event %s\n", - ca_message(status)); - } - if(link_action&CA_MONITOR_STRING) { - pca->pgetString = dbCalloc(MAX_STRING_SIZE,sizeof(char)); - status = ca_add_array_event(DBR_TIME_STRING,1, - 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_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)); - } - } else { /* caList was empty */ - epicsMutexUnlock(caListSem); - break; /*caList is empty*/ - } - } - SEVCHK(ca_flush_io(),"dbCaTask"); + epicsEventMustWait(caWakeupSem); + while(TRUE) { /* process all requests in caList*/ + epicsMutexMustLock(caListSem); + if((pca = (caLink *)ellFirst(&caList))){/*Take off list head*/ + ellDelete(&caList,&pca->node); + link_action = pca->link_action; + pca->link_action = 0; + epicsMutexUnlock(caListSem); /*Give it back immediately*/ + if(link_action&CA_DELETE) {/*This must be first*/ + if(pca->chid) ca_clear_channel(pca->chid); + free(pca->pgetNative); + free(pca->pputNative); + free(pca->pgetString); + free(pca->pputString); + free(pca->pcaAttributes); + epicsMutexDestroy(pca->lock); + free(pca); + continue; /*No other link_action makes sense*/ + } + if(link_action&CA_CONNECT) { + status = ca_search_and_connect( + pca->plink->value.pv_link.pvname, + &(pca->chid), + connectionCallback,(void *)pca); + if(status!=ECA_NORMAL) { + errlogPrintf("dbCaTask ca_search_and_connect %s\n", + ca_message(status)); + continue; + } + status = ca_replace_access_rights_event(pca->chid, + accessRightsCallback); + if(status!=ECA_NORMAL) + errlogPrintf("dbCaTask replace_access_rights_event %s\n", + ca_message(status)); + continue; /*Other options must wait until connect*/ + } + if(ca_state(pca->chid) != cs_conn) continue; + if(link_action&CA_WRITE_NATIVE) { + status = ca_array_put( + pca->dbrType,pca->nelements, + pca->chid,pca->pputNative); + if(status==ECA_NORMAL) pca->newOutNative = FALSE; + } + if(link_action&CA_WRITE_STRING) { + status = ca_array_put( + DBR_STRING,1, + pca->chid,pca->pputString); + if(status==ECA_NORMAL) pca->newOutString = FALSE; + } + if(link_action&CA_MONITOR_NATIVE) { + short element_size; + + element_size = dbr_value_size[ca_field_type(pca->chid)]; + pca->pgetNative = dbCalloc(pca->nelements,element_size); + 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); + if(status!=ECA_NORMAL) + errlogPrintf("dbCaTask ca_add_array_event %s\n", + ca_message(status)); + } + if(link_action&CA_MONITOR_STRING) { + pca->pgetString = dbCalloc(MAX_STRING_SIZE,sizeof(char)); + status = ca_add_array_event(DBR_TIME_STRING,1, + 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_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)); + } + } else { /* caList was empty */ + epicsMutexUnlock(caListSem); + break; /*caList is empty*/ + } + } + SEVCHK(ca_flush_io(),"dbCaTask"); } }