lock.h 8.64 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * lock.h
4
 *	  POSTGRES low-level lock mechanism
5 6
 *
 *
7
 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
Bruce Momjian's avatar
Add:  
Bruce Momjian committed
8
 * Portions Copyright (c) 1994, Regents of the University of California
9
 *
10
 * $Id: lock.h,v 1.44 2001/01/25 03:31:16 tgl Exp $
11 12 13 14 15 16
 *
 *-------------------------------------------------------------------------
 */
#ifndef LOCK_H_
#define LOCK_H_

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


22 23 24
/* originally in procq.h */
typedef struct PROC_QUEUE
{
25 26
	SHM_QUEUE	links;			/* head of list of PROC objects */
	int			size;			/* number of entries in list */
27 28 29 30
} PROC_QUEUE;

/* struct proc is declared in storage/proc.h, but must forward-reference it */
typedef struct proc PROC;
31 32


33 34
extern SPINLOCK LockMgrLock;

35 36 37 38 39 40 41 42 43
#ifdef LOCK_DEBUG
extern int  Trace_lock_oidmin;
extern bool Trace_locks;
extern bool Trace_userlocks;
extern int  Trace_lock_table;
extern bool Debug_deadlocks;
#endif /* LOCK_DEBUG */


44 45
/* ----------------------
 * The following defines are used to estimate how much shared
46
 * memory the lock manager is going to require.
47
 * See LockShmemSize() in lock.c.
48
 *
49 50
 * NLOCKS_PER_XACT - The number of unique objects locked in a transaction
 *					 (this should be configurable!)
51 52 53
 * NLOCKENTS - The maximum number of lock entries in the lock table.
 * ----------------------
 */
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
54
#define NLOCKS_PER_XACT			64
55
#define NLOCKENTS(maxBackends)	(NLOCKS_PER_XACT*(maxBackends))
56

57 58
typedef int LOCKMASK;

59 60
typedef int LOCKMODE;
typedef int LOCKMETHOD;
61

62
/* MAX_LOCKMODES cannot be larger than the # of bits in LOCKMASK */
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
63
#define MAX_LOCKMODES	8
64 65

/*
66
 * MAX_LOCK_METHODS corresponds to the number of spin locks allocated in
67 68 69
 * CreateSpinLocks() or the number of shared memory locations allocated
 * for lock table spin locks in the case of machines with TAS instructions.
 */
70
#define MAX_LOCK_METHODS	3
71

72 73 74 75 76 77
#define INVALID_TABLEID		0

#define INVALID_LOCKMETHOD	INVALID_TABLEID
#define DEFAULT_LOCKMETHOD	1
#define USER_LOCKMETHOD		2
#define MIN_LOCKMETHOD		DEFAULT_LOCKMETHOD
78 79


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

/*
110 111 112 113 114
 * Non-shared header for a lock table.
 *
 * lockHash -- hash table holding per-locked-object lock information
 * holderHash -- hash table holding per-lock-holder lock information
 * ctl - shared control structure described above.
115
 */
116
typedef struct LOCKMETHODTABLE
117
{
118
	HTAB	   *lockHash;
119
	HTAB	   *holderHash;
120
	LOCKMETHODCTL *ctl;
121
} LOCKMETHODTABLE;
122

123

124 125 126 127 128
/*
 * LOCKTAG is the key information needed to look up a LOCK item in the
 * lock hashtable.  A LOCKTAG value uniquely identifies a lockable object.
 */
typedef struct LOCKTAG
129
{
130 131 132 133 134 135 136
	Oid			relId;
	Oid			dbId;
	union
	{
		BlockNumber blkno;
		TransactionId xid;
	}			objId;
137

138 139 140 141 142 143
	/*
	 * offnum should be part of objId.tupleId above, but would increase
	 * sizeof(LOCKTAG) and so moved here; currently used by userlocks
	 * only.
	 */
	OffsetNumber offnum;
144

145 146
	uint16		lockmethod;		/* needed by userlocks */
} LOCKTAG;
147 148 149


/*
150
 * Per-locked-object lock information:
151 152
 *
 * tag -- uniquely identifies the object being locked
153 154
 * grantMask -- bitmask for all lock types currently granted on this object.
 * waitMask -- bitmask for all lock types currently awaited on this object.
155
 * lockHolders -- list of HOLDER objects for this lock.
156 157 158 159 160 161
 * waitProcs -- queue of processes waiting for this lock.
 * requested -- count of each lock type currently requested on the lock
 *		(includes requests already granted!!).
 * nRequested -- total requested locks of all types.
 * granted -- count of each lock type currently granted on the lock.
 * nGranted -- total granted locks of all types.
162
 */
163
typedef struct LOCK
164 165
{
	/* hash key */
166
	LOCKTAG		tag;			/* unique identifier of lockable object */
167 168

	/* data */
169 170
	int			grantMask;		/* bitmask for lock types already granted */
	int			waitMask;		/* bitmask for lock types awaited */
171
	SHM_QUEUE	lockHolders;	/* list of HOLDER objects assoc. with lock */
172 173 174 175 176
	PROC_QUEUE	waitProcs;		/* list of PROC objects waiting on lock */
	int			requested[MAX_LOCKMODES]; /* counts of requested locks */
	int			nRequested;		/* total of requested[] array */
	int			granted[MAX_LOCKMODES];	/* counts of granted locks */
	int			nGranted;		/* total of granted[] array */
177
} LOCK;
178

