Add dbLinkDoLocked() support
New lset method, implemented in all link types. Includes a test for the dbCa implementation.
This commit is contained in:
@@ -684,6 +684,17 @@ static long getUnits(const struct link *plink,
|
||||
return gotAttributes ? 0 : -1;
|
||||
}
|
||||
|
||||
static long doLocked(struct link *plink, dbLinkUserCallback rtn, void *priv)
|
||||
{
|
||||
caLink *pca;
|
||||
long status;
|
||||
|
||||
pcaGetCheck
|
||||
status = rtn(plink, priv);
|
||||
epicsMutexUnlock(pca->lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
static void scanComplete(void *raw, dbCommon *prec)
|
||||
{
|
||||
caLink *pca = raw;
|
||||
@@ -727,7 +738,7 @@ static lset dbCa_lset = {
|
||||
getPrecision, getUnits,
|
||||
getAlarm, getTimeStamp,
|
||||
dbCaPutLink, dbCaPutAsync,
|
||||
scanForward
|
||||
scanForward, doLocked
|
||||
};
|
||||
|
||||
static void connectionCallback(struct connection_handler_args arg)
|
||||
|
||||
@@ -135,6 +135,5 @@ static lset dbConst_lset = {
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL
|
||||
NULL, NULL
|
||||
};
|
||||
|
||||
|
||||
@@ -337,6 +337,11 @@ static void dbDbScanFwdLink(struct link *plink)
|
||||
dbScanPassive(precord, paddr->precord);
|
||||
}
|
||||
|
||||
static long doLocked(struct link *plink, dbLinkUserCallback rtn, void *priv)
|
||||
{
|
||||
return rtn(plink, priv);
|
||||
}
|
||||
|
||||
static lset dbDb_lset = {
|
||||
0, 0, /* not Constant, not Volatile */
|
||||
NULL, dbDbRemoveLink,
|
||||
@@ -348,6 +353,5 @@ static lset dbDb_lset = {
|
||||
dbDbGetPrecision, dbDbGetUnits,
|
||||
dbDbGetAlarm, dbDbGetTimeStamp,
|
||||
dbDbPutValue, NULL,
|
||||
dbDbScanFwdLink
|
||||
dbDbScanFwdLink, doLocked
|
||||
};
|
||||
|
||||
|
||||
@@ -414,6 +414,18 @@ void dbScanFwdLink(struct link *plink)
|
||||
plset->scanForward(plink);
|
||||
}
|
||||
|
||||
long dbLinkDoLocked(struct link *plink, dbLinkUserCallback rtn,
|
||||
void *priv)
|
||||
{
|
||||
lset *plset = plink->lset;
|
||||
|
||||
if (!rtn || !plset || !plset->doLocked)
|
||||
return S_db_noLSET;
|
||||
|
||||
return plset->doLocked(plink, rtn, priv);
|
||||
}
|
||||
|
||||
|
||||
/* Helper functions for long string support */
|
||||
|
||||
long dbGetLinkLS(struct link *plink, char *pbuffer, epicsUInt32 size,
|
||||
|
||||
@@ -27,6 +27,8 @@ extern "C" {
|
||||
|
||||
struct dbLocker;
|
||||
|
||||
typedef long (*dbLinkUserCallback)(struct link *plink, void *priv);
|
||||
|
||||
typedef struct lset {
|
||||
/* Characteristics of the link type */
|
||||
const unsigned isConstant:1;
|
||||
@@ -71,6 +73,9 @@ typedef struct lset {
|
||||
|
||||
/* Process */
|
||||
void (*scanForward)(struct link *plink);
|
||||
|
||||
/* Atomicity */
|
||||
long (*doLocked)(struct link *plink, dbLinkUserCallback rtn, void *priv);
|
||||
} lset;
|
||||
|
||||
#define dbGetSevr(link, sevr) \
|
||||
@@ -117,6 +122,9 @@ epicsShareFunc long dbPutLinkAsync(struct link *plink, short dbrType,
|
||||
const void *pbuffer, long nRequest);
|
||||
epicsShareFunc void dbScanFwdLink(struct link *plink);
|
||||
|
||||
epicsShareFunc long dbLinkDoLocked(struct link *plink, dbLinkUserCallback rtn,
|
||||
void *priv);
|
||||
|
||||
epicsShareFunc long dbLoadLinkLS(struct link *plink, char *pbuffer,
|
||||
epicsUInt32 size, epicsUInt32 *plen);
|
||||
epicsShareFunc long dbGetLinkLS(struct link *plink, char *pbuffer,
|
||||
|
||||
@@ -107,6 +107,39 @@ void putLink(DBLINK *plink, short dbr, const void*buf, long nReq)
|
||||
waitEvent = NULL;
|
||||
}
|
||||
|
||||
static long getTwice(struct link *psrclnk, void *dummy)
|
||||
{
|
||||
epicsInt32 val1, val2;
|
||||
long status = dbGetLink(psrclnk, DBR_LONG, &val1, 0, 0);
|
||||
|
||||
if (status) return status;
|
||||
|
||||
epicsThreadSleep(0.5);
|
||||
status = dbGetLink(psrclnk, DBR_LONG, &val2, 0, 0);
|
||||
if (status) return status;
|
||||
|
||||
testDiag("val1 = %d, val2 = %d", val1, val2);
|
||||
return (val1 == val2) ? 0 : -1;
|
||||
}
|
||||
|
||||
static void countUp(void *parm)
|
||||
{
|
||||
xRecord *ptarg = (xRecord *)parm;
|
||||
epicsInt32 val;
|
||||
|
||||
for (val = 1; val < 10; val++) {
|
||||
dbScanLock((dbCommon*)ptarg);
|
||||
ptarg->val = val;
|
||||
db_post_events(ptarg, &ptarg->val, DBE_VALUE|DBE_ALARM|DBE_ARCHIVE);
|
||||
dbScanUnlock((dbCommon*)ptarg);
|
||||
|
||||
epicsThreadSleep(0.1);
|
||||
}
|
||||
|
||||
if (waitEvent)
|
||||
epicsEventMustTrigger(waitEvent);
|
||||
}
|
||||
|
||||
static void testNativeLink(void)
|
||||
{
|
||||
xRecord *psrc, *ptarg;
|
||||
@@ -166,6 +199,27 @@ static void testNativeLink(void)
|
||||
testOk1(ptarg->val==1010);
|
||||
dbScanUnlock((dbCommon*)ptarg);
|
||||
|
||||
assert(!waitEvent);
|
||||
waitEvent = epicsEventMustCreate(epicsEventEmpty);
|
||||
|
||||
/* Start counter */
|
||||
epicsThreadCreate("countUp", epicsThreadPriorityHigh,
|
||||
epicsThreadGetStackSize(epicsThreadStackSmall), countUp, ptarg);
|
||||
|
||||
dbScanLock((dbCommon*)psrc);
|
||||
/* Check that unlocked gets change */
|
||||
temp = getTwice(psrclnk, NULL);
|
||||
testOk(temp == -1, "unlocked, getTwice returned %d (-1)", temp);
|
||||
|
||||
/* Check locked gets are atomic */
|
||||
temp = dbLinkDoLocked(psrclnk, getTwice, NULL);
|
||||
testOk(temp == 0, "locked, getTwice returned %d (0)", temp);
|
||||
dbScanUnlock((dbCommon*)psrc);
|
||||
|
||||
epicsEventMustWait(waitEvent);
|
||||
epicsEventDestroy(waitEvent);
|
||||
waitEvent = NULL;
|
||||
|
||||
testIocShutdownOk();
|
||||
|
||||
testdbCleanup();
|
||||
@@ -598,7 +652,7 @@ static void testCAC(void)
|
||||
|
||||
MAIN(dbCaLinkTest)
|
||||
{
|
||||
testPlan(99);
|
||||
testPlan(101);
|
||||
testNativeLink();
|
||||
testStringLink();
|
||||
testCP();
|
||||
|
||||
@@ -146,6 +146,7 @@ static lset lsetZ = {
|
||||
&z_putval,
|
||||
NULL, /* putasync */
|
||||
NULL, /* forward */
|
||||
NULL, /* doLocked */
|
||||
};
|
||||
|
||||
static
|
||||
|
||||
@@ -73,7 +73,7 @@ static lset xlink_lset = {
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL
|
||||
NULL, NULL
|
||||
};
|
||||
|
||||
static jlif xlinkIf = {
|
||||
|
||||
@@ -597,6 +597,11 @@ static long lnkCalc_getAlarm(const struct link *plink, epicsEnum16 *status,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long doLocked(struct link *plink, dbLinkUserCallback rtn, void *priv)
|
||||
{
|
||||
return rtn(plink, priv);
|
||||
}
|
||||
|
||||
|
||||
/************************* Interface Tables *************************/
|
||||
|
||||
@@ -610,7 +615,7 @@ static lset lnkCalc_lset = {
|
||||
lnkCalc_getPrecision, lnkCalc_getUnits,
|
||||
lnkCalc_getAlarm, NULL,
|
||||
NULL, NULL,
|
||||
NULL
|
||||
NULL, doLocked
|
||||
};
|
||||
|
||||
static jlif lnkCalcIf = {
|
||||
|
||||
@@ -551,7 +551,7 @@ static lset lnkConst_lset = {
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL
|
||||
NULL, NULL
|
||||
};
|
||||
|
||||
static jlif lnkConstIf = {
|
||||
|
||||
Reference in New Issue
Block a user