lock.h 6.1 KB
Newer Older
1 2 3
/*-------------------------------------------------------------------------
 *
 * lock.h--
4
 *
5 6 7 8
 *
 *
 * Copyright (c) 1994, Regents of the University of California
 *
9
 * $Id: lock.h,v 1.15 1998/06/30 02:33:33 momjian Exp $
10 11 12 13 14 15
 *
 *-------------------------------------------------------------------------
 */
#ifndef LOCK_H_
#define LOCK_H_

16 17
#include <storage/shmem.h>
#include <storage/itemptr.h>
18 19

extern SPINLOCK LockMgrLock;
20
typedef int MASK;
21

22 23
#define INIT_TABLE_SIZE			100
#define MAX_TABLE_SIZE			1000
24 25 26 27


/* ----------------------
 * The following defines are used to estimate how much shared
28 29
 * memory the lock manager is going to require.
 *
30 31 32 33 34 35 36 37 38
 * NBACKENDS - The number of concurrently running backends
 * NLOCKS_PER_XACT - The number of unique locks acquired in a transaction
 * NLOCKENTS - The maximum number of lock entries in the lock table.
 * ----------------------
 */
#define NBACKENDS 50
#define NLOCKS_PER_XACT 40
#define NLOCKENTS NLOCKS_PER_XACT*NBACKENDS

39 40
typedef int LOCKMODE;
typedef int LOCKMETHOD;
41

42 43
/* MAX_LOCKMODES cannot be larger than the bits in MASK */
#define MAX_LOCKMODES 6
44 45

/*
46
 * MAX_LOCK_METHODS corresponds to the number of spin locks allocated in
47 48 49
 * CreateSpinLocks() or the number of shared memory locations allocated
 * for lock table spin locks in the case of machines with TAS instructions.
 */
50
#define MAX_LOCK_METHODS 2
51 52 53 54 55 56

#define INVALID_TABLEID 0

/*typedef struct LOCK LOCK; */


57
typedef struct LTAG
58
{
59 60
	Oid			relId;
	Oid			dbId;
61
	ItemPointerData tupleId;
62
} LOCKTAG;
63 64 65

#define TAGSIZE (sizeof(LOCKTAG))

66
/* This is the control structure for a lock table.	It
67 68
 * lives in shared memory:
 *
69 70
 * lockmethod -- the handle used by the lock table's clients to
 *		refer to the type of lock table being used.
71
 *
72
 * numLockModes -- number of lock types (READ,WRITE,etc) that
73
 *		are defined on this lock table
74 75
 *
 * conflictTab -- this is an array of bitmasks showing lock
76 77
 *		type conflicts. conflictTab[i] is a mask with the j-th bit
 *		turned on if lock types i and j conflict.
78
 *
79
 * prio -- each lockmode has a priority, so, for example, waiting
80 81
 *		writers can be given priority over readers (to avoid
 *		starvation).
82 83 84 85
 *
 * masterlock -- synchronizes access to the table
 *
 */
86
typedef struct LOCKMETHODCTL
87
{
88 89 90 91
	LOCKMETHOD 	lockmethod;
	int			numLockModes;
	int			conflictTab[MAX_LOCKMODES];
	int			prio[MAX_LOCKMODES];
92
	SPINLOCK	masterLock;
93
} LOCKMETHODCTL;
94 95 96 97

/*
 * lockHash -- hash table on lock Ids,
 * xidHash -- hash on xid and lockId in case
98
 *		multiple processes are holding the lock
99 100
 * ctl - control structure described above.
 */
101
typedef struct LOCKMETHODTABLE
102
{
103 104
	HTAB	   *lockHash;
	HTAB	   *xidHash;
105 106
	LOCKMETHODCTL    *ctl;
} LOCKMETHODTABLE;
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136

