lock.h 7.43 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * lock.h
4
 *
5 6 7 8
 *
 *
 * Copyright (c) 1994, Regents of the University of California
 *
Bruce Momjian's avatar
Bruce Momjian committed
9
 * $Id: lock.h,v 1.33 1999/07/16 17:07:38 momjian Exp $
10 11 12 13 14 15
 *
 *-------------------------------------------------------------------------
 */
#ifndef LOCK_H_
#define LOCK_H_

16
#include "storage/itemptr.h"
Bruce Momjian's avatar
Bruce Momjian committed
17
#include "storage/shmem.h"
18 19
#include "storage/sinvaladt.h"
#include "utils/array.h"
20 21

extern SPINLOCK LockMgrLock;
Bruce Momjian's avatar
Bruce Momjian committed
22
typedef int LOCKMASK;
23

24 25
#define INIT_TABLE_SIZE			100
#define MAX_TABLE_SIZE			1000
26 27 28 29


/* ----------------------
 * The following defines are used to estimate how much shared
30
 * memory the lock manager is going to require.
31
 * See LockShmemSize() in lock.c.
32
 *
33
 * NLOCKS_PER_XACT - The number of unique locks acquired in a transaction
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
34
 *                   (should be configurable!)
35 36 37
 * NLOCKENTS - The maximum number of lock entries in the lock table.
 * ----------------------
 */
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
38
#define NLOCKS_PER_XACT			64
39
#define NLOCKENTS(maxBackends)	(NLOCKS_PER_XACT*(maxBackends))
40

41 42
typedef int LOCKMODE;
typedef int LOCKMETHOD;
43

Bruce Momjian's avatar
Bruce Momjian committed
44
/* MAX_LOCKMODES cannot be larger than the bits in LOCKMASK */
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
45
#define MAX_LOCKMODES	8
46 47

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

54 55 56 57 58 59
#define INVALID_TABLEID		0

#define INVALID_LOCKMETHOD	INVALID_TABLEID
#define DEFAULT_LOCKMETHOD	1
#define USER_LOCKMETHOD		2
#define MIN_LOCKMETHOD		DEFAULT_LOCKMETHOD
60 61


62
typedef struct LTAG
63
{
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
64 65
	Oid				relId;
	Oid				dbId;
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
66 67
	union
	{
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
68 69 70 71 72 73 74 75 76
		BlockNumber		blkno;
		TransactionId	xid;
	}				objId;
	/* 
	 * offnum should be part of objId.tupleId above, but would increase 
	 * sizeof(LOCKTAG) and so moved here; currently used by userlocks only.
	 */
	OffsetNumber	offnum;
	uint16			lockmethod;		/* needed by userlocks */
77
} LOCKTAG;
78 79

#define TAGSIZE (sizeof(LOCKTAG))
80
#define LOCKTAG_LOCKMETHOD(locktag) ((locktag).lockmethod)
81

82
/* This is the control structure for a lock table.	It
83 84
 * lives in shared memory:
 *
85 86
 * lockmethod -- the handle used by the lock table's clients to
 *		refer to the type of lock table being used.
87
 *
88
 * numLockModes -- number of lock types (READ,WRITE,etc) that
89
 *		are defined on this lock table
90 91
 *
 * conflictTab -- this is an array of bitmasks showing lock
92 93
 *		type conflicts. conflictTab[i] is a mask with the j-th bit
 *		turned on if lock types i and j conflict.
94
 *
95
 * prio -- each lockmode has a priority, so, for example, waiting
96 97
 *		writers can be given priority over readers (to avoid
 *		starvation).
98 99 100 101
 *
 * masterlock -- synchronizes access to the table
 *
 */
102
typedef struct LOCKMETHODCTL
103
{
104
	LOCKMETHOD	lockmethod;
105 106 107
	int			numLockModes;
	int			conflictTab[MAX_LOCKMODES];
	int			prio[MAX_LOCKMODES];
108
	SPINLOCK	masterLock;
109
} LOCKMETHODCTL;
110 111 112 113

/*
 * lockHash -- hash table on lock Ids,
 * xidHash -- hash on xid and lockId in case
114
 *		multiple processes are holding the lock
115 116
 * ctl - control structure described above.
 */
117
typedef struct LOCKMETHODTABLE
118
{
119 120
	HTAB	   *lockHash;
	HTAB	   *xidHash;
121
	LOCKMETHODCTL *ctl;
122
} LOCKMETHODTABLE;
123 124 125 126 127 128 129 130 131 132

/* -----------------------
 * 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.
 *
Bruce Momjian's avatar
Bruce Momjian committed
133
 * NOTE:
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
 * 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.
 * -----------------------
 */

