From 583c818e3121c0f7c6506b434497c81ae94ee9cb Mon Sep 17 00:00:00 2001 From: Craig Ringer Date: Thu, 19 Nov 2020 17:30:47 +0800 Subject: [PATCH v1 4/4] Comments on LWLock tranches --- src/backend/storage/lmgr/lwlock.c | 49 +++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index cfdfa7f328..123bcc463e 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -112,11 +112,14 @@ extern slock_t *ShmemLock; * * 1. The individually-named locks defined in lwlocknames.h each have their * own tranche. The names of these tranches appear in IndividualLWLockNames[] - * in lwlocknames.c. + * in lwlocknames.c. The LWLock structs are allocated in MainLWLockArray. * * 2. There are some predefined tranches for built-in groups of locks. * These are listed in enum BuiltinTrancheIds in lwlock.h, and their names - * appear in BuiltinTrancheNames[] below. + * appear in BuiltinTrancheNames[] below. The LWLock structs are allocated + * elsewhere under the control of the subsystem that manages the tranche. The + * LWLock code does not know or care where in shared memory they are allocated + * or how many there are in a tranche. * * 3. Extensions can create new tranches, via either RequestNamedLWLockTranche * or LWLockRegisterTranche. The names of these that are known in the current @@ -196,6 +199,13 @@ static int LWLockTrancheNamesAllocated = 0; * This points to the main array of LWLocks in shared memory. Backends inherit * the pointer by fork from the postmaster (except in the EXEC_BACKEND case, * where we have special measures to pass it down). + * + * This array holds individual LWLocks and LWLocks allocated in named tranches. + * + * It does not hold locks for any LWLock that's separately initialized with + * LWLockInitialize(). Locks in tranches listed in BuiltinTrancheIds or + * allocated with LWLockNewTrancheId() can be embedded in other structs + * anywhere in shared memory. */ LWLockPadded *MainLWLockArray = NULL; @@ -593,6 +603,12 @@ InitLWLockAccess(void) * Caller needs to retrieve the requested number of LWLocks starting from * the base lock address returned by this API. This can be used for * tranches that are requested by using RequestNamedLWLockTranche() API. + * + * The locks are already initialized. + * + * This function can not be used for locks in builtin tranches or tranches + * registered with LWLockRegisterTranche(). There is no way to look those locks + * up by name. */ LWLockPadded * GetNamedLWLockTranche(const char *tranche_name) @@ -647,6 +663,14 @@ LWLockNewTrancheId(void) * * The tranche name will be user-visible as a wait event name, so try to * use a name that fits the style for those. + * + * The tranche ID should be a user-defined tranche ID acquired from + * LWLockNewTrancheId(). It is not necessary to call this for tranches + * allocated by RequestNamedLWLockTranche(). + * + * The LWLock subsystem does not know where LWLock(s) that will be assigned to + * this tranche are stored, or how many of them there are. The caller allocates + * suitable shared memory storage and initializes locks with LWLockInitialize(). */ void LWLockRegisterTranche(int tranche_id, const char *tranche_name) @@ -699,6 +723,10 @@ LWLockRegisterTranche(int tranche_id, const char *tranche_name) * * The tranche name will be user-visible as a wait event name, so try to * use a name that fits the style for those. + * + * The LWLocks allocated here are retrieved after shmem startup using + * GetNamedLWLockTranche(). They are intialized during shared memory startup so + * it is not necessary to call LWLockInitialize() on them. */ void RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks) @@ -739,10 +767,17 @@ RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks) /* * LWLockInitialize - initialize a new lwlock; it's initially unlocked + * + * For callers outside the LWLock subsystem itself, the tranche ID must either + * be a BuiltinTrancheIds entry for the calling subsysytem or a tranche ID + * assigned with LWLockNewTrancheId(). */ void LWLockInitialize(LWLock *lock, int tranche_id) { + /* Re-initialization of individual LWLocks is not permitted */ + Assert(tranche_id >= NUM_INDIVIDUAL_LWLOCKS || !IsUnderPostmaster); + pg_atomic_init_u32(&lock->state, LW_FLAG_RELEASE_OK); #ifdef LOCK_DEBUG pg_atomic_init_u32(&lock->nwaiters, 0); @@ -803,6 +838,11 @@ GetLWTrancheName(uint16 trancheId) /* * Return an identifier for an LWLock based on the wait class and event. + * + * Note that there's no way to identify a individual LWLock within a tranche by + * anything except its address. The LWLock subsystem doesn't know how many + * locks there are in all tranches and there's no requirement that they be + * stored in contiguous arrays. */ const char * GetLWLockIdentifier(uint32 classId, uint16 eventId) @@ -1010,7 +1050,7 @@ LWLockWakeup(LWLock *lock) Assert(proclist_is_empty(&wakeup) || pg_atomic_read_u32(&lock->state) & LW_FLAG_HAS_WAITERS); - /* unset required flags, and release lock, in one fell swoop */ + /* unset required flags, and release waitlist lock, in one fell swoop */ { uint32 old_state; uint32 desired_state; @@ -1837,6 +1877,9 @@ LWLockUpdateVar(LWLock *lock, uint64 *valptr, uint64 val) /* * LWLockRelease - release a previously acquired lock + * + * The actual lock acquire corresponding to this release happens in + * LWLockAttemptLock(). */ void LWLockRelease(LWLock *lock) -- 2.29.2