Add dbLinkDoLocked() support

New lset method, implemented in all link types.
Includes a test for the dbCa implementation.
This commit is contained in:
Andrew Johnson
2017-04-19 16:44:11 -05:00
parent 17bd1ae6d0
commit d2db634ed2
10 changed files with 103 additions and 9 deletions

View File

@@ -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)

View File

@@ -135,6 +135,5 @@ static lset dbConst_lset = {
NULL, NULL,
NULL, NULL,
NULL, NULL,
NULL
NULL, NULL
};

View File

@@ -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
};

View File

@@ -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,

View File

@@ -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,

View File

@@ -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();

View File

@@ -146,6 +146,7 @@ static lset lsetZ = {
&z_putval,
NULL, /* putasync */
NULL, /* forward */
NULL, /* doLocked */
};
static

View File

@@ -73,7 +73,7 @@ static lset xlink_lset = {
NULL, NULL,
NULL, NULL,
NULL, NULL,
NULL
NULL, NULL
};
static jlif xlinkIf = {

View File

@@ -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 = {

View File

@@ -551,7 +551,7 @@ static lset lnkConst_lset = {
NULL, NULL,
NULL, NULL,
NULL, NULL,
NULL
NULL, NULL
};
static jlif lnkConstIf = {