dbLock: multi-locking

new API to lock 2 or more lockSets simultaneously
removes global locks for dbScanLock() only
one global lock for debugging/freelist
Introduce dbLockPvt.h for internal API
This commit is contained in:
Michael Davidsaver
2015-03-24 14:14:46 -04:00
parent adcde46e9e
commit af89b716f4
3 changed files with 1032 additions and 493 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -13,6 +13,7 @@
#ifndef INCdbLockh
#define INCdbLockh
#include "ellLib.h"
#include "shareLib.h"
#ifdef __cplusplus
@@ -21,21 +22,27 @@ extern "C" {
struct dbCommon;
struct dbBase;
//struct dbLockSet;
typedef struct dbLocker dbLocker;
epicsShareFunc void dbScanLock(struct dbCommon *precord);
epicsShareFunc void dbScanUnlock(struct dbCommon *precord);
epicsShareFunc dbLocker *dbLockerAlloc(struct dbCommon **precs,
size_t nrecs,
unsigned int flags);
epicsShareFunc void dbLockerFree(dbLocker *);
epicsShareFunc void dbScanLockMany(dbLocker*);
epicsShareFunc void dbScanUnlockMany(dbLocker*);
epicsShareFunc unsigned long dbLockGetLockId(
struct dbCommon *precord);
epicsShareFunc void dbLockInitRecords(struct dbBase *pdbbase);
epicsShareFunc void dbLockCleanupRecords(struct dbBase *pdbbase);
epicsShareFunc void dbLockSetMerge(
struct dbCommon *pfirst,struct dbCommon *psecond);
epicsShareFunc void dbLockSetSplit(struct dbCommon *psource);
/*The following are for code that modifies lock sets*/
epicsShareFunc void dbLockSetGblLock(void);
epicsShareFunc void dbLockSetGblUnlock(void);
epicsShareFunc void dbLockSetRecordLock(struct dbCommon *precord);
/* Lock Set Report */
epicsShareFunc long dblsr(char *recordname,int level);
@@ -47,6 +54,10 @@ epicsShareFunc long dbLockShowLocked(int level);
/*KLUDGE to support field TPRO*/
epicsShareFunc int * dbLockSetAddrTrace(struct dbCommon *precord);
/* debugging */
epicsShareFunc unsigned long dbLockGetRefs(struct dbCommon*);
epicsShareFunc unsigned long dbLockCountSets(void);
#ifdef __cplusplus
}
#endif

109
src/ioc/db/dbLockPvt.h Normal file
View File

@@ -0,0 +1,109 @@
/*************************************************************************\
* Copyright (c) 2014 Brookhaven Science Assoc., as Operator of Brookhaven
* National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#ifndef DBLOCKPVT_H
#define DBLOCKPVT_H
#include "dbLock.h"
#define LOCKSET_DEBUG
#define LOCKSET_FREE
#define LOCKSET_NOCNT
/* except for refcount (and lock), all members of dbLockSet
* are guarded by its lock.
*/
typedef struct dbLockSet {
ELLNODE node;
ELLLIST lockRecordList; /* holds lockRecord::node */
epicsMutexId lock;
unsigned long id;
int refcount;
#ifdef LOCKSET_DEBUG
int ownercount;
epicsThreadId owner;
#endif
dbLocker *ownerlocker;
ELLNODE lockernode;
int trace; /*For field TPRO*/
} lockSet;
struct lockRecord;
typedef struct {
ELLNODE backlinksnode;
struct lockRecord *psrc;
struct lockRecord *ptarget;
} linkRef;
/* dbCommon.LSET is a plockRecord.
* Except for spin and plockSet, all members of lockRecord are guarded
* by the present lockset lock.
* plockSet is guarded by spin.
*/
typedef struct lockRecord {
ELLNODE node;
/* The association between lockRecord and lockSet
* can only be changed while the lockSet is held,
* and the lockRecord's spinlock is held.
* It may be read which either lock is held.
*/
lockSet *plockSet;
dbCommon *precord;
epicsSpinId spin;
/* temp used during lockset split */
ELLNODE compnode;
unsigned int compflag;
ELLLIST backlinks;
linkRef links[1]; /* actual size based on no_links from dbRecordType */
} lockRecord;
typedef struct {
lockRecord *plr;
/* the last lock found associated with the ref.
* not stable unless lock is locked, or ref spin
* is locked.
*/
lockSet *plockSet;
} lockRecordRef;
#define DBLOCKER_NALLOC 3
/* a dbLocker can only be used by a single thread. */
struct dbLocker {
ELLLIST locked;
#ifndef LOCKSET_NOCNT
size_t recomp; /* snapshot of recomputeCnt when refs[] cache updated */
#endif
size_t maxrefs;
lockRecordRef refs[DBLOCKER_NALLOC]; /* actual length is maxrefs */
};
lockSet* dbLockGetRef(lockRecord *lr);
void dbLockIncRef(lockSet* ls);
void dbLockDecRef(lockSet *ls);
/* Optimization used by for dbLocker on the stack.
* nrecs must be <=DBLOCKER_NALLOC.
*/
void dbLockerPrepare(struct dbLocker *locker,
struct dbCommon **precs,
size_t nrecs);
void dbLockerFinalize(dbLocker *);
void dbLockSetMerge(struct dbLocker *locker,
struct dbCommon *pfirst,
struct dbCommon *psecond);
void dbLockSetSplit(struct dbLocker *locker,
struct dbCommon *psource,
struct dbCommon *psecond);
#endif // DBLOCKPVT_H