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:
1391
src/ioc/db/dbLock.c
1391
src/ioc/db/dbLock.c
File diff suppressed because it is too large
Load Diff
@@ -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
109
src/ioc/db/dbLockPvt.h
Normal 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
|
||||
Reference in New Issue
Block a user