diff --git a/src/ioc/db/dbCa.c b/src/ioc/db/dbCa.c index 20b012178..a7b4511f1 100644 --- a/src/ioc/db/dbCa.c +++ b/src/ioc/db/dbCa.c @@ -227,6 +227,22 @@ void dbCaSync(void) epicsEventDestroy(wake); } +epicsShareFunc unsigned long dbCaGetUpdateCount(struct link *plink) +{ + caLink *pca = (caLink *)plink->value.pv_link.pvt; + unsigned long ret; + + if (!pca) return (unsigned long)-1; + + epicsMutexMustLock(pca->lock); + + ret = pca->nUpdate; + + epicsMutexUnlock(pca->lock); + + return ret; +} + void dbCaCallbackProcess(void *userPvt) { struct link *plink = (struct link *)userPvt; @@ -805,6 +821,7 @@ static void eventCallback(struct event_handler_args arg) epicsMutexMustLock(pca->lock); plink = pca->plink; if (!plink) goto done; + pca->nUpdate++; monitor = pca->monitor; userPvt = pca->userPvt; precord = plink->precord; diff --git a/src/ioc/db/dbCa.h b/src/ioc/db/dbCa.h index f1cfada40..a33c32023 100644 --- a/src/ioc/db/dbCa.h +++ b/src/ioc/db/dbCa.h @@ -49,6 +49,7 @@ extern struct ca_client_context * dbCaClientContext; #ifdef EPICS_DBCA_PRIVATE_API epicsShareFunc void dbCaSync(void); +epicsShareFunc unsigned long dbCaGetUpdateCount(struct link *plink); #endif /* These macros are for backwards compatibility */ diff --git a/src/ioc/db/dbCaPvt.h b/src/ioc/db/dbCaPvt.h index 663688d9c..454ead5ac 100644 --- a/src/ioc/db/dbCaPvt.h +++ b/src/ioc/db/dbCaPvt.h @@ -90,6 +90,7 @@ typedef struct caLink /* The following are for dbcar*/ unsigned long nDisconnect; unsigned long nNoWrite; /*only modified by dbCaPutLink*/ + unsigned long nUpdate; }caLink; #endif /* INC_dbCaPvt_H */ diff --git a/src/ioc/db/test/dbCaLinkTest.c b/src/ioc/db/test/dbCaLinkTest.c index e1955a5ad..5c823c4e0 100644 --- a/src/ioc/db/test/dbCaLinkTest.c +++ b/src/ioc/db/test/dbCaLinkTest.c @@ -13,6 +13,8 @@ #include #include +#define EPICS_DBCA_PRIVATE_API + #include "epicsString.h" #include "dbUnitTest.h" #include "epicsThread.h" @@ -42,50 +44,11 @@ epicsShareExtern short epicsShareAPI ca_field_type (chid chan); void dbTestIoc_registerRecordDeviceDriver(struct dbBase *); -static epicsEventId waitEvent; -static unsigned waitCounter; - static -void waitCB(void *unused) +void waitForUpdateN(DBLINK *plink, unsigned long n) { - if(waitEvent) - epicsEventMustTrigger(waitEvent); - waitCounter++; /* TODO: atomic */ -} - -static -void startWait(DBLINK *plink) -{ - caLink *pca = plink->value.pv_link.pvt; - - assert(!waitEvent); - waitEvent = epicsEventMustCreate(epicsEventEmpty); - - assert(pca); - epicsMutexMustLock(pca->lock); - assert(!pca->monitor && !pca->userPvt); - pca->monitor = &waitCB; - epicsMutexUnlock(pca->lock); - testDiag("Preparing to wait on pca=%p", pca); -} - -static -void waitForUpdate(DBLINK *plink) -{ - caLink *pca = plink->value.pv_link.pvt; - - assert(pca); - - testDiag("Waiting on pca=%p", pca); - epicsEventMustWait(waitEvent); - - epicsMutexMustLock(pca->lock); - pca->monitor = NULL; - pca->userPvt = NULL; - epicsMutexUnlock(pca->lock); - - epicsEventDestroy(waitEvent); - waitEvent = NULL; + while(dbCaGetUpdateCount(plink)type==CA_LINK); - startWait(psrclnk); + waitForUpdateN(psrclnk, 1); dbScanLock((dbCommon*)ptarg); ptarg->val = 42; db_post_events(ptarg, &ptarg->val, DBE_VALUE|DBE_ALARM|DBE_ARCHIVE); dbScanUnlock((dbCommon*)ptarg); - waitForUpdate(psrclnk); + waitForUpdateN(psrclnk, 2); dbScanLock((dbCommon*)psrc); /* local CA_LINK connects immediately */ @@ -200,14 +158,14 @@ static void testStringLink(void) testOk1(psrclnk->type==CA_LINK); - startWait(psrclnk); + waitForUpdateN(psrclnk, 1); dbScanLock((dbCommon*)ptarg); strcpy(ptarg->desc, "hello"); db_post_events(ptarg, &ptarg->desc, DBE_VALUE|DBE_ALARM|DBE_ARCHIVE); dbScanUnlock((dbCommon*)ptarg); - waitForUpdate(psrclnk); + waitForUpdateN(psrclnk, 2); dbScanLock((dbCommon*)psrc); /* local CA_LINK connects immediately */ @@ -231,9 +189,13 @@ static void testStringLink(void) testdbCleanup(); } +static epicsEventId waitEvent; +static unsigned waitCounter; + static void wasproc(xRecord *prec) { - waitCB(NULL); + waitCounter++; + epicsEventTrigger(waitEvent); } static void testCP(void) @@ -262,6 +224,7 @@ static void testCP(void) eltc(0); testIocInitOk(); eltc(1); + dbCaSync(); epicsEventMustWait(waitEvent); @@ -380,6 +343,8 @@ static void testArrayLink(unsigned nsrc, unsigned ntarg) testIocInitOk(); eltc(1); + waitForUpdateN(psrclnk, 1); + bufsrc = psrc->bptr; buftarg= ptarg->bptr; @@ -393,15 +358,13 @@ static void testArrayLink(unsigned nsrc, unsigned ntarg) tmpbuf = callocMustSucceed(num_max, sizeof(*tmpbuf), "tmpbuf"); - startWait(psrclnk); - dbScanLock((dbCommon*)ptarg); fillArray(buftarg, ptarg->nelm, 1); ptarg->nord = ptarg->nelm; db_post_events(ptarg, ptarg->bptr, DBE_VALUE|DBE_ALARM|DBE_ARCHIVE); dbScanUnlock((dbCommon*)ptarg); - waitForUpdate(psrclnk); + waitForUpdateN(psrclnk, 2); dbScanLock((dbCommon*)psrc); testDiag("fetch source.INP into source.BPTR"); @@ -471,7 +434,8 @@ static void softarr(arrRecord *prec) if(nReq>0) testDiag("%s.VAL[0] - %f", prec->name, *(double*)prec->bptr); } - waitCB(NULL); + waitCounter++; + epicsEventTrigger(waitEvent); } static void testreTargetTypeChange(void)