121 lines
3.4 KiB
C
121 lines
3.4 KiB
C
/*************************************************************************\
|
|
* Copyright (c) 2014 Brookhaven Science Assoc., as Operator of Brookhaven
|
|
* National Laboratory.
|
|
* SPDX-License-Identifier: EPICS
|
|
* EPICS BASE is 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"
|
|
#include "epicsMutex.h"
|
|
#include "epicsSpin.h"
|
|
|
|
/* Define to enable additional error checking */
|
|
#undef LOCKSET_DEBUG
|
|
|
|
/* Define to disable the free list for lockSets */
|
|
#undef LOCKSET_NOFREE
|
|
|
|
/* Define to disable use of recomputeCnt optimization */
|
|
#undef 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;
|
|
|
|
/* 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; /* in lockSet::lockRecordList */
|
|
/* 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;
|
|
/* the association between lockRecord and dbCommon never changes */
|
|
dbCommon *precord;
|
|
epicsSpinId spin;
|
|
|
|
/* temp used during lockset split.
|
|
* lockSet must be locked for access
|
|
*/
|
|
ELLNODE compnode;
|
|
unsigned int compflag;
|
|
} 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 2
|
|
/* 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 */
|
|
};
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/* These are exported for testing only */
|
|
DBCORE_API lockSet* dbLockGetRef(lockRecord *lr); /* lookup lockset and increment ref count */
|
|
DBCORE_API void dbLockIncRef(lockSet* ls);
|
|
DBCORE_API void dbLockDecRef(lockSet *ls);
|
|
|
|
/* Calling dbLockerPrepare directly is an internal
|
|
* optimization used when dbLocker on the stack.
|
|
* nrecs must be <=DBLOCKER_NALLOC.
|
|
*/
|
|
void dbLockerPrepare(struct dbLocker *locker,
|
|
struct dbCommon * const *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);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* DBLOCKPVT_H */
|