153 154
typedef struct XIDTAG
{
155 156 157
	SHMEM_OFFSET lock;
	int			pid;
	TransactionId xid;
158
#ifdef USE_XIDTAG_LOCKMETHOD
159
	uint16		lockmethod;		/* for debug or consistency checking */
160
#endif
161
} XIDTAG;
162

163 164 165 166 167 168 169
#ifdef USE_XIDTAG_LOCKMETHOD
#define XIDTAG_LOCKMETHOD(xidtag) ((xidtag).lockmethod)
#else
#define XIDTAG_LOCKMETHOD(xidtag) \
		(((LOCK*) MAKE_PTR((xidtag).lock))->tag.lockmethod)
#endif

170 171 172
typedef struct XIDLookupEnt
{
	/* tag */
173
	XIDTAG		tag;
174

175
	/* data */
176
	int			holders[MAX_LOCKMODES];
177 178
	int			nHolding;
	SHM_QUEUE	queue;
179
} XIDLookupEnt;
180

181 182 183
#define SHMEM_XIDTAB_KEYSIZE  sizeof(XIDTAG)
#define SHMEM_XIDTAB_DATASIZE (sizeof(XIDLookupEnt) - SHMEM_XIDTAB_KEYSIZE)

184
#define XID_TAGSIZE (sizeof(XIDTAG))
185
#define XIDENT_LOCKMETHOD(xident) (XIDTAG_LOCKMETHOD((xident).tag))
186 187

/* originally in procq.h */
188
typedef struct PROC_QUEUE
189
{
190 191
	SHM_QUEUE	links;
	int			size;
192
} PROC_QUEUE;
193 194 195 196 197 198 199


/*
 * lock information:
 *
 * tag -- uniquely identifies the object being locked
 * mask -- union of the conflict masks of all lock types
200
 *		currently held on this object.
201 202
 * waitProcs -- queue of processes waiting for this lock
 * holders -- count of each lock type currently held on the
203
 *		lock.
204 205
 * nHolding -- total locks of all types.
 */
206
typedef struct LOCK
207 208
{
	/* hash key */
209
	LOCKTAG		tag;
210 211

	/* data */
212
	int			mask;
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
213
	int			waitMask;
214
	PROC_QUEUE	waitProcs;
215
	int			holders[MAX_LOCKMODES];
216
	int			nHolding;
217
	int			activeHolders[MAX_LOCKMODES];
218
	int			nActive;
219
} LOCK;
220

221 222 223
#define SHMEM_LOCKTAB_KEYSIZE  sizeof(LOCKTAG)
#define SHMEM_LOCKTAB_DATASIZE (sizeof(LOCK) - SHMEM_LOCKTAB_KEYSIZE)

224
#define LOCK_LOCKMETHOD(lock) (LOCKTAG_LOCKMETHOD((lock).tag))
225

226 227
#define LockGetLock_nHolders(l) l->nHolders
#ifdef NOT_USED
228
#define LockDecrWaitHolders(lock, lockmode) \
229 230
( \
  lock->nHolding--, \
231
  lock->holders[lockmode]-- \
232
)
233
#endif
234 235 236 237 238 239 240 241
#define LockLockTable() SpinAcquire(LockMgrLock);
#define UnlockLockTable() SpinRelease(LockMgrLock);

extern SPINLOCK LockMgrLock;

/*
 * function prototypes
 */
242 243
extern void InitLocks(void);
extern void LockDisable(int status);
Bruce Momjian's avatar
Bruce Momjian committed
244
extern LOCKMETHOD LockMethodTableInit(char *tabName, LOCKMASK *conflictsP,
245
					int *prioP, int numModes);
246 247
extern LOCKMETHOD LockMethodTableRename(LOCKMETHOD lockmethod);
extern bool LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
248
			LOCKMODE lockmode);
249
extern int LockResolveConflicts(LOCKMETHOD lockmethod, LOCK *lock,
250 251
					 LOCKMODE lockmode, TransactionId xid,
					 XIDLookupEnt *xidentP);
252
extern bool LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag,
253
			LOCKMODE lockmode);
254 255
extern void GrantLock(LOCK *lock, LOCKMODE lockmode);
extern bool LockReleaseAll(LOCKMETHOD lockmethod, SHM_QUEUE *lockQueue);
256
extern int	LockShmemSize(int maxBackends);
257
extern bool LockingDisabled(void);
Bruce Momjian's avatar
Bruce Momjian committed
258
extern bool DeadLockCheck(void *proc, LOCK *findlock);
259

260
#ifdef DEADLOCK_DEBUG
261
extern void DumpLocks(void);
262
extern void DumpAllLocks(void);
263

264 265
#endif

266
#endif	 /* LOCK_H */