diff options
| author | Tom Lane <tgl@sss.pgh.pa.us> | 2001-09-29 04:02:27 +0000 |
|---|---|---|
| committer | Tom Lane <tgl@sss.pgh.pa.us> | 2001-09-29 04:02:27 +0000 |
| commit | 499abb0c0f21cb861c5af1d49a06469f3cfcc1eb (patch) | |
| tree | 0af6262d9b6d1159315e93e90e69047b959ea5f5 /src/include/storage | |
| parent | 818fb55ac49b4b20e65d9899fc1784e54e86db58 (diff) | |
| download | postgresql-499abb0c0f21cb861c5af1d49a06469f3cfcc1eb.tar.gz | |
Implement new 'lightweight lock manager' that's intermediate between
existing lock manager and spinlocks: it understands exclusive vs shared
lock but has few other fancy features. Replace most uses of spinlocks
with lightweight locks. All remaining uses of spinlocks have very short
lock hold times (a few dozen instructions), so tweak spinlock backoff
code to work efficiently given this assumption. All per my proposal on
pghackers 26-Sep-01.
Diffstat (limited to 'src/include/storage')
| -rw-r--r-- | src/include/storage/buf_internals.h | 18 | ||||
| -rw-r--r-- | src/include/storage/freespace.h | 5 | ||||
| -rw-r--r-- | src/include/storage/ipc.h | 29 | ||||
| -rw-r--r-- | src/include/storage/lock.h | 28 | ||||
| -rw-r--r-- | src/include/storage/lwlock.h | 69 | ||||
| -rw-r--r-- | src/include/storage/proc.h | 44 | ||||
| -rw-r--r-- | src/include/storage/s_lock.h | 91 | ||||
| -rw-r--r-- | src/include/storage/shmem.h | 11 | ||||
| -rw-r--r-- | src/include/storage/sinval.h | 9 | ||||
| -rw-r--r-- | src/include/storage/smgr.h | 6 | ||||
| -rw-r--r-- | src/include/storage/spin.h | 73 |
11 files changed, 197 insertions, 186 deletions
diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h index ca1e1dd4b4..f85a93c258 100644 --- a/src/include/storage/buf_internals.h +++ b/src/include/storage/buf_internals.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: buf_internals.h,v 1.49 2001/07/06 21:04:26 tgl Exp $ + * $Id: buf_internals.h,v 1.50 2001/09/29 04:02:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -17,7 +17,7 @@ #include "storage/backendid.h" #include "storage/buf.h" #include "storage/lmgr.h" -#include "storage/s_lock.h" +#include "storage/lwlock.h" /* Buf Mgr constants */ @@ -89,12 +89,8 @@ typedef struct sbufdesc BufFlags flags; /* see bit definitions above */ unsigned refcount; /* # of backends holding pins on buffer */ - slock_t io_in_progress_lock; /* to wait for I/O to complete */ - slock_t cntx_lock; /* to lock access to page context */ - - unsigned r_locks; /* # of shared locks */ - bool ri_lock; /* read-intent lock */ - bool w_lock; /* context exclusively locked */ + LWLockId io_in_progress_lock; /* to wait for I/O to complete */ + LWLockId cntx_lock; /* to lock access to page context */ bool cntxDirty; /* new way to mark block as dirty */ @@ -117,10 +113,7 @@ typedef struct sbufdesc * We have to free these locks in elog(ERROR)... */ #define BL_IO_IN_PROGRESS (1 << 0) /* unimplemented */ -#define BL_R_LOCK (1 << 1) -#define BL_RI_LOCK (1 << 2) -#define BL_W_LOCK (1 << 3) -#define BL_PIN_COUNT_LOCK (1 << 4) +#define BL_PIN_COUNT_LOCK (1 << 1) /* * mao tracing buffer allocation @@ -173,7 +166,6 @@ extern bits8 *BufferLocks; extern BufferTag *BufferTagLastDirtied; extern LockRelId *BufferRelidLastDirtied; extern bool *BufferDirtiedByMe; -extern SPINLOCK BufMgrLock; /* localbuf.c */ extern BufferDesc *LocalBufferDescriptors; diff --git a/src/include/storage/freespace.h b/src/include/storage/freespace.h index 0f11dd02f9..affde80717 100644 --- a/src/include/storage/freespace.h +++ b/src/include/storage/freespace.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: freespace.h,v 1.2 2001/07/02 20:50:46 tgl Exp $ + * $Id: freespace.h,v 1.3 2001/09/29 04:02:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,11 +16,8 @@ #include "storage/block.h" #include "storage/relfilenode.h" -#include "storage/spin.h" -extern SPINLOCK FreeSpaceLock; - extern int MaxFSMRelations; extern int MaxFSMPages; diff --git a/src/include/storage/ipc.h b/src/include/storage/ipc.h index 8ce1a84593..dae16748d0 100644 --- a/src/include/storage/ipc.h +++ b/src/include/storage/ipc.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: ipc.h,v 1.50 2001/06/27 23:31:39 tgl Exp $ + * $Id: ipc.h,v 1.51 2001/09/29 04:02:26 tgl Exp $ * * Some files that would normally need to include only sys/ipc.h must * instead include this file because on Ultrix, sys/ipc.h is not designed @@ -30,9 +30,9 @@ union semun struct semid_ds *buf; unsigned short *array; }; - #endif + /* generic IPC definitions */ #define IPCProtection (0600) /* access/modify by user only */ @@ -51,7 +51,7 @@ typedef int IpcSemaphoreId; /* semaphore ID returned by semget(2) */ typedef uint32 IpcMemoryKey; /* shared memory key passed to shmget(2) */ typedef int IpcMemoryId; /* shared memory ID returned by shmget(2) */ -typedef struct /* standard header for all Postgres shmem */ +typedef struct PGShmemHeader /* standard header for all Postgres shmem */ { int32 magic; /* magic # to identify Postgres segments */ #define PGShmemMagic 679834892 @@ -61,29 +61,6 @@ typedef struct /* standard header for all Postgres shmem */ } PGShmemHeader; -/* spinlock definitions */ - -typedef enum _LockId_ -{ - BUFMGRLOCKID, - OIDGENLOCKID, - XIDGENLOCKID, - CNTLFILELOCKID, - SHMEMLOCKID, - SHMEMINDEXLOCKID, - LOCKMGRLOCKID, - SINVALLOCKID, - PROCSTRUCTLOCKID, - FREESPACELOCKID, - -#ifdef STABLE_MEMORY_STORAGE - MMCACHELOCKID, -#endif - - MAX_SPINS /* must be last item! */ -} _LockId_; - - /* ipc.c */ extern bool proc_exit_inprogress; diff --git a/src/include/storage/lock.h b/src/include/storage/lock.h index ed134bcc77..b5ac03eb7e 100644 --- a/src/include/storage/lock.h +++ b/src/include/storage/lock.h @@ -7,15 +7,15 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: lock.h,v 1.52 2001/09/27 16:29:13 tgl Exp $ + * $Id: lock.h,v 1.53 2001/09/29 04:02:26 tgl Exp $ * *------------------------------------------------------------------------- */ #ifndef LOCK_H_ #define LOCK_H_ -#include "storage/ipc.h" #include "storage/itemptr.h" +#include "storage/lwlock.h" #include "storage/shmem.h" @@ -26,12 +26,10 @@ typedef struct PROC_QUEUE int size; /* number of entries in list */ } PROC_QUEUE; -/* struct proc is declared in storage/proc.h, but must forward-reference it */ -typedef struct proc PROC; +/* struct PROC is declared in storage/proc.h, but must forward-reference it */ +typedef struct PROC PROC; -extern SPINLOCK LockMgrLock; - extern int max_locks_per_xact; #ifdef LOCK_DEBUG @@ -51,11 +49,7 @@ typedef int LOCKMETHOD; /* MAX_LOCKMODES cannot be larger than the # of bits in LOCKMASK */ #define MAX_LOCKMODES 10 -/* - * MAX_LOCK_METHODS 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. - */ +/* MAX_LOCK_METHODS is the number of distinct lock control tables allowed */ #define MAX_LOCK_METHODS 3 #define INVALID_TABLEID 0 @@ -69,7 +63,7 @@ typedef int LOCKMETHOD; * If user locks are enabled, an additional lock method is present. * * LOCKMETHODCTL and LOCKMETHODTABLE are split because the first lives - * in shared memory. This is because it contains a spinlock. + * in shared memory. (There isn't any really good reason for the split.) * LOCKMETHODTABLE exists in private memory. Both are created by the * postmaster and should be the same in all backends. */ @@ -93,7 +87,7 @@ typedef int LOCKMETHOD; * writers can be given priority over readers (to avoid * starvation). XXX this field is not actually used at present! * - * masterlock -- synchronizes access to the table + * masterLock -- synchronizes access to the table */ typedef struct LOCKMETHODCTL { @@ -101,7 +95,7 @@ typedef struct LOCKMETHODCTL int numLockModes; int conflictTab[MAX_LOCKMODES]; int prio[MAX_LOCKMODES]; - SPINLOCK masterLock; + LWLockId masterLock; } LOCKMETHODCTL; /* @@ -235,11 +229,6 @@ typedef struct HOLDER (((LOCK *) MAKE_PTR((holder).tag.lock))->tag.lockmethod) - -#define LockLockTable() SpinAcquire(LockMgrLock) -#define UnlockLockTable() SpinRelease(LockMgrLock) - - /* * function prototypes */ @@ -267,7 +256,6 @@ extern void InitDeadLockChecking(void); #ifdef LOCK_DEBUG extern void DumpLocks(void); extern void DumpAllLocks(void); - #endif #endif /* LOCK_H */ diff --git a/src/include/storage/lwlock.h b/src/include/storage/lwlock.h new file mode 100644 index 0000000000..02610d3541 --- /dev/null +++ b/src/include/storage/lwlock.h @@ -0,0 +1,69 @@ +/*------------------------------------------------------------------------- + * + * lwlock.h + * Lightweight lock manager + * + * + * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * $Id: lwlock.h,v 1.1 2001/09/29 04:02:26 tgl Exp $ + * + *------------------------------------------------------------------------- + */ +#ifndef LWLOCK_H +#define LWLOCK_H + +/* + * We have a number of predefined LWLocks, plus a bunch of LWLocks that are + * dynamically assigned (for shared buffers). The LWLock structures live + * in shared memory (since they contain shared data) and are identified by + * values of this enumerated type. We abuse the notion of an enum somewhat + * by allowing values not listed in the enum declaration to be assigned. + * The extra value MaxDynamicLWLock is there to keep the compiler from + * deciding that the enum can be represented as char or short ... + */ +typedef enum LWLockId +{ + BufMgrLock, + LockMgrLock, + OidGenLock, + XidGenLock, + ShmemIndexLock, + SInvalLock, + FreeSpaceLock, + MMCacheLock, + WALInsertLock, + WALWriteLock, + ControlFileLock, + CheckpointLock, + CLogControlLock, + + NumFixedLWLocks, /* must be last except for MaxDynamicLWLock */ + + MaxDynamicLWLock = 1000000000 +} LWLockId; + + +typedef enum LWLockMode +{ + LW_EXCLUSIVE, + LW_SHARED +} LWLockMode; + + +#ifdef LOCK_DEBUG +extern bool Trace_lwlocks; +#endif + +extern LWLockId LWLockAssign(void); +extern void LWLockAcquire(LWLockId lockid, LWLockMode mode); +extern bool LWLockConditionalAcquire(LWLockId lockid, LWLockMode mode); +extern void LWLockRelease(LWLockId lockid); +extern void LWLockReleaseAll(void); + +extern int NumLWLocks(void); +extern int LWLockShmemSize(void); +extern void CreateLWLocks(void); + +#endif /* LWLOCK_H */ diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h index 9a1c63ef1b..77def9f473 100644 --- a/src/include/storage/proc.h +++ b/src/include/storage/proc.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: proc.h,v 1.47 2001/09/21 17:06:12 tgl Exp $ + * $Id: proc.h,v 1.48 2001/09/29 04:02:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,10 +16,9 @@ #include "access/xlog.h" #include "storage/backendid.h" +#include "storage/ipc.h" #include "storage/lock.h" -/* configurable option */ -extern int DeadlockTimeout; typedef struct { @@ -35,10 +34,9 @@ typedef struct * the PROC is linked into that lock's waitProcs queue. A recycled PROC * is linked into ProcGlobal's freeProcs list. */ -struct proc +struct PROC { /* proc->links MUST BE FIRST IN STRUCT (see ProcSleep,ProcWakeup,etc) */ - SHM_QUEUE links; /* list link if process is in a list */ SEMA sem; /* ONE semaphore to sleep on */ @@ -51,6 +49,9 @@ struct proc * were starting our xact: vacuum must not * remove tuples deleted by xid >= xmin ! */ + int pid; /* This backend's process id */ + Oid databaseId; /* OID of database this backend is using */ + /* * XLOG location of first XLOG record written by this backend's * current transaction. If backend is not in a transaction or hasn't @@ -58,6 +59,11 @@ struct proc */ XLogRecPtr logRec; + /* Info about LWLock the process is currently waiting for, if any. */ + bool lwWaiting; /* true if waiting for an LW lock */ + bool lwExclusive; /* true if waiting for exclusive access */ + struct PROC *lwWaitLink; /* next waiter for same LW lock */ + /* Info about lock the process is currently waiting for, if any. */ /* waitLock and waitHolder are NULL if not currently waiting. */ LOCK *waitLock; /* Lock object we're sleeping on ... */ @@ -66,32 +72,15 @@ struct proc LOCKMASK heldLocks; /* bitmask for lock types already held on * this lock object by this backend */ - 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 procHolders; /* list of HOLDER objects for locks held * or awaited by this backend */ }; -/* NOTE: "typedef struct proc PROC" appears in storage/lock.h. */ +/* NOTE: "typedef struct PROC PROC" appears in storage/lock.h. */ extern PROC *MyProc; -extern SPINLOCK ProcStructLock; - - -#define PROC_INCR_SLOCK(lock) \ -do { \ - if (MyProc) (MyProc->sLocks[(lock)])++; \ -} while (0) - -#define PROC_DECR_SLOCK(lock) \ -do { \ - if (MyProc) (MyProc->sLocks[(lock)])--; \ -} while (0) - /* * There is one ProcGlobal struct for the whole installation. @@ -120,7 +109,7 @@ typedef struct */ } SEM_MAP_ENTRY; -typedef struct procglobal +typedef struct PROC_HDR { /* Head of list of free PROC structures */ SHMEM_OFFSET freeProcs; @@ -134,11 +123,17 @@ typedef struct procglobal SEM_MAP_ENTRY procSemMap[1]; } PROC_HDR; + +/* configurable option */ +extern int DeadlockTimeout; + + /* * Function Prototypes */ extern void InitProcGlobal(int maxBackends); extern void InitProcess(void); +extern void InitDummyProcess(void); extern void ProcReleaseLocks(bool isCommit); extern void ProcQueueInit(PROC_QUEUE *queue); @@ -146,7 +141,6 @@ extern int ProcSleep(LOCKMETHODTABLE *lockMethodTable, LOCKMODE lockmode, LOCK *lock, HOLDER *holder); extern PROC *ProcWakeup(PROC *proc, int errType); extern void ProcLockWakeup(LOCKMETHODTABLE *lockMethodTable, LOCK *lock); -extern void ProcReleaseSpins(PROC *proc); extern bool LockWaitCancel(void); extern void HandleDeadLock(SIGNAL_ARGS); diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h index 2188dcd9f2..166019a6fa 100644 --- a/src/include/storage/s_lock.h +++ b/src/include/storage/s_lock.h @@ -1,22 +1,13 @@ /*------------------------------------------------------------------------- * * s_lock.h - * This file contains the in-line portion of the implementation - * of spinlocks. + * Hardware-dependent implementation of spinlocks. * - * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/include/storage/s_lock.h,v 1.94 2001/09/24 20:10:44 petere Exp $ + * NOTE: none of the macros in this file are intended to be called directly. + * Call them through the hardware-independent macros in spin.h. * - *------------------------------------------------------------------------- - */ - -/*---------- - * DESCRIPTION - * The public macros that must be provided are: + * The following hardware-dependent macros must be provided for each + * supported platform: * * void S_INIT_LOCK(slock_t *lock) * Initialize a spinlock (to the unlocked state). @@ -33,51 +24,43 @@ * Tests if the lock is free. Returns TRUE if free, FALSE if locked. * This does *not* change the state of the lock. * + * Note to implementors: there are default implementations for all these + * macros at the bottom of the file. Check if your platform can use + * these or needs to override them. + * + * Usually, S_LOCK() is implemented in terms of an even lower-level macro + * TAS(): + * * int TAS(slock_t *lock) * Atomic test-and-set instruction. Attempt to acquire the lock, * but do *not* wait. Returns 0 if successful, nonzero if unable * to acquire the lock. * - * TAS() is a lower-level part of the API, but is used directly in a - * few places that want to do other things while waiting for a lock. - * The S_LOCK() macro is equivalent to - * - * void - * S_LOCK(slock_t *lock) - * { - * unsigned spins = 0; - * - * while (TAS(lock)) - * S_LOCK_SLEEP(lock, spins++, timeout); - * } + * TAS() is NOT part of the API, and should never be called directly. * - * where S_LOCK_SLEEP() checks for timeout and sleeps for a short - * interval. (The timeout is expressed in microseconds, or can be 0 for - * "infinity".) Callers that want to perform useful work while waiting - * can write out this entire loop and insert the "useful work" inside - * the loop. - * - * CAUTION to TAS() callers: on some platforms TAS() may sometimes - * report failure to acquire a lock even when the lock is not locked. - * For example, on Alpha TAS() will "fail" if interrupted. Therefore - * TAS() must *always* be invoked in a retry loop as depicted, even when - * you are certain the lock is free. + * CAUTION: on some platforms TAS() may sometimes report failure to acquire + * a lock even when the lock is not locked. For example, on Alpha TAS() + * will "fail" if interrupted. Therefore TAS() should always be invoked + * in a retry loop, even if you are certain the lock is free. * * On most supported platforms, TAS() uses a tas() function written * in assembly language to execute a hardware atomic-test-and-set * instruction. Equivalent OS-supplied mutex routines could be used too. * * If no system-specific TAS() is available (ie, HAS_TEST_AND_SET is not - * defined), then we fall back on an emulation that uses SysV semaphores. - * This emulation will be MUCH MUCH MUCH slower than a proper TAS() + * defined), then we fall back on an emulation that uses SysV semaphores + * (see spin.c). This emulation will be MUCH MUCH slower than a proper TAS() * implementation, because of the cost of a kernel call per lock or unlock. * An old report is that Postgres spends around 40% of its time in semop(2) * when using the SysV semaphore code. * - * Note to implementors: there are default implementations for all these - * macros at the bottom of the file. Check if your platform can use - * these or needs to override them. - *---------- + * + * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * $Id: s_lock.h,v 1.95 2001/09/29 04:02:26 tgl Exp $ + * + *------------------------------------------------------------------------- */ #ifndef S_LOCK_H #define S_LOCK_H @@ -476,7 +459,7 @@ extern slock_t wc_tas(volatile slock_t *lock); /* * Fake spinlock implementation using SysV semaphores --- slow and prone * to fall foul of kernel limits on number of semaphores, so don't use this - * unless you must! + * unless you must! The subroutines appear in spin.c. */ typedef struct @@ -500,7 +483,7 @@ extern int tas_sema(volatile slock_t *lock); -/**************************************************************************** +/* * Default Definitions - override these above as needed. */ @@ -512,16 +495,6 @@ extern int tas_sema(volatile slock_t *lock); } while (0) #endif /* S_LOCK */ -#if !defined(S_LOCK_SLEEP) -#define S_LOCK_SLEEP(lock,spins,timeout) \ - s_lock_sleep((spins), (timeout), 0, (lock), __FILE__, __LINE__) -#endif /* S_LOCK_SLEEP */ - -#if !defined(S_LOCK_SLEEP_INTERVAL) -#define S_LOCK_SLEEP_INTERVAL(lock,spins,timeout,microsec) \ - s_lock_sleep((spins), (timeout), (microsec), (lock), __FILE__, __LINE__) -#endif /* S_LOCK_SLEEP_INTERVAL */ - #if !defined(S_LOCK_FREE) #define S_LOCK_FREE(lock) (*(lock) == 0) #endif /* S_LOCK_FREE */ @@ -542,13 +515,9 @@ extern int tas(volatile slock_t *lock); /* in port/.../tas.s, or #endif /* TAS */ -/**************************************************************************** +/* * Platform-independent out-of-line support routines */ -extern void s_lock(volatile slock_t *lock, - const char *file, const int line); -extern void s_lock_sleep(unsigned spins, int timeout, int microsec, - volatile slock_t *lock, - const char *file, const int line); +extern void s_lock(volatile slock_t *lock, const char *file, int line); #endif /* S_LOCK_H */ diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index e01a0f0143..1043beb634 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -7,14 +7,13 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: shmem.h,v 1.30 2001/09/07 00:27:30 tgl Exp $ + * $Id: shmem.h,v 1.31 2001/09/29 04:02:27 tgl Exp $ * *------------------------------------------------------------------------- */ #ifndef SHMEM_H #define SHMEM_H -#include "storage/spin.h" #include "utils/hsearch.h" @@ -55,9 +54,6 @@ extern DLLIMPORT SHMEM_OFFSET ShmemBase; (((xx_offs) != 0) && ((xx_offs) != INVALID_OFFSET)) -extern SPINLOCK ShmemLock; -extern SPINLOCK ShmemIndexLock; - /* shmemqueue.c */ typedef struct SHM_QUEUE { @@ -66,16 +62,15 @@ typedef struct SHM_QUEUE } SHM_QUEUE; /* shmem.c */ -extern void InitShmemAllocation(PGShmemHeader *seghdr); +extern void InitShmemAllocation(void *seghdr); extern void *ShmemAlloc(Size size); extern bool ShmemIsValid(unsigned long addr); +extern void InitShmemIndex(void); extern HTAB *ShmemInitHash(char *name, long init_size, long max_size, HASHCTL *infoP, int hash_flags); extern void *ShmemInitStruct(char *name, Size size, bool *foundPtr); -typedef int TableID; - /* size constants for the shmem index table */ /* max size of data structure string name */ #define SHMEM_INDEX_KEYSIZE (50) diff --git a/src/include/storage/sinval.h b/src/include/storage/sinval.h index 2e1ac7bfb1..8ecb9024d2 100644 --- a/src/include/storage/sinval.h +++ b/src/include/storage/sinval.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: sinval.h,v 1.21 2001/08/26 16:56:02 tgl Exp $ + * $Id: sinval.h,v 1.22 2001/09/29 04:02:27 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,7 +16,6 @@ #include "storage/backendid.h" #include "storage/itemptr.h" -#include "storage/spin.h" /* @@ -64,8 +63,6 @@ typedef union } SharedInvalidationMessage; -extern SPINLOCK SInvalLock; - extern int SInvalShmemSize(int maxBackends); extern void CreateSharedInvalidationState(int maxBackends); extern void InitBackendSharedInvalidationState(void); @@ -78,7 +75,7 @@ extern bool DatabaseHasActiveBackends(Oid databaseId, bool ignoreMyself); extern bool TransactionIdIsInProgress(TransactionId xid); extern TransactionId GetOldestXmin(bool allDbs); extern int CountActiveBackends(void); -/* Use "struct proc", not PROC, to avoid including proc.h here */ -extern struct proc *BackendIdGetProc(BackendId procId); +/* Use "struct PROC", not PROC, to avoid including proc.h here */ +extern struct PROC *BackendIdGetProc(BackendId procId); #endif /* SINVAL_H */ diff --git a/src/include/storage/smgr.h b/src/include/storage/smgr.h index b4193b5fa8..d20ce73a8f 100644 --- a/src/include/storage/smgr.h +++ b/src/include/storage/smgr.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: smgr.h,v 1.30 2001/06/27 23:31:39 tgl Exp $ + * $Id: smgr.h,v 1.31 2001/09/29 04:02:27 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -17,9 +17,9 @@ #include "access/xlog.h" #include "storage/relfilenode.h" #include "storage/block.h" -#include "storage/spin.h" #include "utils/rel.h" + #define SM_FAIL 0 #define SM_SUCCESS 1 @@ -79,8 +79,6 @@ extern int mdabort(void); extern int mdsync(void); /* mm.c */ -extern SPINLOCK MMCacheLock; - extern int mminit(void); extern int mmcreate(Relation reln); extern int mmunlink(RelFileNode rnode); diff --git a/src/include/storage/spin.h b/src/include/storage/spin.h index 1d488e5476..bc6ad3fde0 100644 --- a/src/include/storage/spin.h +++ b/src/include/storage/spin.h @@ -1,42 +1,77 @@ /*------------------------------------------------------------------------- * * spin.h - * synchronization routines + * Hardware-independent implementation of spinlocks. + * + * + * The hardware-independent interface to spinlocks is defined by the + * typedef "slock_t" and these macros: + * + * void SpinLockInit(slock_t *lock) + * Initialize a spinlock (to the unlocked state). + * + * void SpinLockAcquire(slock_t *lock) + * Acquire a spinlock, waiting if necessary. + * Time out and abort() if unable to acquire the lock in a + * "reasonable" amount of time --- typically ~ 1 minute. + * Cancel/die interrupts are held off until the lock is released. + * + * void SpinLockRelease(slock_t *lock) + * Unlock a previously acquired lock. + * Release the cancel/die interrupt holdoff. + * + * void SpinLockAcquire_NoHoldoff(slock_t *lock) + * void SpinLockRelease_NoHoldoff(slock_t *lock) + * Same as above, except no interrupt holdoff processing is done. + * This pair of macros may be used when there is a surrounding + * interrupt holdoff. + * + * bool SpinLockFree(slock_t *lock) + * Tests if the lock is free. Returns TRUE if free, FALSE if locked. + * This does *not* change the state of the lock. + * + * Callers must beware that the macro argument may be evaluated multiple + * times! + * + * The macros are implemented in terms of hardware-dependent macros + * supplied by s_lock.h. * * * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: spin.h,v 1.15 2001/03/22 04:01:09 momjian Exp $ + * $Id: spin.h,v 1.16 2001/09/29 04:02:27 tgl Exp $ * *------------------------------------------------------------------------- */ #ifndef SPIN_H #define SPIN_H -#include "storage/ipc.h" +#include "storage/s_lock.h" +#include "miscadmin.h" -/* - * two implementations of spin locks - * - * Where TAS instruction is available: real spin locks. - * See src/storage/ipc/s_lock.c for details. - * - * Otherwise: fake spin locks using semaphores. see spin.c - */ -typedef int SPINLOCK; +#define SpinLockInit(lock) S_INIT_LOCK(lock) + +#define SpinLockAcquire(lock) \ + do { \ + HOLD_INTERRUPTS(); \ + S_LOCK(lock); \ + } while (0) + +#define SpinLockAcquire_NoHoldoff(lock) S_LOCK(lock) -#ifdef LOCK_DEBUG -extern bool Trace_spinlocks; +#define SpinLockRelease(lock) \ + do { \ + S_UNLOCK(lock); \ + RESUME_INTERRUPTS(); \ + } while (0) -#endif +#define SpinLockRelease_NoHoldoff(lock) S_UNLOCK(lock) +#define SpinLockFree(lock) S_LOCK_FREE(lock) -extern int SLockShmemSize(void); -extern void CreateSpinlocks(PGShmemHeader *seghdr); -extern void SpinAcquire(SPINLOCK lockid); -extern void SpinRelease(SPINLOCK lockid); +extern void CreateSpinlocks(void); #endif /* SPIN_H */ |
