aboutsummaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
Diffstat (limited to 'src/include')
-rw-r--r--src/include/storage/lmgr.h12
-rw-r--r--src/include/storage/lock.h229
-rw-r--r--src/include/storage/proc.h30
3 files changed, 131 insertions, 140 deletions
diff --git a/src/include/storage/lmgr.h b/src/include/storage/lmgr.h
index f859dc0762f..6f7a16311fd 100644
--- a/src/include/storage/lmgr.h
+++ b/src/include/storage/lmgr.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: lmgr.h,v 1.26 2000/11/28 23:27:57 tgl Exp $
+ * $Id: lmgr.h,v 1.27 2000/12/22 00:51:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -33,17 +33,21 @@
extern LOCKMETHOD LockTableId;
-extern LOCKMETHOD InitLockTable(void);
+extern LOCKMETHOD InitLockTable(int maxBackends);
extern void RelationInitLockInfo(Relation relation);
+/* Lock a relation */
extern void LockRelation(Relation relation, LOCKMODE lockmode);
extern void UnlockRelation(Relation relation, LOCKMODE lockmode);
-/* this is for indices */
+extern void LockRelationForSession(LockRelId *relid, LOCKMODE lockmode);
+extern void UnlockRelationForSession(LockRelId *relid, LOCKMODE lockmode);
+
+/* Lock a page (mainly used for indices) */
extern void LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode);
extern void UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode);
-/* and this is for transactions */
+/* Lock an XID (used to wait for a transaction to finish) */
extern void XactLockTableInsert(TransactionId xid);
extern void XactLockTableWait(TransactionId xid);
diff --git a/src/include/storage/lock.h b/src/include/storage/lock.h
index 195842811af..211deebc0d5 100644
--- a/src/include/storage/lock.h
+++ b/src/include/storage/lock.h
@@ -1,13 +1,13 @@
/*-------------------------------------------------------------------------
*
* lock.h
- *
+ * POSTGRES low-level lock mechanism
*
*
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: lock.h,v 1.39 2000/07/17 03:05:30 tgl Exp $
+ * $Id: lock.h,v 1.40 2000/12/22 00:51:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -18,13 +18,20 @@
#include "storage/itemptr.h"
#include "storage/shmem.h"
-extern SPINLOCK LockMgrLock;
-typedef int LOCKMASK;
-#define INIT_TABLE_SIZE 100
-#define MAX_TABLE_SIZE 1000
+/* originally in procq.h */
+typedef struct PROC_QUEUE
+{
+ SHM_QUEUE links;
+ int size;
+} PROC_QUEUE;
+
+/* struct proc is declared in storage/proc.h, but must forward-reference it */
+typedef struct proc PROC;
+extern SPINLOCK LockMgrLock;
+
#ifdef LOCK_DEBUG
extern int Trace_lock_oidmin;
extern bool Trace_locks;
@@ -39,14 +46,16 @@ extern bool Debug_deadlocks;
* memory the lock manager is going to require.
* See LockShmemSize() in lock.c.
*
- * NLOCKS_PER_XACT - The number of unique locks acquired in a transaction
- * (should be configurable!)
+ * NLOCKS_PER_XACT - The number of unique objects locked in a transaction
+ * (this should be configurable!)
* NLOCKENTS - The maximum number of lock entries in the lock table.
* ----------------------
*/
#define NLOCKS_PER_XACT 64
#define NLOCKENTS(maxBackends) (NLOCKS_PER_XACT*(maxBackends))
+typedef int LOCKMASK;
+
typedef int LOCKMODE;
typedef int LOCKMETHOD;
@@ -68,29 +77,8 @@ typedef int LOCKMETHOD;
#define MIN_LOCKMETHOD DEFAULT_LOCKMETHOD
-typedef struct LTAG
-{
- Oid relId;
- Oid dbId;
- union
- {
- 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 */
-} LOCKTAG;
-
-#define TAGSIZE (sizeof(LOCKTAG))
-#define LOCKTAG_LOCKMETHOD(locktag) ((locktag).lockmethod)
-
-/* This is the control structure for a lock table. It
+/*
+ * This is the control structure for a lock table. It
* lives in shared memory:
*
* lockmethod -- the handle used by the lock table's clients to
@@ -108,7 +96,6 @@ typedef struct LTAG
* starvation).
*
* masterlock -- synchronizes access to the table
- *
*/
typedef struct LOCKMETHODCTL
{
@@ -120,91 +107,47 @@ typedef struct LOCKMETHODCTL
} LOCKMETHODCTL;
/*
- * lockHash -- hash table on lock Ids,
- * xidHash -- hash on xid and lockId in case
- * multiple processes are holding the lock
- * ctl - control structure described above.
+ * 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.
*/
typedef struct LOCKMETHODTABLE
{
HTAB *lockHash;
- HTAB *xidHash;
+ HTAB *holderHash;
LOCKMETHODCTL *ctl;
} LOCKMETHODTABLE;
-/* -----------------------
- * 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.
- * -----------------------
- */
-
-typedef struct XIDTAG
-{
- SHMEM_OFFSET lock;
- int pid;
- TransactionId xid;
-#ifdef USE_XIDTAG_LOCKMETHOD
- uint16 lockmethod; /* for debug or consistency checking */
-#endif
-} XIDTAG;
-
-#ifdef USE_XIDTAG_LOCKMETHOD
-#define XIDTAG_LOCKMETHOD(xidtag) ((xidtag).lockmethod)
-#else
-#define XIDTAG_LOCKMETHOD(xidtag) \
- (((LOCK*) MAKE_PTR((xidtag).lock))->tag.lockmethod)
-#endif
-typedef struct XIDLookupEnt
+/*
+ * 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
{
- /* tag */
- XIDTAG tag;
-
- /* data */
- int holders[MAX_LOCKMODES];
- int nHolding;
- SHM_QUEUE queue;
-} XIDLookupEnt;
-
-#define SHMEM_XIDTAB_KEYSIZE sizeof(XIDTAG)
-#define SHMEM_XIDTAB_DATASIZE (sizeof(XIDLookupEnt) - SHMEM_XIDTAB_KEYSIZE)
+ Oid relId;
+ Oid dbId;
+ union
+ {
+ BlockNumber blkno;
+ TransactionId xid;
+ } objId;
-#define XID_TAGSIZE (sizeof(XIDTAG))
-#define XIDENT_LOCKMETHOD(xident) (XIDTAG_LOCKMETHOD((xident).tag))
+ /*
+ * offnum should be part of objId.tupleId above, but would increase
+ * sizeof(LOCKTAG) and so moved here; currently used by userlocks
+ * only.
+ */
+ OffsetNumber offnum;
-/* originally in procq.h */
-typedef struct PROC_QUEUE
-{
- SHM_QUEUE links;
- int size;
-} PROC_QUEUE;
+ uint16 lockmethod; /* needed by userlocks */
+} LOCKTAG;
/*
- * lock information:
+ * Per-locked-object lock information:
*
* tag -- uniquely identifies the object being locked
* mask -- union of the conflict masks of all lock types
@@ -232,40 +175,76 @@ typedef struct LOCK
#define SHMEM_LOCKTAB_KEYSIZE sizeof(LOCKTAG)
#define SHMEM_LOCKTAB_DATASIZE (sizeof(LOCK) - SHMEM_LOCKTAB_KEYSIZE)
-#define LOCK_LOCKMETHOD(lock) (LOCKTAG_LOCKMETHOD((lock).tag))
+#define LOCK_LOCKMETHOD(lock) ((lock).tag.lockmethod)
-#define LockGetLock_nHolders(l) l->nHolders
-#ifdef NOT_USED
-#define LockDecrWaitHolders(lock, lockmode) \
-( \
- lock->nHolding--, \
- lock->holders[lockmode]-- \
-)
-#endif
-#define LockLockTable() SpinAcquire(LockMgrLock);
-#define UnlockLockTable() SpinRelease(LockMgrLock);
+
+/*
+ * 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
+ * both by the PID of the backend running it, and the xact's own ID) and
+ * a session (identified by backend PID, with xid = InvalidTransactionId).
+ *
+ * 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.
+ */
+typedef struct HOLDERTAG
+{
+ SHMEM_OFFSET lock; /* link to per-lockable-object information */
+ int pid; /* PID of backend */
+ TransactionId xid; /* xact ID, or InvalidTransactionId */
+} HOLDERTAG;
+
+typedef struct HOLDER
+{
+ /* tag */
+ HOLDERTAG tag;
+
+ /* data */
+ int holders[MAX_LOCKMODES];
+ int nHolding;
+ SHM_QUEUE queue;
+} 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)
/*
* function prototypes
*/
extern void InitLocks(void);
-extern void LockDisable(int status);
+extern void LockDisable(bool status);
+extern bool LockingDisabled(void);
extern LOCKMETHOD LockMethodTableInit(char *tabName, LOCKMASK *conflictsP,
- int *prioP, int numModes);
+ int *prioP, int numModes, int maxBackends);
extern LOCKMETHOD LockMethodTableRename(LOCKMETHOD lockmethod);
extern bool LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
- LOCKMODE lockmode);
-extern int LockResolveConflicts(LOCKMETHOD lockmethod, LOCK *lock,
- LOCKMODE lockmode, TransactionId xid,
- XIDLookupEnt *xidentP);
+ TransactionId xid, LOCKMODE lockmode);
extern bool LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag,
- LOCKMODE lockmode);
-extern void GrantLock(LOCK *lock, LOCKMODE lockmode);
-extern bool LockReleaseAll(LOCKMETHOD lockmethod, SHM_QUEUE *lockQueue);
+ TransactionId xid, LOCKMODE lockmode);
+extern bool LockReleaseAll(LOCKMETHOD lockmethod, PROC *proc,
+ bool allxids, TransactionId xid);
+extern int LockResolveConflicts(LOCKMETHOD lockmethod, LOCKMODE lockmode,
+ LOCK *lock, HOLDER *holder, PROC *proc,
+ int *myHolders);
+extern void GrantLock(LOCK *lock, HOLDER *holder, LOCKMODE lockmode);
extern int LockShmemSize(int maxBackends);
-extern bool LockingDisabled(void);
-extern bool DeadLockCheck(void *proc, LOCK *findlock);
+extern bool DeadLockCheck(PROC *thisProc, LOCK *findlock);
#ifdef LOCK_DEBUG
extern void DumpLocks(void);
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index 41305d80831..96928eb4528 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: proc.h,v 1.32 2000/11/28 23:27:57 tgl Exp $
+ * $Id: proc.h,v 1.33 2000/12/22 00:51:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -30,7 +30,7 @@ typedef struct
/*
* Each backend has:
*/
-typedef struct proc
+struct proc
{
/* proc->links MUST BE THE FIRST ELEMENT OF STRUCT (see ProcWakeup()) */
@@ -50,16 +50,25 @@ typedef struct proc
TransactionId xmin; /* minimal running XID as it was when we
* were starting our xact: vacuum must not
* remove tuples deleted by xid >= xmin ! */
+
XLogRecPtr logRec;
- LOCK *waitLock; /* Lock we're sleeping on ... */
- int token; /* type of lock we sleeping for */
- int holdLock; /* while holding these locks */
+
+ /* Info about lock the process is currently waiting for, if any */
+ LOCK *waitLock; /* Lock object we're sleeping on ... */
+ HOLDER *waitHolder; /* Per-holder info for our lock */
+ LOCKMODE waitLockMode; /* type of lock we're waiting for */
+ LOCKMASK holdLock; /* bitmask for lock types already held */
+
int pid; /* This backend's process id */
Oid databaseId; /* OID of database this backend is using */
+
short sLocks[MAX_SPINS]; /* Spin lock stats */
SHM_QUEUE lockQueue; /* locks associated with current
* transaction */
-} PROC;
+};
+
+/* NOTE: "typedef struct proc PROC" appears in storage/lock.h. */
+
extern PROC *MyProc;
@@ -122,15 +131,14 @@ typedef struct procglobal
*/
extern void InitProcGlobal(int maxBackends);
extern void InitProcess(void);
-extern void ProcReleaseLocks(void);
+extern void ProcReleaseLocks(bool isCommit);
extern bool ProcRemove(int pid);
extern void ProcQueueInit(PROC_QUEUE *queue);
-extern int ProcSleep(PROC_QUEUE *queue, LOCKMETHODCTL *lockctl, int token,
- LOCK *lock);
+extern int ProcSleep(LOCKMETHODCTL *lockctl, LOCKMODE lockmode,
+ LOCK *lock, HOLDER *holder);
extern PROC *ProcWakeup(PROC *proc, int errType);
-extern int ProcLockWakeup(PROC_QUEUE *queue, LOCKMETHOD lockmethod,
- LOCK *lock);
+extern int ProcLockWakeup(LOCKMETHOD lockmethod, LOCK *lock);
extern void ProcAddLock(SHM_QUEUE *elem);
extern void ProcReleaseSpins(PROC *proc);
extern void LockWaitCancel(void);