diff options
author | Marc G. Fournier <scrappy@hub.org> | 1996-07-09 06:22:35 +0000 |
---|---|---|
committer | Marc G. Fournier <scrappy@hub.org> | 1996-07-09 06:22:35 +0000 |
commit | d31084e9d1118b25fd16580d9d8c2924b5740dff (patch) | |
tree | 3179e66307d54df9c7b966543550e601eb55e668 /src/backend/storage/lock.h | |
download | postgresql-PG95-1_01.tar.gz postgresql-PG95-1_01.zip |
Postgres95 1.01 Distribution - Virgin SourcesPG95-1_01
Diffstat (limited to 'src/backend/storage/lock.h')
-rw-r--r-- | src/backend/storage/lock.h | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/src/backend/storage/lock.h b/src/backend/storage/lock.h new file mode 100644 index 00000000000..df490e76512 --- /dev/null +++ b/src/backend/storage/lock.h @@ -0,0 +1,218 @@ +/*------------------------------------------------------------------------- + * + * lock.h-- + * + * + * + * Copyright (c) 1994, Regents of the University of California + * + * $Id: lock.h,v 1.1.1.1 1996/07/09 06:21:53 scrappy Exp $ + * + *------------------------------------------------------------------------- + */ +#ifndef LOCK_H_ +#define LOCK_H_ + +#include "postgres.h" +#include "storage/itemptr.h" +#include "storage/shmem.h" +#include "storage/spin.h" +#include "storage/backendid.h" +#include "utils/hsearch.h" + +extern SPINLOCK LockMgrLock; +typedef int MASK; + +#define INIT_TABLE_SIZE 100 +#define MAX_TABLE_SIZE 1000 + + +/* ---------------------- + * The following defines are used to estimate how much shared + * memory the lock manager is going to require. + * + * 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 + +typedef int LOCK_TYPE; +typedef int LOCKT; +typedef int LockTableId; + +/* 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; */ + + +typedef struct ltag { + Oid relId; + Oid dbId; + ItemPointerData tupleId; +} LOCKTAG; + +#define TAGSIZE (sizeof(LOCKTAG)) + +/* This is the control structure for a lock table. It + * lives in shared memory: + * + * tableID -- the handle used by the lock table's clients to + * refer to the table. + * + * nLockTypes -- number of lock types (READ,WRITE,etc) that + * are defined on this lock table + * + * conflictTab -- this is an array of bitmasks showing lock + * type conflicts. conflictTab[i] is a mask with the j-th bit + * turned on if lock types i and j conflict. + * + * prio -- each locktype has a priority, so, for example, waiting + * writers can be given priority over readers (to avoid + * starvation). + * + * masterlock -- synchronizes access to the table + * + */ +typedef struct lockctl { + LockTableId tableId; + int nLockTypes; + int conflictTab[MAX_LOCKTYPES]; + int prio[MAX_LOCKTYPES]; + SPINLOCK masterLock; +} LOCKCTL; + +/* + * 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. + */ +typedef struct ltable { + HTAB *lockHash; + HTAB *xidHash; + LOCKCTL *ctl; +} LOCKTAB; + +/* ----------------------- + * 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; +} XIDTAG; + +typedef struct XIDLookupEnt { + /* tag */ + XIDTAG tag; + + /* data */ + int holders[MAX_LOCKTYPES]; + int nHolding; + SHM_QUEUE queue; +} XIDLookupEnt; + +#define XID_TAGSIZE (sizeof(XIDTAG)) + +/* originally in procq.h */ +typedef struct procQueue { + SHM_QUEUE links; + int size; +} PROC_QUEUE; + + +/* + * lock information: + * + * tag -- uniquely identifies the object being locked + * mask -- union of the conflict masks of all lock types + * currently held on this object. + * waitProcs -- queue of processes waiting for this lock + * holders -- count of each lock type currently held on the + * lock. + * nHolding -- total locks of all types. + */ +typedef struct Lock { + /* hash key */ + LOCKTAG tag; + + /* data */ + int mask; + PROC_QUEUE waitProcs; + int holders[MAX_LOCKTYPES]; + int nHolding; + int activeHolders[MAX_LOCKTYPES]; + int nActive; +} LOCK; + +#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 + */ +extern void InitLocks(void); +extern void LockDisable(int status); +extern LockTableId LockTabInit(char *tabName, MASK *conflictsP, int *prioP, + int ntypes); +extern LockTableId LockTabRename(LockTableId tableId); +extern bool LockAcquire(LockTableId tableId, LOCKTAG *lockName, LOCKT lockt); +extern int LockResolveConflicts(LOCKTAB *ltable, LOCK *lock, LOCKT lockt, + TransactionId xid); +extern int WaitOnLock(LOCKTAB *ltable, LockTableId tableId, LOCK *lock, + LOCKT lockt); +extern bool LockRelease(LockTableId tableId, LOCKTAG *lockName, LOCKT lockt); +extern void GrantLock(LOCK *lock, LOCKT lockt); +extern bool LockReleaseAll(LockTableId tableId, SHM_QUEUE *lockQueue); +extern int LockShmemSize(void); +extern bool LockingDisabled(void); + +#endif /* LOCK_H */ |