From 8af3ffb6539cf66d44638a48ee6616c3f957239e Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Tue, 24 Mar 2015 14:18:11 -0400 Subject: [PATCH] dbAccess: multi-locking in dbPutFieldLink Use new locking API in dbPutFieldLink() Adjust dbAddLink() and dbRemoveLink() to pass a dbLocker* through to lockSet merge/split --- src/ioc/db/dbAccess.c | 25 +++++++++++++++++-------- src/ioc/db/dbLink.c | 22 +++++++++++++--------- src/ioc/db/dbLink.h | 6 ++++-- 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/ioc/db/dbAccess.c b/src/ioc/db/dbAccess.c index b13d7a138..b24739d2c 100644 --- a/src/ioc/db/dbAccess.c +++ b/src/ioc/db/dbAccess.c @@ -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; diff --git a/src/ioc/db/dbLink.c b/src/ioc/db/dbLink.c index 2ad9c6606..4ab5dcde5 100644 --- a/src/ioc/db/dbLink.c +++ b/src/ioc/db/dbLink.c @@ -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); diff --git a/src/ioc/db/dbLink.h b/src/ioc/db/dbLink.h index f96f8ece1..006189728 100644 --- a/src/ioc/db/dbLink.h +++ b/src/ioc/db/dbLink.h @@ -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);