179 180 181
#define SHMEM_LOCKTAB_KEYSIZE  sizeof(LOCKTAG)
#define SHMEM_LOCKTAB_DATASIZE (sizeof(LOCK) - SHMEM_LOCKTAB_KEYSIZE)

182
#define LOCK_LOCKMETHOD(lock) ((lock).tag.lockmethod)
183

184 185 186 187 188 189 190 191 192 193

/*
 * We may have several different transactions holding or awaiting locks
 * on the same lockable object.  We need to store some per-holder information
 * for each such holder (or would-be holder).
 *
 * HOLDERTAG is the key information needed to look up a HOLDER item in the
 * holder hashtable.  A HOLDERTAG value uniquely identifies a lock holder.
 *
 * There are two possible kinds of holder tags: a transaction (identified
194 195
 * both by the PROC of the backend running it, and the xact's own ID) and
 * a session (identified by backend PROC, with xid = InvalidTransactionId).
196 197 198 199
 *
 * Currently, session holders are used for user locks and for cross-xact
 * locks obtained for VACUUM.  We assume that a session lock never conflicts
 * with per-transaction locks obtained by the same backend.
200 201 202 203 204 205
 *
 * The holding[] array counts the granted locks (of each type) represented
 * by this holder.  Note that there will be a holder object, possibly with
 * zero holding[], for any lock that the process is currently waiting on.
 * Otherwise, holder objects whose counts have gone to zero are recycled
 * as soon as convenient.
206 207 208 209 210 211
 *
 * Each HOLDER object is linked into lists for both the associated LOCK object
 * and the owning PROC object.  Note that the HOLDER is entered into these
 * lists as soon as it is created, even if no lock has yet been granted.
 * A PROC that is waiting for a lock to be granted will also be linked into
 * the lock's waitProcs queue.
212 213 214 215
 */
typedef struct HOLDERTAG
{
	SHMEM_OFFSET lock;			/* link to per-lockable-object information */
216
	SHMEM_OFFSET proc;			/* link to PROC of owning backend */
217 218 219 220 221 222
	TransactionId xid;			/* xact ID, or InvalidTransactionId */
} HOLDERTAG;

typedef struct HOLDER
{
	/* tag */
223
	HOLDERTAG	tag;			/* unique identifier of holder object */
224 225

	/* data */
226 227
	int			holding[MAX_LOCKMODES];	/* count of locks currently held */
	int			nHolding;		/* total of holding[] array */
228 229
	SHM_QUEUE	lockLink;		/* list link for lock's list of holders */
	SHM_QUEUE	procLink;		/* list link for process's list of holders */
230 231 232 233 234 235 236 237 238 239 240 241
} HOLDER;

#define SHMEM_HOLDERTAB_KEYSIZE  sizeof(HOLDERTAG)
#define SHMEM_HOLDERTAB_DATASIZE (sizeof(HOLDER) - SHMEM_HOLDERTAB_KEYSIZE)

#define HOLDER_LOCKMETHOD(holder) \
		(((LOCK *) MAKE_PTR((holder).tag.lock))->tag.lockmethod)



#define LockLockTable() SpinAcquire(LockMgrLock)
#define UnlockLockTable() SpinRelease(LockMgrLock)
242 243 244 245 246


/*
 * function prototypes
 */
247
extern void InitLocks(void);
248 249
extern void LockDisable(bool status);
extern bool LockingDisabled(void);
250
extern LOCKMETHODTABLE *GetLocksMethodTable(LOCK *lock);
Bruce Momjian's avatar
Bruce Momjian committed
251
extern LOCKMETHOD LockMethodTableInit(char *tabName, LOCKMASK *conflictsP,
252
					int *prioP, int numModes, int maxBackends);
253 254
extern LOCKMETHOD LockMethodTableRename(LOCKMETHOD lockmethod);
extern bool LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
255
						TransactionId xid, LOCKMODE lockmode);
256
extern bool LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag,
257 258 259
						TransactionId xid, LOCKMODE lockmode);
extern bool LockReleaseAll(LOCKMETHOD lockmethod, PROC *proc,
						   bool allxids, TransactionId xid);
260 261 262 263
extern int LockCheckConflicts(LOCKMETHODTABLE *lockMethodTable,
							  LOCKMODE lockmode,
							  LOCK *lock, HOLDER *holder, PROC *proc,
							  int *myHolding);
264
extern void GrantLock(LOCK *lock, HOLDER *holder, LOCKMODE lockmode);
265
extern void RemoveFromWaitQueue(PROC *proc);
266
extern int	LockShmemSize(int maxBackends);
267 268
extern bool DeadLockCheck(PROC *proc);
extern void InitDeadLockChecking(void);
269

270
#ifdef LOCK_DEBUG
271
extern void DumpLocks(void);
272
extern void DumpAllLocks(void);
273 274
#endif

275
#endif	 /* LOCK_H */