lock.h 6.02 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.10 1998/01/27 03:00:43 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 41
typedef int LOCK_TYPE;
typedef int LOCKT;
typedef int LockTableId;
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57

/* MAX_LOCKTYPES cannot be larger than the bits in MASK */
#define MAX_LOCKTYPES 6

/*
 * MAX_TABLES corresponds to the number of spin locks allocated in
 * CreateSpinLocks() or the number of shared memory locations allocated
 * for lock table spin locks in the case of machines with TAS instructions.
 */
#define MAX_TABLES 2

#define INVALID_TABLEID 0

/*typedef struct LOCK LOCK; */


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

#define TAGSIZE (sizeof(LOCKTAG))

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

/*
 * lockHash -- hash table on lock Ids,
 * xidHash -- hash on xid and lockId in case
99
 *		multiple processes are holding the lock
100 101
 * ctl - control structure described above.
 */
102 103
typedef struct ltable
{
104 105 106
	HTAB	   *lockHash;
	HTAB	   *xidHash;
	LOCKCTL    *ctl;
107
} LOCKTAB;
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 137

/* -----------------------
 * 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.
 * -----------------------
 */

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

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

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

#define XID_TAGSIZE (sizeof(XIDTAG))

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


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

	/* data */
183 184 185 186 187 188
	int			mask;
	PROC_QUEUE	waitProcs;
	int			holders[MAX_LOCKTYPES];
	int			nHolding;
	int			activeHolders[MAX_LOCKTYPES];
	int			nActive;
189
} LOCK;
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204

#define LockGetLock_nHolders(l) l->nHolders

#define LockDecrWaitHolders(lock, lockt) \
  lock->nHolding--; \
  lock->holders[lockt]--

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

extern SPINLOCK LockMgrLock;

/*
 * function prototypes
 */
205 206
extern void InitLocks(void);
extern void LockDisable(int status);
207
extern LockTableId LockTabInit(char *tabName, MASK *conflictsP, int *prioP,
208
			int ntypes);
209
extern bool LockAcquire(LockTableId tableId, LOCKTAG *lockName, LOCKT lockt);
210
extern int LockResolveConflicts(LOCKTAB *ltable, LOCK *lock, LOCKT lockt,
211
					 TransactionId xid);
212 213 214
extern bool LockRelease(LockTableId tableId, LOCKTAG *lockName, LOCKT lockt);
extern void GrantLock(LOCK *lock, LOCKT lockt);
extern bool LockReleaseAll(LockTableId tableId, SHM_QUEUE *lockQueue);
215 216
extern int	LockShmemSize(void);
extern bool LockingDisabled(void);
Bruce Momjian's avatar
Bruce Momjian committed
217
extern bool DeadLockCheck(SHM_QUEUE *lockQueue, LOCK *findlock, bool skip_check);
218
#ifdef DEADLOCK_DEBUG
219
extern void DumpLocks(void);
220

221 222
#endif

223
#endif							/* LOCK_H */