/* -----------------------
 * A transaction never conflicts with its own locks.  Hence, if
 * multiple transactions hold non-conflicting locks on the same
 * data, private per-transaction information must be stored in the
 * XID table.  The tag is XID + shared memory lock address so that
 * all locks can use the same XID table.  The private information
 * we store is the number of locks of each type (holders) and the
 * total number of locks (nHolding) held by the transaction.
 *
 * NOTE: --
 * There were some problems with the fact that currently TransactionIdData
 * is a 5 byte entity and compilers long word aligning of structure fields.
 * If the 3 byte padding is put in front of the actual xid data then the
 * hash function (which uses XID_TAGSIZE when deciding how many bytes of a
 * struct to look at for the key) might only see the last two bytes of the xid.
 *
 * Clearly this is not good since its likely that these bytes will be the
 * same for many transactions and hence they will share the same entry in
 * hash table causing the entry to be corrupted.  For this long-winded
 * reason I have put the tag in a struct of its own to ensure that the
 * XID_TAGSIZE is computed correctly.  It used to be sizeof (SHMEM_OFFSET) +
 * sizeof(TransactionIdData) which != sizeof(XIDTAG).
 *
 * Finally since the hash function will now look at all 12 bytes of the tag
 * the padding bytes MUST be zero'd before use in hash_search() as they
 * will have random values otherwise.  Jeff 22 July 1991.
 * -----------------------
 */

137 138
typedef struct XIDTAG
{
139 140 141
	SHMEM_OFFSET lock;
	int			pid;
	TransactionId xid;
142
} XIDTAG;
143

144 145 146
typedef struct XIDLookupEnt
{
	/* tag */
147
	XIDTAG		tag;
148

149
	/* data */
150
	int			holders[MAX_LOCKMODES];
151 152
	int			nHolding;
	SHM_QUEUE	queue;
153
} XIDLookupEnt;
154 155 156 157

#define XID_TAGSIZE (sizeof(XIDTAG))

/* originally in procq.h */
158
typedef struct PROC_QUEUE
159
{
160 161
	SHM_QUEUE	links;
	int			size;
162
} PROC_QUEUE;
163 164 165 166 167 168 169


/*
 * lock information:
 *
 * tag -- uniquely identifies the object being locked
 * mask -- union of the conflict masks of all lock types
170
 *		currently held on this object.
171 172
 * waitProcs -- queue of processes waiting for this lock
 * holders -- count of each lock type currently held on the
173
 *		lock.
174 175
 * nHolding -- total locks of all types.
 */
176
typedef struct LOCK
177 178
{
	/* hash key */
179
	LOCKTAG		tag;
180 181

	/* data */
182 183
	int			mask;
	PROC_QUEUE	waitProcs;
184
	int			holders[MAX_LOCKMODES];
185
	int			nHolding;
186
	int			activeHolders[MAX_LOCKMODES];
187
	int			nActive;
188
} LOCK;
189 190 191

#define LockGetLock_nHolders(l) l->nHolders

192
#define LockDecrWaitHolders(lock, lockmode) \
193 194
( \
  lock->nHolding--, \
195
  lock->holders[lockmode]-- \
196
)
197 198 199 200 201 202 203 204 205

#define LockLockTable() SpinAcquire(LockMgrLock);
#define UnlockLockTable() SpinRelease(LockMgrLock);

extern SPINLOCK LockMgrLock;

/*
 * function prototypes
 */
206 207
extern void InitLocks(void);
extern void LockDisable(int status);
208 209 210 211
extern LOCKMETHOD
LockMethodTableInit(char *tabName, MASK *conflictsP, int *prioP,
			int numModes);
extern bool LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode);
212
extern int
213
LockResolveConflicts(LOCKMETHOD lockmethod, LOCK *lock, LOCKMODE lockmode,
214
					 TransactionId xid);
215 216 217
extern bool LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode);
extern void GrantLock(LOCK *lock, LOCKMODE lockmode);
extern bool LockReleaseAll(LOCKMETHOD lockmethod, SHM_QUEUE *lockQueue);
218 219
extern int	LockShmemSize(void);
extern bool LockingDisabled(void);
B
Bruce Momjian 已提交
220
extern bool DeadLockCheck(SHM_QUEUE *lockQueue, LOCK *findlock, bool skip_check);
221

222
#ifdef DEADLOCK_DEBUG
223
extern void DumpLocks(void);
224

225 226
#endif

227
#endif							/* LOCK_H */