dbAccess: multi-locking in dbPutFieldLink

Use new locking API in dbPutFieldLink()
Adjust dbAddLink() and dbRemoveLink()
to pass a dbLocker* through to lockSet merge/split
This commit is contained in:
Michael Davidsaver
2015-03-24 14:18:11 -04:00
parent ffd188bea3
commit 8af3ffb653
3 changed files with 34 additions and 19 deletions

View File

@@ -32,6 +32,7 @@
#include "epicsThread.h"
#include "epicsTime.h"
#include "errlog.h"
#include "epicsSpin.h"
#include "errMdef.h"
#define epicsExportSharedSymbols
@@ -50,7 +51,7 @@
#include "dbFldTypes.h"
#include "dbFldTypes.h"
#include "dbLink.h"
#include "dbLock.h"
#include "dbLockPvt.h"
#include "dbNotify.h"
#include "dbScan.h"
#include "dbServer.h"
@@ -944,6 +945,8 @@ static long dbPutFieldLink(DBADDR *paddr,
dbLinkInfo link_info;
DBADDR *pdbaddr = NULL;
dbCommon *precord = paddr->precord;
dbCommon *lockrecs[3];
dbLocker locker;
dbFldDes *pfldDes = paddr->pfldDes;
long special = paddr->special;
struct link *plink = (struct link *)paddr->pfield;
@@ -956,6 +959,8 @@ static long dbPutFieldLink(DBADDR *paddr,
int isDevLink;
short scan;
STATIC_ASSERT(DBLOCKER_NALLOC>=3);
switch (dbrType) {
case DBR_CHAR:
case DBR_UCHAR:
@@ -992,10 +997,13 @@ static long dbPutFieldLink(DBADDR *paddr,
isDevLink = ellCount(&precord->rdes->devList) > 0 &&
pfldDes->isDevLink;
dbLockSetGblLock();
dbLockSetRecordLock(precord);
if (pdbaddr)
dbLockSetRecordLock(pdbaddr->precord);
memset(&locker, 0, sizeof(locker));
lockrecs[0] = precord;
lockrecs[1] = pdbaddr ? pdbaddr->precord : NULL;
lockrecs[2] = NULL;
dbLockerPrepare(&locker, lockrecs, 3);
dbScanLockMany(&locker);
scan = precord->scan;
@@ -1044,7 +1052,7 @@ static long dbPutFieldLink(DBADDR *paddr,
switch (plink->type) { /* Old link type */
case DB_LINK:
case CA_LINK:
dbRemoveLink(plink);
dbRemoveLink(&locker, precord, plink);
break;
case PV_LINK:
@@ -1091,7 +1099,7 @@ static long dbPutFieldLink(DBADDR *paddr,
switch (plink->type) { /* New link type */
case PV_LINK:
dbAddLink(precord, plink, pfldDes->field_type, pdbaddr);
dbAddLink(&locker, precord, plink, pfldDes->field_type, pdbaddr);
break;
case CONSTANT:
@@ -1121,7 +1129,8 @@ postScanEvent:
if (scan != precord->scan)
db_post_events(precord, &precord->scan, DBE_VALUE | DBE_LOG);
unlock:
dbLockSetGblUnlock();
dbScanUnlockMany(&locker);
dbLockerFinalize(&locker);
cleanup:
free(link_info.target);
return status;

View File

@@ -23,6 +23,7 @@
#include "cantProceed.h"
#include "cvtFast.h"
#include "dbDefs.h"
#include "epicsSpin.h"
#include "ellLib.h"
#include "epicsThread.h"
#include "epicsTime.h"
@@ -45,7 +46,7 @@
#include "dbFldTypes.h"
#include "dbFldTypes.h"
#include "dbLink.h"
#include "dbLock.h"
#include "dbLockPvt.h"
#include "dbNotify.h"
#include "dbScan.h"
#include "dbStaticLib.h"
@@ -140,18 +141,21 @@ static long dbDbInitLink(struct link *plink, short dbfType)
pdbAddr = dbCalloc(1, sizeof(struct dbAddr));
*pdbAddr = dbaddr; /* structure copy */
plink->value.pv_link.pvt = pdbAddr;
dbLockSetMerge(plink->value.pv_link.precord, pdbAddr->precord);
/* merging into the same lockset is deferred to the caller.
* cf. initPVLinks()
*/
return 0;
}
static void dbDbRemoveLink(struct link *plink)
static void dbDbRemoveLink(dbLocker *locker, struct dbCommon *prec, struct link *plink)
{
free(plink->value.pv_link.pvt);
DBADDR *pdbAddr = (DBADDR *) plink->value.pv_link.pvt;
plink->value.pv_link.pvt = 0;
plink->value.pv_link.getCvt = 0;
plink->value.pv_link.lastGetdbrType = 0;
plink->type = PV_LINK;
dbLockSetSplit(plink->value.pv_link.precord);
dbLockSetSplit(locker, prec, pdbAddr->precord);
free(pdbAddr);
}
static int dbDbIsLinkConnected(const struct link *plink)
@@ -422,7 +426,7 @@ void dbInitLink(struct dbCommon *precord, struct link *plink, short dbfType)
}
}
void dbAddLink(struct dbCommon *precord, struct link *plink, short dbfType, DBADDR *ptargetaddr)
void dbAddLink(dbLocker *locker, struct dbCommon *precord, struct link *plink, short dbfType, DBADDR *ptargetaddr)
{
plink->value.pv_link.precord = precord;
@@ -436,7 +440,7 @@ void dbAddLink(struct dbCommon *precord, struct link *plink, short dbfType, DBAD
plink->value.pv_link.pvt = ptargetaddr;
/* target record is already locked in dbPutFieldLink() */
dbLockSetMerge(plink->value.pv_link.precord, ptargetaddr->precord);
dbLockSetMerge(locker, plink->value.pv_link.precord, ptargetaddr->precord);
return;
}
@@ -463,11 +467,11 @@ long dbLoadLink(struct link *plink, short dbrType, void *pbuffer)
return S_db_notFound;
}
void dbRemoveLink(struct link *plink)
void dbRemoveLink(dbLocker *locker, dbCommon *prec, struct link *plink)
{
switch (plink->type) {
case DB_LINK:
dbDbRemoveLink(plink);
dbDbRemoveLink(locker, prec, plink);
break;
case CA_LINK:
dbCaRemoveLink(plink);

View File

@@ -50,13 +50,15 @@ typedef struct lset {
#define dbGetSevr(PLINK, PSEVERITY) \
dbGetAlarm((PLINK), NULL, (PSEVERITY))
struct dbLocker;
epicsShareFunc void dbInitLink(struct dbCommon *precord, struct link *plink,
short dbfType);
epicsShareFunc void dbAddLink(struct dbCommon *precord, struct link *plink,
epicsShareFunc void dbAddLink(struct dbLocker *locker, struct dbCommon *precord, struct link *plink,
short dbfType, DBADDR *ptargetaddr);
epicsShareFunc long dbLoadLink(struct link *plink, short dbrType,
void *pbuffer);
epicsShareFunc void dbRemoveLink(struct link *plink);
epicsShareFunc void dbRemoveLink(struct dbLocker *locker, struct dbCommon *prec, struct link *plink);
epicsShareFunc long dbGetNelements(const struct link *plink, long *nelements);
epicsShareFunc int dbIsLinkConnected(const struct link *plink);
epicsShareFunc int dbGetLinkDBFtype(const struct link *plink);