PostgreSQL Source Code git master
Loading...
Searching...
No Matches
lwlock.h File Reference
#include "port/atomics.h"
#include "storage/lwlocknames.h"
#include "storage/proclist_types.h"
#include "storage/lwlocklist.h"
Include dependency graph for lwlock.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  LWLock
 
union  LWLockPadded
 

Macros

#define LWLOCK_PADDED_SIZE   PG_CACHE_LINE_SIZE
 
#define NUM_BUFFER_PARTITIONS   128
 
#define LOG2_NUM_LOCK_PARTITIONS   4
 
#define NUM_LOCK_PARTITIONS   (1 << LOG2_NUM_LOCK_PARTITIONS)
 
#define LOG2_NUM_PREDICATELOCK_PARTITIONS   4
 
#define NUM_PREDICATELOCK_PARTITIONS   (1 << LOG2_NUM_PREDICATELOCK_PARTITIONS)
 
#define BUFFER_MAPPING_LWLOCK_OFFSET   NUM_INDIVIDUAL_LWLOCKS
 
#define LOCK_MANAGER_LWLOCK_OFFSET    (BUFFER_MAPPING_LWLOCK_OFFSET + NUM_BUFFER_PARTITIONS)
 
#define PREDICATELOCK_MANAGER_LWLOCK_OFFSET    (LOCK_MANAGER_LWLOCK_OFFSET + NUM_LOCK_PARTITIONS)
 
#define NUM_FIXED_LWLOCKS    (PREDICATELOCK_MANAGER_LWLOCK_OFFSET + NUM_PREDICATELOCK_PARTITIONS)
 
#define PG_LWLOCK(id, name)
 
#define PG_LWLOCKTRANCHE(id, name)   LWTRANCHE_##id,
 

Typedefs

typedef enum LWLockWaitState LWLockWaitState
 
typedef struct LWLock LWLock
 
typedef union LWLockPadded LWLockPadded
 
typedef enum LWLockMode LWLockMode
 
typedef enum BuiltinTrancheIds BuiltinTrancheIds
 
typedef LWLockLWLockId
 

Enumerations

enum  LWLockWaitState { LW_WS_NOT_WAITING , LW_WS_WAITING , LW_WS_PENDING_WAKEUP }
 
enum  LWLockMode { LW_EXCLUSIVE , LW_SHARED , LW_WAIT_UNTIL_FREE }
 
enum  BuiltinTrancheIds { LWTRANCHE_INVALID = NUM_INDIVIDUAL_LWLOCKS - 1 , LWTRANCHE_FIRST_USER_DEFINED }
 

Functions

 StaticAssertDecl (sizeof(LWLock)<=LWLOCK_PADDED_SIZE, "Miscalculated LWLock padding")
 
bool LWLockAcquire (LWLock *lock, LWLockMode mode)
 
bool LWLockConditionalAcquire (LWLock *lock, LWLockMode mode)
 
bool LWLockAcquireOrWait (LWLock *lock, LWLockMode mode)
 
void LWLockRelease (LWLock *lock)
 
void LWLockReleaseClearVar (LWLock *lock, pg_atomic_uint64 *valptr, uint64 val)
 
void LWLockReleaseAll (void)
 
bool LWLockHeldByMe (LWLock *lock)
 
bool LWLockAnyHeldByMe (LWLock *lock, int nlocks, size_t stride)
 
bool LWLockHeldByMeInMode (LWLock *lock, LWLockMode mode)
 
bool LWLockWaitForVar (LWLock *lock, pg_atomic_uint64 *valptr, uint64 oldval, uint64 *newval)
 
void LWLockUpdateVar (LWLock *lock, pg_atomic_uint64 *valptr, uint64 val)
 
void InitLWLockAccess (void)
 
const charGetLWLockIdentifier (uint32 classId, uint16 eventId)
 
void RequestNamedLWLockTranche (const char *tranche_name, int num_lwlocks)
 
LWLockPaddedGetNamedLWLockTranche (const char *tranche_name)
 
int LWLockNewTrancheId (const char *name)
 
void LWLockInitialize (LWLock *lock, int tranche_id)
 

Variables

PGDLLIMPORT LWLockPaddedMainLWLockArray
 

Macro Definition Documentation

◆ BUFFER_MAPPING_LWLOCK_OFFSET

#define BUFFER_MAPPING_LWLOCK_OFFSET   NUM_INDIVIDUAL_LWLOCKS

Definition at line 94 of file lwlock.h.

◆ LOCK_MANAGER_LWLOCK_OFFSET

#define LOCK_MANAGER_LWLOCK_OFFSET    (BUFFER_MAPPING_LWLOCK_OFFSET + NUM_BUFFER_PARTITIONS)

Definition at line 95 of file lwlock.h.

103{
105 LW_SHARED,
106 LW_WAIT_UNTIL_FREE, /* A special mode used in PGPROC->lwWaitMode,
107 * when waiting for lock to become free. Not
108 * to be used as LWLockAcquire argument */
109} LWLockMode;
110
111
112#ifdef LOCK_DEBUG
113extern PGDLLIMPORT bool Trace_lwlocks;
114#endif
115
116extern bool LWLockAcquire(LWLock *lock, LWLockMode mode);
118extern bool LWLockAcquireOrWait(LWLock *lock, LWLockMode mode);
119extern void LWLockRelease(LWLock *lock);
121extern void LWLockReleaseAll(void);
122extern bool LWLockHeldByMe(LWLock *lock);
123extern bool LWLockAnyHeldByMe(LWLock *lock, int nlocks, size_t stride);
124extern bool LWLockHeldByMeInMode(LWLock *lock, LWLockMode mode);
125
128
129extern void InitLWLockAccess(void);
130
131extern const char *GetLWLockIdentifier(uint32 classId, uint16 eventId);
132
133/*
134 * Extensions (or core code) can obtain an LWLocks by calling
135 * RequestNamedLWLockTranche() during postmaster startup. Subsequently,
136 * call GetNamedLWLockTranche() to obtain a pointer to an array containing
137 * the number of LWLocks requested.
138 */
139extern void RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks);
140extern LWLockPadded *GetNamedLWLockTranche(const char *tranche_name);
141
142/*
143 * There is another, more flexible method of obtaining lwlocks. First, call
144 * LWLockNewTrancheId to obtain a tranche ID; this allocates from a shared
145 * counter. Second, LWLockInitialize should be called just once per lwlock,
146 * passing the tranche ID as an argument.
147 */
148extern int LWLockNewTrancheId(const char *name);
149extern void LWLockInitialize(LWLock *lock, int tranche_id);
150
151/*
152 * Every tranche ID less than NUM_INDIVIDUAL_LWLOCKS is reserved; also,
153 * we reserve additional tranche IDs for builtin tranches not included in
154 * the set of individual LWLocks. A call to LWLockNewTrancheId will never
155 * return a value less than LWTRANCHE_FIRST_USER_DEFINED. The actual list of
156 * built-in tranches is kept in lwlocklist.h.
157 */
158typedef enum BuiltinTrancheIds
159{
160 /*
161 * LWTRANCHE_INVALID is an unused value that only exists to initialize the
162 * rest of the tranches to appropriate values.
163 */
165
166#define PG_LWLOCK(id, name)
167#define PG_LWLOCKTRANCHE(id, name) LWTRANCHE_##id,
168#include "storage/lwlocklist.h"
169#undef PG_LWLOCK
170#undef PG_LWLOCKTRANCHE
171
174
175/*
176 * Prior to PostgreSQL 9.4, we used an enum type called LWLockId to refer
177 * to LWLocks. New code should instead use LWLock *. However, for the
178 * convenience of third-party code, we include the following typedef.
179 */
180typedef LWLock *LWLockId;
181
182#endif /* LWLOCK_H */
#define PGDLLIMPORT
Definition c.h:1421
uint64_t uint64
Definition c.h:625
uint16_t uint16
Definition c.h:623
uint32_t uint32
Definition c.h:624
#define newval
long val
Definition informix.c:689
void LWLockUpdateVar(LWLock *lock, pg_atomic_uint64 *valptr, uint64 val)
Definition lwlock.c:1702
bool LWLockHeldByMe(LWLock *lock)
Definition lwlock.c:1885
void LWLockReleaseClearVar(LWLock *lock, pg_atomic_uint64 *valptr, uint64 val)
Definition lwlock.c:1840
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1150
int LWLockNewTrancheId(const char *name)
Definition lwlock.c:562
LWLockPadded * GetNamedLWLockTranche(const char *tranche_name)
Definition lwlock.c:522
bool LWLockHeldByMeInMode(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1929
bool LWLockWaitForVar(LWLock *lock, pg_atomic_uint64 *valptr, uint64 oldval, uint64 *newval)
Definition lwlock.c:1566
void RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks)
Definition lwlock.c:620
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1767
BuiltinTrancheIds
Definition lwlock.h:159
@ LWTRANCHE_FIRST_USER_DEFINED
Definition lwlock.h:172
@ LWTRANCHE_INVALID
Definition lwlock.h:164
void LWLockReleaseAll(void)
Definition lwlock.c:1866
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition lwlock.c:670
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1321
bool LWLockAcquireOrWait(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1378
LWLockMode
Definition lwlock.h:103
@ LW_SHARED
Definition lwlock.h:105
@ LW_WAIT_UNTIL_FREE
Definition lwlock.h:106
@ LW_EXCLUSIVE
Definition lwlock.h:104
LWLock * LWLockId
Definition lwlock.h:180
const char * GetLWLockIdentifier(uint32 classId, uint16 eventId)
Definition lwlock.c:747
bool LWLockAnyHeldByMe(LWLock *lock, int nlocks, size_t stride)
Definition lwlock.c:1903
void InitLWLockAccess(void)
Definition lwlock.c:506
static PgChecksumMode mode
static int fb(int x)
const char * name

◆ LOG2_NUM_LOCK_PARTITIONS

#define LOG2_NUM_LOCK_PARTITIONS   4

Definition at line 86 of file lwlock.h.

◆ LOG2_NUM_PREDICATELOCK_PARTITIONS

#define LOG2_NUM_PREDICATELOCK_PARTITIONS   4

Definition at line 90 of file lwlock.h.

◆ LWLOCK_PADDED_SIZE

#define LWLOCK_PADDED_SIZE   PG_CACHE_LINE_SIZE

Definition at line 62 of file lwlock.h.

◆ NUM_BUFFER_PARTITIONS

#define NUM_BUFFER_PARTITIONS   128

Definition at line 83 of file lwlock.h.

◆ NUM_FIXED_LWLOCKS

Definition at line 99 of file lwlock.h.

◆ NUM_LOCK_PARTITIONS

#define NUM_LOCK_PARTITIONS   (1 << LOG2_NUM_LOCK_PARTITIONS)

Definition at line 87 of file lwlock.h.

◆ NUM_PREDICATELOCK_PARTITIONS

#define NUM_PREDICATELOCK_PARTITIONS   (1 << LOG2_NUM_PREDICATELOCK_PARTITIONS)

Definition at line 91 of file lwlock.h.

◆ PG_LWLOCK

#define PG_LWLOCK (   id,
  name 
)

Definition at line 166 of file lwlock.h.

◆ PG_LWLOCKTRANCHE

#define PG_LWLOCKTRANCHE (   id,
  name 
)    LWTRANCHE_##id,

Definition at line 167 of file lwlock.h.

◆ PREDICATELOCK_MANAGER_LWLOCK_OFFSET

#define PREDICATELOCK_MANAGER_LWLOCK_OFFSET    (LOCK_MANAGER_LWLOCK_OFFSET + NUM_LOCK_PARTITIONS)

Definition at line 97 of file lwlock.h.

Typedef Documentation

◆ BuiltinTrancheIds

◆ LWLock

◆ LWLockId

Definition at line 180 of file lwlock.h.

◆ LWLockMode

◆ LWLockPadded

◆ LWLockWaitState

Enumeration Type Documentation

◆ BuiltinTrancheIds

Enumerator
LWTRANCHE_INVALID 
LWTRANCHE_FIRST_USER_DEFINED 

Definition at line 158 of file lwlock.h.

159{
160 /*
161 * LWTRANCHE_INVALID is an unused value that only exists to initialize the
162 * rest of the tranches to appropriate values.
163 */
165
166#define PG_LWLOCK(id, name)
167#define PG_LWLOCKTRANCHE(id, name) LWTRANCHE_##id,
168#include "storage/lwlocklist.h"
169#undef PG_LWLOCK
170#undef PG_LWLOCKTRANCHE
171

◆ LWLockMode

Enumerator
LW_EXCLUSIVE 
LW_SHARED 
LW_WAIT_UNTIL_FREE 

Definition at line 102 of file lwlock.h.

103{
105 LW_SHARED,
106 LW_WAIT_UNTIL_FREE, /* A special mode used in PGPROC->lwWaitMode,
107 * when waiting for lock to become free. Not
108 * to be used as LWLockAcquire argument */
109} LWLockMode;

◆ LWLockWaitState

Enumerator
LW_WS_NOT_WAITING 
LW_WS_WAITING 
LW_WS_PENDING_WAKEUP 

Definition at line 28 of file lwlock.h.

29{
30 LW_WS_NOT_WAITING, /* not currently waiting / woken up */
31 LW_WS_WAITING, /* currently waiting */
32 LW_WS_PENDING_WAKEUP, /* removed from waitlist, but not yet
33 * signalled */
LWLockWaitState
Definition lwlock.h:29
@ LW_WS_NOT_WAITING
Definition lwlock.h:30
@ LW_WS_WAITING
Definition lwlock.h:31
@ LW_WS_PENDING_WAKEUP
Definition lwlock.h:32

Function Documentation

◆ GetLWLockIdentifier()

const char * GetLWLockIdentifier ( uint32  classId,
uint16  eventId 
)
extern

Definition at line 747 of file lwlock.c.

748{
749 Assert(classId == PG_WAIT_LWLOCK);
750 /* The event IDs are just tranche numbers. */
752}
#define Assert(condition)
Definition c.h:943
static const char * GetLWTrancheName(uint16 trancheId)
Definition lwlock.c:709
#define PG_WAIT_LWLOCK

References Assert, fb(), GetLWTrancheName(), and PG_WAIT_LWLOCK.

Referenced by pgstat_get_wait_event(), test_lwlock_get_lwlock_identifier(), and test_startup_lwlocks().

◆ GetNamedLWLockTranche()

LWLockPadded * GetNamedLWLockTranche ( const char tranche_name)
extern

Definition at line 522 of file lwlock.c.

523{
527
528 /*
529 * Obtain the position of base address of LWLock belonging to requested
530 * tranche_name in MainLWLockArray. LWLocks for user-defined tranches
531 * requested with RequestNamedLWLockTranche() are placed in
532 * MainLWLockArray after fixed locks.
533 */
534 for (int i = 0; i < LocalNumUserDefinedTranches; i++)
535 {
537 tranche_name) == 0)
538 {
540
541 /*
542 * GetNamedLWLockTranche() should only be used for locks requested
543 * with RequestNamedLWLockTranche(), not those allocated with
544 * LWLockNewTrancheId().
545 */
546 if (lock_pos == -1)
547 elog(ERROR, "requested tranche was not registered with RequestNamedLWLockTranche()");
548 return &MainLWLockArray[lock_pos];
549 }
550 }
551
552 elog(ERROR, "requested tranche is not registered");
553
554 /* just to keep compiler quiet */
555 return NULL;
556}
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:227
int i
Definition isn.c:77
static LWLockTrancheShmemData * LWLockTranches
Definition lwlock.c:195
static int LocalNumUserDefinedTranches
Definition lwlock.c:198
LWLockPadded * MainLWLockArray
Definition lwlock.c:150
static void SpinLockRelease(volatile slock_t *lock)
Definition spin.h:62
static void SpinLockAcquire(volatile slock_t *lock)
Definition spin.h:56
struct LWLockTrancheShmemData::@23 user_defined[MAX_USER_DEFINED_TRANCHES]
char name[NAMEDATALEN]
Definition lwlock.c:180

References elog, ERROR, fb(), i, LocalNumUserDefinedTranches, LWLockTrancheShmemData::lock, LWLockTranches, LWLockTrancheShmemData::main_array_idx, MainLWLockArray, LWLockTrancheShmemData::name, LWLockTrancheShmemData::num_user_defined, SpinLockAcquire(), SpinLockRelease(), and LWLockTrancheShmemData::user_defined.

Referenced by test_lwlock_tranche_lookup(), and test_startup_lwlocks().

◆ InitLWLockAccess()

void InitLWLockAccess ( void  )
extern

Definition at line 506 of file lwlock.c.

507{
508#ifdef LWLOCK_STATS
510#endif
511}

References fb().

Referenced by InitAuxiliaryProcess(), and InitProcess().

◆ LWLockAcquire()

bool LWLockAcquire ( LWLock lock,
LWLockMode  mode 
)
extern

Definition at line 1150 of file lwlock.c.

1151{
1152 PGPROC *proc = MyProc;
1153 bool result = true;
1154 int extraWaits = 0;
1155#ifdef LWLOCK_STATS
1157
1159#endif
1160
1162
1163 PRINT_LWDEBUG("LWLockAcquire", lock, mode);
1164
1165#ifdef LWLOCK_STATS
1166 /* Count lock acquisition attempts */
1167 if (mode == LW_EXCLUSIVE)
1168 lwstats->ex_acquire_count++;
1169 else
1170 lwstats->sh_acquire_count++;
1171#endif /* LWLOCK_STATS */
1172
1173 /*
1174 * We can't wait if we haven't got a PGPROC. This should only occur
1175 * during bootstrap or shared memory initialization. Put an Assert here
1176 * to catch unsafe coding practices.
1177 */
1178 Assert(!(proc == NULL && IsUnderPostmaster));
1179
1180 /* Ensure we will have room to remember the lock */
1182 elog(ERROR, "too many LWLocks taken");
1183
1184 /*
1185 * Lock out cancel/die interrupts until we exit the code section protected
1186 * by the LWLock. This ensures that interrupts will not interfere with
1187 * manipulations of data structures in shared memory.
1188 */
1190
1191 /*
1192 * Loop here to try to acquire lock after each time we are signaled by
1193 * LWLockRelease.
1194 *
1195 * NOTE: it might seem better to have LWLockRelease actually grant us the
1196 * lock, rather than retrying and possibly having to go back to sleep. But
1197 * in practice that is no good because it means a process swap for every
1198 * lock acquisition when two or more processes are contending for the same
1199 * lock. Since LWLocks are normally used to protect not-very-long
1200 * sections of computation, a process needs to be able to acquire and
1201 * release the same lock many times during a single CPU time slice, even
1202 * in the presence of contention. The efficiency of being able to do that
1203 * outweighs the inefficiency of sometimes wasting a process dispatch
1204 * cycle because the lock is not free when a released waiter finally gets
1205 * to run. See pgsql-hackers archives for 29-Dec-01.
1206 */
1207 for (;;)
1208 {
1209 bool mustwait;
1210
1211 /*
1212 * Try to grab the lock the first time, we're not in the waitqueue
1213 * yet/anymore.
1214 */
1216
1217 if (!mustwait)
1218 {
1219 LOG_LWDEBUG("LWLockAcquire", lock, "immediately acquired lock");
1220 break; /* got the lock */
1221 }
1222
1223 /*
1224 * Ok, at this point we couldn't grab the lock on the first try. We
1225 * cannot simply queue ourselves to the end of the list and wait to be
1226 * woken up because by now the lock could long have been released.
1227 * Instead add us to the queue and try to grab the lock again. If we
1228 * succeed we need to revert the queuing and be happy, otherwise we
1229 * recheck the lock. If we still couldn't grab it, we know that the
1230 * other locker will see our queue entries when releasing since they
1231 * existed before we checked for the lock.
1232 */
1233
1234 /* add to the queue */
1235 LWLockQueueSelf(lock, mode);
1236
1237 /* we're now guaranteed to be woken up if necessary */
1239
1240 /* ok, grabbed the lock the second time round, need to undo queueing */
1241 if (!mustwait)
1242 {
1243 LOG_LWDEBUG("LWLockAcquire", lock, "acquired, undoing queue");
1244
1245 LWLockDequeueSelf(lock);
1246 break;
1247 }
1248
1249 /*
1250 * Wait until awakened.
1251 *
1252 * It is possible that we get awakened for a reason other than being
1253 * signaled by LWLockRelease. If so, loop back and wait again. Once
1254 * we've gotten the LWLock, re-increment the sema by the number of
1255 * additional signals received.
1256 */
1257 LOG_LWDEBUG("LWLockAcquire", lock, "waiting");
1258
1259#ifdef LWLOCK_STATS
1260 lwstats->block_count++;
1261#endif
1262
1266
1267 for (;;)
1268 {
1269 PGSemaphoreLock(proc->sem);
1270 if (proc->lwWaiting == LW_WS_NOT_WAITING)
1271 break;
1272 extraWaits++;
1273 }
1274
1275 /* Retrying, allow LWLockRelease to release waiters again. */
1277
1278#ifdef LOCK_DEBUG
1279 {
1280 /* not waiting anymore */
1282
1284 }
1285#endif
1286
1290
1291 LOG_LWDEBUG("LWLockAcquire", lock, "awakened");
1292
1293 /* Now loop back and try to acquire lock again. */
1294 result = false;
1295 }
1296
1299
1300 /* Add lock to list of locks held by this backend */
1303
1304 /*
1305 * Fix the process wait semaphore's count for any absorbed wakeups.
1306 */
1307 while (extraWaits-- > 0)
1308 PGSemaphoreUnlock(proc->sem);
1309
1310 return result;
1311}
static uint32 pg_atomic_fetch_and_u32(volatile pg_atomic_uint32 *ptr, uint32 and_)
Definition atomics.h:396
static uint32 pg_atomic_fetch_sub_u32(volatile pg_atomic_uint32 *ptr, int32 sub_)
Definition atomics.h:381
#define PG_USED_FOR_ASSERTS_ONLY
Definition c.h:249
uint32 result
bool IsUnderPostmaster
Definition globals.c:122
static LWLockHandle held_lwlocks[MAX_SIMUL_LWLOCKS]
Definition lwlock.c:167
static bool LWLockAttemptLock(LWLock *lock, LWLockMode mode)
Definition lwlock.c:764
static void LWLockReportWaitEnd(void)
Definition lwlock.c:700
#define MAX_SIMUL_LWLOCKS
Definition lwlock.c:157
#define T_NAME(lock)
Definition lwlock.c:229
static int num_held_lwlocks
Definition lwlock.c:166
#define LOG_LWDEBUG(a, b, c)
Definition lwlock.c:294
static void LWLockQueueSelf(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1018
#define PRINT_LWDEBUG(a, b, c)
Definition lwlock.c:293
static void LWLockReportWaitStart(LWLock *lock)
Definition lwlock.c:691
#define LW_FLAG_WAKE_IN_PROGRESS
Definition lwlock.c:97
static void LWLockDequeueSelf(LWLock *lock)
Definition lwlock.c:1061
#define HOLD_INTERRUPTS()
Definition miscadmin.h:136
void PGSemaphoreUnlock(PGSemaphore sema)
Definition posix_sema.c:333
void PGSemaphoreLock(PGSemaphore sema)
Definition posix_sema.c:313
#define MAX_BACKENDS
Definition procnumber.h:39
PGPROC * MyProc
Definition proc.c:71
LWLockMode mode
Definition lwlock.c:163
LWLock * lock
Definition lwlock.c:162
pg_atomic_uint32 state
Definition lwlock.h:44
Definition proc.h:179
PGSemaphore sem
Definition proc.h:258
uint8 lwWaiting
Definition proc.h:283

References Assert, elog, ERROR, fb(), held_lwlocks, HOLD_INTERRUPTS, IsUnderPostmaster, LWLockHandle::lock, LOG_LWDEBUG, LW_EXCLUSIVE, LW_FLAG_WAKE_IN_PROGRESS, LW_SHARED, LW_WS_NOT_WAITING, LWLockAttemptLock(), LWLockDequeueSelf(), LWLockQueueSelf(), LWLockReportWaitEnd(), LWLockReportWaitStart(), PGPROC::lwWaiting, MAX_BACKENDS, MAX_SIMUL_LWLOCKS, LWLockHandle::mode, mode, MyProc, num_held_lwlocks, pg_atomic_fetch_and_u32(), pg_atomic_fetch_sub_u32(), PG_USED_FOR_ASSERTS_ONLY, PGSemaphoreLock(), PGSemaphoreUnlock(), PRINT_LWDEBUG, result, PGPROC::sem, LWLock::state, and T_NAME.

Referenced by _bt_end_vacuum(), _bt_parallel_done(), _bt_parallel_primscan_schedule(), _bt_parallel_release(), _bt_parallel_seize(), _bt_start_vacuum(), _bt_vacuum_cycleid(), abort_logical_decoding_activation(), AbsorbSyncRequests(), ActivateCommitTs(), addLSNWaiter(), AdvanceNextFullTransactionIdPastXid(), AdvanceOldestClogXid(), AdvanceOldestCommitTsXid(), AdvanceXLInsertBuffer(), alloc_object(), AlterSystemSetConfigFile(), ApplyLauncherMain(), apw_detach_shmem(), apw_dump_now(), apw_load_buffers(), AsyncNotifyFreezeXids(), asyncQueueAddEntries(), asyncQueueAdvanceTail(), asyncQueueReadAllNotifications(), asyncQueueUnregister(), AtAbort_Twophase(), AtEOXact_LogicalRepWorkers(), AtPrepare_PredicateLocks(), attach_internal(), autoprewarm_main(), autoprewarm_start_worker(), AutoVacLauncherMain(), AutoVacuumRequestWork(), AutoVacWorkerMain(), BackendPidGetProc(), BackendXidGetPid(), BecomeLockGroupLeader(), BecomeLockGroupMember(), BecomeRegisteredListener(), btparallelrescan(), BufferAlloc(), CallShmemCallbacksAfterStartup(), check_for_freed_segments(), CheckDeadLock(), CheckForSerializableConflictOut(), CheckLogicalSlotExists(), CheckPointPredicate(), CheckPointRelationMap(), CheckPointReplicationOrigin(), CheckPointReplicationSlots(), CheckPointTwoPhase(), CheckTableForSerializableConflictIn(), CheckTargetForConflictsIn(), choose_next_subplan_for_leader(), choose_next_subplan_for_worker(), CleanupInvalidationState(), ClearOldPredicateLocks(), ComputeXidHorizons(), consume_xids_shortcut(), copy_replication_slot(), CountDBBackends(), CountDBConnections(), CountOtherDBBackends(), CountUserBackends(), CreateCheckPoint(), CreateEndOfRecoveryRecord(), CreateInitDecodingContext(), CreatePredicateLock(), CreateRestartPoint(), DataChecksumsWorkerLauncherMain(), DataChecksumsWorkerMain(), DeactivateCommitTs(), DeleteChildTargetLocks(), DeleteLockTarget(), deleteLSNWaiter(), destroy_superblock(), DisableLogicalDecoding(), DisableLogicalDecodingIfNecessary(), do_autovacuum(), do_pg_backup_start(), do_pg_backup_stop(), do_start_worker(), DropAllPredicateLocksFromTable(), DropTableSpace(), dsa_allocate_extended(), dsa_dump(), dsa_free(), dsa_get_total_size(), dsa_get_total_size_from_handle(), dsa_pin(), dsa_release_in_place(), dsa_set_size_limit(), dsa_trim(), dsa_unpin(), dshash_delete_key(), dshash_dump(), dshash_find(), dshash_find_or_insert_extended(), dshash_seq_next(), dsm_attach(), dsm_create(), dsm_detach(), dsm_pin_segment(), dsm_unpin_segment(), EnableLogicalDecoding(), ensure_active_superblock(), entry_reset(), ExecParallelHashMergeCounters(), ExecParallelHashPopChunkQueue(), ExecParallelHashTupleAlloc(), ExecParallelHashTuplePrealloc(), ExpireAllKnownAssignedTransactionIds(), ExpireOldKnownAssignedTransactionIds(), ExpireTreeKnownAssignedTransactionIds(), ExtendBufferedRelShared(), ExtendCLOG(), ExtendCommitTs(), ExtendMultiXactMember(), ExtendMultiXactOffset(), ExtendSUBTRANS(), FastPathGetRelationLockEntry(), FastPathTransferRelationLocks(), FindAndDropRelationBuffers(), FindDeletedTupleInLocalRel(), FinishPreparedTransaction(), ForceTransactionIdLimitUpdate(), ForwardSyncRequest(), FreeWorkerInfo(), get_local_synced_slots(), get_val_in_shmem(), get_xid_status(), GetBackgroundWorkerPid(), GetBackgroundWorkerTypeByPid(), GetBlockerStatusData(), GetConflictingVirtualXIDs(), GetCurrentVirtualXIDs(), GetLastImportantRecPtr(), GetLastSegSwitchData(), GetLatestCommitTsData(), GetLeaderApplyWorkerPid(), GetLockConflicts(), GetLockStatusData(), GetMultiXactIdMembers(), GetMultiXactInfo(), GetNewMultiXactId(), GetNewObjectId(), GetNewTransactionId(), GetOldestActiveTransactionId(), GetOldestMultiXactId(), GetOldestRestartPoint(), GetOldestSafeDecodingTransactionId(), GetOldestUnsummarizedLSN(), GetPredicateLockStatusData(), GetPreparedTransactionList(), GetRunningTransactionData(), GetRunningTransactionLocks(), GetSafeSnapshot(), GetSafeSnapshotBlockingPids(), GetSerializableTransactionSnapshotInt(), GetSnapshotData(), GetStrictOldestNonRemovableTransactionId(), GetVirtualXIDsDelayingChkpt(), GetWaitEventCustomIdentifier(), GetWaitEventCustomNames(), GetWalSummarizerState(), HaveVirtualXIDsDelayingChkpt(), init_conflict_slot_xmin(), init_dsm_registry(), initGlobalChannelTable(), InitWalSender(), InjectionPointAttach(), InjectionPointDetach(), InjectionPointList(), InstallXLogFileSegment(), InvalidateBuffer(), InvalidateObsoleteReplicationSlots(), InvalidatePossiblyObsoleteSlot(), InvalidateVictimBuffer(), IoWorkerMain(), IsInstallXLogFileSegmentActive(), IsLogicalDecodingEnabled(), IsXLogLogicalInfoEnabled(), KnownAssignedXidsCompress(), KnownAssignedXidsReset(), launcher_exit(), lock_twophase_recover(), LockAcquireExtended(), LockErrorCleanup(), LockGXact(), LockHasWaiters(), LockRefindAndRelease(), LockRelease(), LockReleaseAll(), LockWaiterCount(), logicalrep_launcher_attach_dshmem(), logicalrep_pa_worker_stop(), logicalrep_reset_seqsync_start_time(), logicalrep_worker_attach(), logicalrep_worker_detach(), logicalrep_worker_launch(), logicalrep_worker_stop(), logicalrep_worker_stop_internal(), logicalrep_worker_wakeup(), logicalrep_workers_find(), LookupGXact(), LookupGXactBySubid(), MarkAsPrepared(), MarkAsPreparing(), multixact_redo(), MultiXactAdvanceNextMXact(), MultiXactGetCheckptMulti(), MultiXactIdSetOldestMember(), MultiXactIdSetOldestVisible(), MultiXactSetNextMXact(), PageIsPredicateLocked(), perform_relmap_update(), pg_control_checkpoint(), pg_control_init(), pg_control_recovery(), pg_control_system(), pg_create_advice_stash(), pg_drop_advice_stash(), pg_get_replication_slots(), pg_get_shmem_allocations(), pg_get_shmem_allocations_numa(), pg_notification_queue_usage(), pg_set_stashed_advice(), pg_show_replication_origin_status(), pg_start_stash_advice_worker(), pg_stash_advice_worker_main(), pg_stat_get_subscription(), pg_stat_statements_internal(), pg_xact_status(), pgaio_worker_can_timeout(), pgaio_worker_die(), pgaio_worker_register(), pgsa_attach(), pgsa_detach_shmem(), pgsa_read_from_disk(), pgsa_restore_entries(), pgsa_restore_stashes(), pgss_store(), pgstat_archiver_reset_all_cb(), pgstat_archiver_snapshot_cb(), pgstat_bgwriter_reset_all_cb(), pgstat_bgwriter_snapshot_cb(), pgstat_build_snapshot(), pgstat_checkpointer_reset_all_cb(), pgstat_checkpointer_snapshot_cb(), pgstat_fetch_replslot(), pgstat_io_flush_cb(), pgstat_io_reset_all_cb(), pgstat_io_snapshot_cb(), pgstat_lock_entry(), pgstat_lock_entry_shared(), pgstat_lock_flush_cb(), pgstat_lock_reset_all_cb(), pgstat_lock_snapshot_cb(), pgstat_reset_matching_entries(), pgstat_reset_replslot(), pgstat_reset_slru_counter_internal(), pgstat_slru_flush_cb(), pgstat_slru_snapshot_cb(), pgstat_wal_flush_cb(), pgstat_wal_reset_all_cb(), pgstat_wal_snapshot_cb(), PostPrepare_Locks(), PostPrepare_MultiXact(), PostPrepare_Twophase(), PreCommit_CheckForSerializationFailure(), PreCommit_Notify(), predicatelock_twophase_recover(), PredicateLockPageSplit(), PredicateLockShmemInit(), PredicateLockTwoPhaseFinish(), PrefetchSharedBuffer(), PrescanPreparedTransactions(), ProcArrayAdd(), ProcArrayApplyRecoveryInfo(), ProcArrayApplyXidAssignment(), ProcArrayClearTransaction(), ProcArrayEndTransaction(), ProcArrayGetReplicationSlotXmin(), ProcArrayGroupClearXid(), ProcArrayInstallImportedXmin(), ProcArrayInstallRestoredXmin(), ProcArrayRemove(), ProcArraySetReplicationSlotXmin(), ProcessDatabase(), ProcessSequencesForSync(), ProcessSingleRelationFork(), ProcessSyncingTablesForApply(), ProcKill(), ProcNumberGetTransactionIds(), ProcSleep(), ReachedEndOfBackup(), read_relmap_file(), ReadMultiXactIdRange(), ReadNextFullTransactionId(), ReadNextMultiXactId(), ReadReplicationSlot(), RecordNewMultiXact(), RecoverPreparedTransactions(), RegisterDynamicBackgroundWorker(), RegisterPredicateLockingXid(), RelationCacheInitFilePreInvalidate(), RelationMapCopy(), RelationMapFinishBootstrap(), ReleaseOneSerializableXact(), ReleasePredicateLocks(), relmap_redo(), RemoveScratchTarget(), ReplicationSlotAcquire(), ReplicationSlotCleanup(), ReplicationSlotCreate(), ReplicationSlotDropPtr(), ReplicationSlotName(), ReplicationSlotRelease(), ReplicationSlotReserveWal(), ReplicationSlotsComputeLogicalRestartLSN(), ReplicationSlotsComputeRequiredLSN(), ReplicationSlotsComputeRequiredXmin(), ReplicationSlotsCountDBSlots(), ReplicationSlotsDropDBSlots(), replorigin_advance(), replorigin_get_progress(), replorigin_session_advance(), replorigin_session_get_progress(), replorigin_session_reset_internal(), replorigin_session_setup(), replorigin_state_clear(), RequestDisableLogicalDecoding(), reserve_wal_for_local_slot(), ResetInstallXLogFileSegmentActive(), resize(), RestoreScratchTarget(), restoreTwoPhaseData(), SaveSlotToPath(), SearchNamedReplicationSlot(), SerialAdd(), SerialGetMinConflictCommitSeqNo(), SerialSetActiveSerXmin(), set_indexsafe_procflags(), set_val_in_shmem(), SetCommitTsLimit(), SetDataChecksumsOff(), SetDataChecksumsOn(), SetDataChecksumsOnInProgress(), SetInstallXLogFileSegmentActive(), SetMultiXactIdLimit(), SetNextObjectId(), SetOldestOffset(), SetTransactionIdLimit(), SetXidCommitTsInPage(), SharedInvalBackendInit(), ShmemInitStruct(), SICleanupQueue(), SIGetDataEntries(), SignalBackends(), SignalRecoveryConflict(), SignalRecoveryConflictWithDatabase(), SignalRecoveryConflictWithVirtualXID(), SIInsertDataEntries(), SimpleLruReadPage(), SimpleLruReadPage_ReadOnly(), SimpleLruTruncate(), SimpleLruWaitIO(), SimpleLruWriteAll(), SimpleLruZeroAndWritePage(), SlruDeleteSegment(), SlruInternalWritePage(), SnapBuildInitialSnapshot(), ss_get_location(), StandbyRecoverPreparedTransactions(), StandbySlotsHaveCaughtup(), StartDataChecksumsWorkerLauncher(), StartupDecodingContext(), StartupSUBTRANS(), StartupXLOG(), sts_parallel_scan_next(), SubTransSetParent(), SummarizeOldestCommittedSxact(), SummarizeWAL(), SwitchIntoArchiveRecovery(), synchronize_one_slot(), SyncRepCancelWait(), SyncRepCleanupAtProcExit(), SyncRepReleaseWaiters(), SyncRepUpdateSyncStandbysDefined(), SyncRepWaitForLSN(), TablespaceCreateDbspace(), tbm_shared_iterate(), TerminateBackgroundWorker(), TerminateBackgroundWorkersForDatabase(), TerminateOtherDBBackends(), test_custom_stats_fixed_reset_all_cb(), test_custom_stats_fixed_snapshot_cb(), test_custom_stats_fixed_update(), test_slru_page_exists(), test_slru_page_read(), test_slru_page_write(), test_startup_lwlocks(), TransactionGroupUpdateXidStatus(), TransactionIdGetCommitTsData(), TransactionIdIsInProgress(), TransactionIdSetPageStatus(), TransactionTreeSetCommitTsData(), TransferPredicateLocksToNewTarget(), TrimCLOG(), TrimMultiXact(), TruncateMultiXact(), TwoPhaseGetGXact(), TwoPhaseGetOldestXidInCommit(), TwoPhaseGetXidByVirtualXID(), update_cached_xid_range(), update_synced_slots_inactive_since(), UpdateLogicalDecodingStatusEndOfRecovery(), UpdateMinRecoveryPoint(), vac_truncate_clog(), vacuum_rel(), VacuumUpdateCosts(), VirtualXactLock(), VirtualXactLockTableCleanup(), VirtualXactLockTableInsert(), wait_for_table_state_change(), wait_for_worker_state_change(), WaitEventCustomNew(), WaitForAllTransactionsToFinish(), WaitForReplicationWorkerAttach(), WaitForWalSummarization(), wakeupWaiters(), WakeupWalSummarizer(), WALInsertLockAcquire(), WALInsertLockAcquireExclusive(), WalSummarizerMain(), WalSummarizerShutdown(), write_relcache_init_file(), xact_redo(), XidCacheRemoveRunningXids(), xlog_redo(), XLogBackgroundFlush(), and XLogReportParameters().

◆ LWLockAcquireOrWait()

bool LWLockAcquireOrWait ( LWLock lock,
LWLockMode  mode 
)
extern

Definition at line 1378 of file lwlock.c.

1379{
1380 PGPROC *proc = MyProc;
1381 bool mustwait;
1382 int extraWaits = 0;
1383#ifdef LWLOCK_STATS
1385
1387#endif
1388
1390
1391 PRINT_LWDEBUG("LWLockAcquireOrWait", lock, mode);
1392
1393 /* Ensure we will have room to remember the lock */
1395 elog(ERROR, "too many LWLocks taken");
1396
1397 /*
1398 * Lock out cancel/die interrupts until we exit the code section protected
1399 * by the LWLock. This ensures that interrupts will not interfere with
1400 * manipulations of data structures in shared memory.
1401 */
1403
1404 /*
1405 * NB: We're using nearly the same twice-in-a-row lock acquisition
1406 * protocol as LWLockAcquire(). Check its comments for details.
1407 */
1409
1410 if (mustwait)
1411 {
1413
1415
1416 if (mustwait)
1417 {
1418 /*
1419 * Wait until awakened. Like in LWLockAcquire, be prepared for
1420 * bogus wakeups.
1421 */
1422 LOG_LWDEBUG("LWLockAcquireOrWait", lock, "waiting");
1423
1424#ifdef LWLOCK_STATS
1425 lwstats->block_count++;
1426#endif
1427
1431
1432 for (;;)
1433 {
1434 PGSemaphoreLock(proc->sem);
1435 if (proc->lwWaiting == LW_WS_NOT_WAITING)
1436 break;
1437 extraWaits++;
1438 }
1439
1440#ifdef LOCK_DEBUG
1441 {
1442 /* not waiting anymore */
1444
1446 }
1447#endif
1451
1452 LOG_LWDEBUG("LWLockAcquireOrWait", lock, "awakened");
1453 }
1454 else
1455 {
1456 LOG_LWDEBUG("LWLockAcquireOrWait", lock, "acquired, undoing queue");
1457
1458 /*
1459 * Got lock in the second attempt, undo queueing. We need to treat
1460 * this as having successfully acquired the lock, otherwise we'd
1461 * not necessarily wake up people we've prevented from acquiring
1462 * the lock.
1463 */
1464 LWLockDequeueSelf(lock);
1465 }
1466 }
1467
1468 /*
1469 * Fix the process wait semaphore's count for any absorbed wakeups.
1470 */
1471 while (extraWaits-- > 0)
1472 PGSemaphoreUnlock(proc->sem);
1473
1474 if (mustwait)
1475 {
1476 /* Failed to get lock, so release interrupt holdoff */
1478 LOG_LWDEBUG("LWLockAcquireOrWait", lock, "failed");
1481 }
1482 else
1483 {
1484 LOG_LWDEBUG("LWLockAcquireOrWait", lock, "succeeded");
1485 /* Add lock to list of locks held by this backend */
1490 }
1491
1492 return !mustwait;
1493}
#define RESUME_INTERRUPTS()
Definition miscadmin.h:138

References Assert, elog, ERROR, fb(), held_lwlocks, HOLD_INTERRUPTS, LWLockHandle::lock, LOG_LWDEBUG, LW_EXCLUSIVE, LW_SHARED, LW_WAIT_UNTIL_FREE, LW_WS_NOT_WAITING, LWLockAttemptLock(), LWLockDequeueSelf(), LWLockQueueSelf(), LWLockReportWaitEnd(), LWLockReportWaitStart(), PGPROC::lwWaiting, MAX_BACKENDS, MAX_SIMUL_LWLOCKS, LWLockHandle::mode, mode, MyProc, num_held_lwlocks, pg_atomic_fetch_sub_u32(), PG_USED_FOR_ASSERTS_ONLY, PGSemaphoreLock(), PGSemaphoreUnlock(), PRINT_LWDEBUG, RESUME_INTERRUPTS, PGPROC::sem, and T_NAME.

Referenced by XLogFlush().

◆ LWLockAnyHeldByMe()

bool LWLockAnyHeldByMe ( LWLock lock,
int  nlocks,
size_t  stride 
)
extern

Definition at line 1903 of file lwlock.c.

1904{
1905 char *held_lock_addr;
1906 char *begin;
1907 char *end;
1908 int i;
1909
1910 begin = (char *) lock;
1911 end = begin + nlocks * stride;
1912 for (i = 0; i < num_held_lwlocks; i++)
1913 {
1914 held_lock_addr = (char *) held_lwlocks[i].lock;
1915 if (held_lock_addr >= begin &&
1916 held_lock_addr < end &&
1917 (held_lock_addr - begin) % stride == 0)
1918 return true;
1919 }
1920 return false;
1921}

References fb(), held_lwlocks, i, and num_held_lwlocks.

◆ LWLockConditionalAcquire()

bool LWLockConditionalAcquire ( LWLock lock,
LWLockMode  mode 
)
extern

Definition at line 1321 of file lwlock.c.

1322{
1323 bool mustwait;
1324
1326
1327 PRINT_LWDEBUG("LWLockConditionalAcquire", lock, mode);
1328
1329 /* Ensure we will have room to remember the lock */
1331 elog(ERROR, "too many LWLocks taken");
1332
1333 /*
1334 * Lock out cancel/die interrupts until we exit the code section protected
1335 * by the LWLock. This ensures that interrupts will not interfere with
1336 * manipulations of data structures in shared memory.
1337 */
1339
1340 /* Check for the lock */
1342
1343 if (mustwait)
1344 {
1345 /* Failed to get lock, so release interrupt holdoff */
1347
1348 LOG_LWDEBUG("LWLockConditionalAcquire", lock, "failed");
1351 }
1352 else
1353 {
1354 /* Add lock to list of locks held by this backend */
1359 }
1360 return !mustwait;
1361}

References Assert, elog, ERROR, fb(), held_lwlocks, HOLD_INTERRUPTS, LWLockHandle::lock, LOG_LWDEBUG, LW_EXCLUSIVE, LW_SHARED, LWLockAttemptLock(), MAX_SIMUL_LWLOCKS, LWLockHandle::mode, mode, num_held_lwlocks, PRINT_LWDEBUG, RESUME_INTERRUPTS, and T_NAME.

Referenced by pgaio_worker_submit(), pgstat_io_flush_cb(), pgstat_lock_entry(), pgstat_lock_entry_shared(), pgstat_lock_flush_cb(), pgstat_slru_flush_cb(), pgstat_wal_flush_cb(), ProcArrayEndTransaction(), SimpleLruWaitIO(), ss_report_location(), TransactionIdSetPageStatus(), and XLogNeedsFlush().

◆ LWLockHeldByMe()

◆ LWLockHeldByMeInMode()

◆ LWLockInitialize()

void LWLockInitialize ( LWLock lock,
int  tranche_id 
)
extern

Definition at line 670 of file lwlock.c.

671{
672 /* verify the tranche_id is valid */
673 (void) GetLWTrancheName(tranche_id);
674
675 pg_atomic_init_u32(&lock->state, 0);
676#ifdef LOCK_DEBUG
677 pg_atomic_init_u32(&lock->nwaiters, 0);
678#endif
679 lock->tranche = tranche_id;
680 proclist_init(&lock->waiters);
681}
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition atomics.h:219
static void proclist_init(proclist_head *list)
Definition proclist.h:29
uint16 tranche
Definition lwlock.h:43
proclist_head waiters
Definition lwlock.h:45

References fb(), GetLWTrancheName(), pg_atomic_init_u32(), proclist_init(), LWLock::state, LWLock::tranche, and LWLock::waiters.

Referenced by apw_init_state(), btinitparallelscan(), create_internal(), dshash_create(), ExecAppendInitializeDSM(), ExecHashJoinInitializeDSM(), init_tdr_dsm(), InitShmemAllocator(), LWLockShmemInit(), pgsa_init_shared_state(), pgss_shmem_init(), pgstat_archiver_init_shmem_cb(), pgstat_bgwriter_init_shmem_cb(), pgstat_checkpointer_init_shmem_cb(), pgstat_init_entry(), pgstat_io_init_shmem_cb(), pgstat_lock_init_shmem_cb(), pgstat_slru_init_shmem_cb(), pgstat_wal_init_shmem_cb(), PredicateLockShmemInit(), ProcGlobalShmemInit(), ReplicationOriginShmemInit(), ReplicationSlotsShmemInit(), shmem_slru_init(), sts_initialize(), tbm_prepare_shared_iterate(), test_custom_stats_fixed_init_shmem_cb(), test_lwlock_initialize(), and XLOGShmemInit().

◆ LWLockNewTrancheId()

int LWLockNewTrancheId ( const char name)
extern

Definition at line 562 of file lwlock.c.

563{
564 int idx;
565
566 if (!name)
569 errmsg("tranche name cannot be NULL")));
570
571 if (strlen(name) >= NAMEDATALEN)
574 errmsg("tranche name too long"),
575 errdetail("LWLock tranche names must be no longer than %d bytes.",
576 NAMEDATALEN - 1)));
577
578 /* The counter and the tranche names are protected by the spinlock */
580
582 {
585 (errmsg("maximum number of tranches already registered"),
586 errdetail("No more than %d tranches may be registered.",
588 }
589
590 /* Allocate an entry in the user_defined array */
592
593 /* update our local copy while we're at it */
595
596 /* Initialize it */
598
599 /* the locks are not in the main array */
601
603
605}
Datum idx(PG_FUNCTION_ARGS)
Definition _int_op.c:262
int errcode(int sqlerrcode)
Definition elog.c:874
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define ereport(elevel,...)
Definition elog.h:151
#define MAX_USER_DEFINED_TRANCHES
Definition lwlock.c:170
static char * errmsg
#define NAMEDATALEN
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition strlcpy.c:45

References ereport, errcode(), errdetail(), errmsg, ERROR, fb(), idx(), LocalNumUserDefinedTranches, LWLockTrancheShmemData::lock, LWLockTranches, LWTRANCHE_FIRST_USER_DEFINED, LWLockTrancheShmemData::main_array_idx, MAX_USER_DEFINED_TRANCHES, LWLockTrancheShmemData::name, name, NAMEDATALEN, LWLockTrancheShmemData::num_user_defined, SpinLockAcquire(), SpinLockRelease(), strlcpy(), and LWLockTrancheShmemData::user_defined.

Referenced by apw_init_state(), GetNamedDSA(), GetNamedDSHash(), init_tdr_dsm(), init_tranche(), pgsa_init_shared_state(), pgss_shmem_init(), shmem_slru_init(), test_basic(), test_create(), test_empty(), test_lwlock_tranche_create(), and test_random().

◆ LWLockRelease()

void LWLockRelease ( LWLock lock)
extern

Definition at line 1767 of file lwlock.c.

1768{
1771 bool check_waiters;
1772 int i;
1773
1774 /*
1775 * Remove lock from list of locks held. Usually, but not always, it will
1776 * be the latest-acquired lock; so search array backwards.
1777 */
1778 for (i = num_held_lwlocks; --i >= 0;)
1779 if (lock == held_lwlocks[i].lock)
1780 break;
1781
1782 if (i < 0)
1783 elog(ERROR, "lock %s is not held", T_NAME(lock));
1784
1786
1788 for (; i < num_held_lwlocks; i++)
1789 held_lwlocks[i] = held_lwlocks[i + 1];
1790
1791 PRINT_LWDEBUG("LWLockRelease", lock, mode);
1792
1793 /*
1794 * Release my hold on lock, after that it can immediately be acquired by
1795 * others, even if we still have to wakeup other waiters.
1796 */
1797 if (mode == LW_EXCLUSIVE)
1799 else
1801
1802 /* nobody else can have that kind of lock */
1804
1807
1808 /*
1809 * Check if we're still waiting for backends to get scheduled, if so,
1810 * don't wake them up again.
1811 */
1812 if ((oldstate & LW_FLAG_HAS_WAITERS) &&
1814 (oldstate & LW_LOCK_MASK) == 0)
1815 check_waiters = true;
1816 else
1817 check_waiters = false;
1818
1819 /*
1820 * As waking up waiters requires the spinlock to be acquired, only do so
1821 * if necessary.
1822 */
1823 if (check_waiters)
1824 {
1825 /* XXX: remove before commit? */
1826 LOG_LWDEBUG("LWLockRelease", lock, "releasing waiters");
1827 LWLockWakeup(lock);
1828 }
1829
1830 /*
1831 * Now okay to allow cancel/die interrupts.
1832 */
1834}
static uint32 pg_atomic_sub_fetch_u32(volatile pg_atomic_uint32 *ptr, int32 sub_)
Definition atomics.h:439
#define LW_VAL_EXCLUSIVE
Definition lwlock.c:103
static void LWLockWakeup(LWLock *lock)
Definition lwlock.c:904
#define LW_VAL_SHARED
Definition lwlock.c:104
#define LW_LOCK_MASK
Definition lwlock.c:108
#define LW_FLAG_HAS_WAITERS
Definition lwlock.c:96

References Assert, elog, ERROR, fb(), held_lwlocks, i, LOG_LWDEBUG, LW_EXCLUSIVE, LW_FLAG_HAS_WAITERS, LW_FLAG_WAKE_IN_PROGRESS, LW_LOCK_MASK, LW_VAL_EXCLUSIVE, LW_VAL_SHARED, LWLockWakeup(), LWLockHandle::mode, mode, num_held_lwlocks, pg_atomic_sub_fetch_u32(), PRINT_LWDEBUG, RESUME_INTERRUPTS, LWLock::state, and T_NAME.

Referenced by _bt_end_vacuum(), _bt_parallel_done(), _bt_parallel_primscan_schedule(), _bt_parallel_release(), _bt_parallel_seize(), _bt_start_vacuum(), _bt_vacuum_cycleid(), abort_logical_decoding_activation(), AbsorbSyncRequests(), ActivateCommitTs(), addLSNWaiter(), AdvanceNextFullTransactionIdPastXid(), AdvanceOldestClogXid(), AdvanceOldestCommitTsXid(), AdvanceXLInsertBuffer(), alloc_object(), AlterSystemSetConfigFile(), ApplyLauncherMain(), apw_detach_shmem(), apw_dump_now(), apw_load_buffers(), AsyncNotifyFreezeXids(), asyncQueueAddEntries(), asyncQueueAdvanceTail(), asyncQueueProcessPageEntries(), asyncQueueReadAllNotifications(), asyncQueueUnregister(), AtAbort_Twophase(), AtEOXact_LogicalRepWorkers(), AtPrepare_PredicateLocks(), attach_internal(), autoprewarm_main(), autoprewarm_start_worker(), AutoVacLauncherMain(), AutoVacuumRequestWork(), AutoVacWorkerMain(), BackendPidGetProc(), BackendXidGetPid(), BecomeLockGroupLeader(), BecomeLockGroupMember(), BecomeRegisteredListener(), btparallelrescan(), BufferAlloc(), CallShmemCallbacksAfterStartup(), check_for_freed_segments(), CheckDeadLock(), CheckForSerializableConflictOut(), CheckLogicalSlotExists(), CheckPointPredicate(), CheckPointRelationMap(), CheckPointReplicationOrigin(), CheckPointReplicationSlots(), CheckPointTwoPhase(), CheckTableForSerializableConflictIn(), CheckTargetForConflictsIn(), choose_next_subplan_for_leader(), choose_next_subplan_for_worker(), CleanupInvalidationState(), ClearOldPredicateLocks(), ComputeXidHorizons(), consume_xids_shortcut(), copy_replication_slot(), CountDBBackends(), CountDBConnections(), CountOtherDBBackends(), CountUserBackends(), CreateCheckPoint(), CreateEndOfRecoveryRecord(), CreateInitDecodingContext(), CreatePredicateLock(), CreateRestartPoint(), DataChecksumsWorkerLauncherMain(), DataChecksumsWorkerMain(), DeactivateCommitTs(), DeleteChildTargetLocks(), DeleteLockTarget(), deleteLSNWaiter(), destroy_superblock(), DisableLogicalDecoding(), DisableLogicalDecodingIfNecessary(), do_autovacuum(), do_pg_backup_start(), do_pg_backup_stop(), do_start_worker(), DropAllPredicateLocksFromTable(), DropTableSpace(), dsa_allocate_extended(), dsa_dump(), dsa_free(), dsa_get_total_size(), dsa_get_total_size_from_handle(), dsa_pin(), dsa_release_in_place(), dsa_set_size_limit(), dsa_trim(), dsa_unpin(), dshash_delete_entry(), dshash_delete_key(), dshash_dump(), dshash_find(), dshash_find_or_insert_extended(), dshash_release_lock(), dshash_seq_next(), dshash_seq_term(), dsm_attach(), dsm_create(), dsm_detach(), dsm_pin_segment(), dsm_unpin_segment(), EnableLogicalDecoding(), ensure_active_superblock(), entry_reset(), ExecParallelHashMergeCounters(), ExecParallelHashPopChunkQueue(), ExecParallelHashTupleAlloc(), ExecParallelHashTuplePrealloc(), ExpireAllKnownAssignedTransactionIds(), ExpireOldKnownAssignedTransactionIds(), ExpireTreeKnownAssignedTransactionIds(), ExtendBufferedRelShared(), ExtendCLOG(), ExtendCommitTs(), ExtendMultiXactMember(), ExtendMultiXactOffset(), ExtendSUBTRANS(), FastPathGetRelationLockEntry(), FastPathTransferRelationLocks(), find_multixact_start(), FindAndDropRelationBuffers(), FindDeletedTupleInLocalRel(), FinishPreparedTransaction(), ForceTransactionIdLimitUpdate(), ForwardSyncRequest(), FreeWorkerInfo(), get_local_synced_slots(), get_val_in_shmem(), get_xid_status(), GetBackgroundWorkerPid(), GetBackgroundWorkerTypeByPid(), GetBlockerStatusData(), GetConflictingVirtualXIDs(), GetCurrentVirtualXIDs(), GetLastImportantRecPtr(), GetLastSegSwitchData(), GetLatestCommitTsData(), GetLeaderApplyWorkerPid(), GetLockConflicts(), GetLockStatusData(), GetMultiXactIdMembers(), GetMultiXactInfo(), GetNewMultiXactId(), GetNewObjectId(), GetNewTransactionId(), GetOldestActiveTransactionId(), GetOldestMultiXactId(), GetOldestRestartPoint(), GetOldestSafeDecodingTransactionId(), GetOldestUnsummarizedLSN(), GetPredicateLockStatusData(), GetPreparedTransactionList(), GetRunningTransactionLocks(), GetSafeSnapshot(), GetSafeSnapshotBlockingPids(), GetSerializableTransactionSnapshotInt(), GetSnapshotData(), GetStrictOldestNonRemovableTransactionId(), GetVirtualXIDsDelayingChkpt(), GetWaitEventCustomIdentifier(), GetWaitEventCustomNames(), GetWalSummarizerState(), HaveVirtualXIDsDelayingChkpt(), init_conflict_slot_xmin(), init_dsm_registry(), initGlobalChannelTable(), InitWalSender(), InjectionPointAttach(), InjectionPointDetach(), InjectionPointList(), InstallXLogFileSegment(), InvalidateBuffer(), InvalidateObsoleteReplicationSlots(), InvalidatePossiblyObsoleteSlot(), InvalidateVictimBuffer(), IoWorkerMain(), IsInstallXLogFileSegmentActive(), IsLogicalDecodingEnabled(), IsXLogLogicalInfoEnabled(), KnownAssignedXidsCompress(), KnownAssignedXidsReset(), launcher_exit(), lock_twophase_recover(), LockAcquireExtended(), LockErrorCleanup(), LockGXact(), LockHasWaiters(), LockRefindAndRelease(), LockRelease(), LockReleaseAll(), LockWaiterCount(), logicalrep_launcher_attach_dshmem(), logicalrep_pa_worker_stop(), logicalrep_reset_seqsync_start_time(), logicalrep_worker_attach(), logicalrep_worker_detach(), logicalrep_worker_launch(), logicalrep_worker_stop(), logicalrep_worker_stop_internal(), logicalrep_worker_wakeup(), logicalrep_workers_find(), LogStandbySnapshot(), LookupGXact(), LookupGXactBySubid(), LWLockReleaseAll(), LWLockReleaseClearVar(), MarkAsPrepared(), MarkAsPreparing(), multixact_redo(), MultiXactAdvanceNextMXact(), MultiXactGetCheckptMulti(), MultiXactIdSetOldestMember(), MultiXactIdSetOldestVisible(), MultiXactSetNextMXact(), OnConflict_CheckForSerializationFailure(), PageIsPredicateLocked(), perform_relmap_update(), pg_control_checkpoint(), pg_control_init(), pg_control_recovery(), pg_control_system(), pg_create_advice_stash(), pg_drop_advice_stash(), pg_get_replication_slots(), pg_get_shmem_allocations(), pg_get_shmem_allocations_numa(), pg_notification_queue_usage(), pg_set_stashed_advice(), pg_show_replication_origin_status(), pg_start_stash_advice_worker(), pg_stash_advice_worker_main(), pg_stat_get_subscription(), pg_stat_statements_internal(), pg_xact_status(), pgaio_worker_can_timeout(), pgaio_worker_die(), pgaio_worker_register(), pgaio_worker_submit(), pgsa_attach(), pgsa_detach_shmem(), pgsa_read_from_disk(), pgsa_restore_entries(), pgsa_restore_stashes(), pgss_store(), pgstat_archiver_reset_all_cb(), pgstat_archiver_snapshot_cb(), pgstat_bgwriter_reset_all_cb(), pgstat_bgwriter_snapshot_cb(), pgstat_build_snapshot(), pgstat_checkpointer_reset_all_cb(), pgstat_checkpointer_snapshot_cb(), pgstat_fetch_replslot(), pgstat_io_flush_cb(), pgstat_io_reset_all_cb(), pgstat_io_snapshot_cb(), pgstat_lock_flush_cb(), pgstat_lock_reset_all_cb(), pgstat_lock_snapshot_cb(), pgstat_reset_matching_entries(), pgstat_reset_replslot(), pgstat_reset_slru_counter_internal(), pgstat_slru_flush_cb(), pgstat_slru_snapshot_cb(), pgstat_unlock_entry(), pgstat_wal_flush_cb(), pgstat_wal_reset_all_cb(), pgstat_wal_snapshot_cb(), PostPrepare_Locks(), PostPrepare_MultiXact(), PostPrepare_Twophase(), PreCommit_CheckForSerializationFailure(), PreCommit_Notify(), predicatelock_twophase_recover(), PredicateLockPageSplit(), PredicateLockShmemInit(), PredicateLockTwoPhaseFinish(), PrefetchSharedBuffer(), PrescanPreparedTransactions(), ProcArrayAdd(), ProcArrayApplyRecoveryInfo(), ProcArrayApplyXidAssignment(), ProcArrayClearTransaction(), ProcArrayEndTransaction(), ProcArrayGetReplicationSlotXmin(), ProcArrayGroupClearXid(), ProcArrayInstallImportedXmin(), ProcArrayInstallRestoredXmin(), ProcArrayRemove(), ProcArraySetReplicationSlotXmin(), ProcessDatabase(), ProcessSequencesForSync(), ProcessSingleRelationFork(), ProcessSyncingTablesForApply(), ProcKill(), ProcNumberGetTransactionIds(), ProcSleep(), ReachedEndOfBackup(), read_relmap_file(), ReadMultiXactIdRange(), ReadNextFullTransactionId(), ReadNextMultiXactId(), ReadReplicationSlot(), RecordNewMultiXact(), RecoverPreparedTransactions(), RegisterDynamicBackgroundWorker(), RegisterPredicateLockingXid(), RelationCacheInitFilePostInvalidate(), RelationMapCopy(), RelationMapFinishBootstrap(), ReleaseOneSerializableXact(), ReleasePredicateLocks(), relmap_redo(), RemoveScratchTarget(), ReplicationSlotAcquire(), ReplicationSlotCleanup(), ReplicationSlotCreate(), ReplicationSlotDropPtr(), ReplicationSlotName(), ReplicationSlotRelease(), ReplicationSlotReserveWal(), ReplicationSlotsComputeLogicalRestartLSN(), ReplicationSlotsComputeRequiredLSN(), ReplicationSlotsComputeRequiredXmin(), ReplicationSlotsCountDBSlots(), ReplicationSlotsDropDBSlots(), replorigin_advance(), replorigin_get_progress(), replorigin_session_advance(), replorigin_session_get_progress(), replorigin_session_reset_internal(), replorigin_session_setup(), replorigin_state_clear(), RequestDisableLogicalDecoding(), reserve_wal_for_local_slot(), ResetInstallXLogFileSegmentActive(), resize(), RestoreScratchTarget(), restoreTwoPhaseData(), SaveSlotToPath(), SearchNamedReplicationSlot(), SerialAdd(), SerialGetMinConflictCommitSeqNo(), SerialSetActiveSerXmin(), set_indexsafe_procflags(), set_val_in_shmem(), SetCommitTsLimit(), SetDataChecksumsOff(), SetDataChecksumsOn(), SetDataChecksumsOnInProgress(), SetInstallXLogFileSegmentActive(), SetMultiXactIdLimit(), SetNextObjectId(), SetOldestOffset(), SetTransactionIdLimit(), SetXidCommitTsInPage(), SharedInvalBackendInit(), ShmemInitStruct(), SICleanupQueue(), SIGetDataEntries(), SignalBackends(), SignalRecoveryConflict(), SignalRecoveryConflictWithDatabase(), SignalRecoveryConflictWithVirtualXID(), SIInsertDataEntries(), SimpleLruReadPage(), SimpleLruReadPage_ReadOnly(), SimpleLruTruncate(), SimpleLruWaitIO(), SimpleLruWriteAll(), SimpleLruZeroAndWritePage(), SlruDeleteSegment(), SlruInternalWritePage(), SnapBuildInitialSnapshot(), ss_get_location(), ss_report_location(), StandbyRecoverPreparedTransactions(), StandbySlotsHaveCaughtup(), StartDataChecksumsWorkerLauncher(), StartupDecodingContext(), StartupSUBTRANS(), StartupXLOG(), sts_parallel_scan_next(), SubTransGetParent(), SubTransSetParent(), SummarizeOldestCommittedSxact(), SummarizeWAL(), SwitchIntoArchiveRecovery(), synchronize_one_slot(), SyncRepCancelWait(), SyncRepCleanupAtProcExit(), SyncRepReleaseWaiters(), SyncRepUpdateSyncStandbysDefined(), SyncRepWaitForLSN(), TablespaceCreateDbspace(), tbm_shared_iterate(), TerminateBackgroundWorker(), TerminateBackgroundWorkersForDatabase(), TerminateOtherDBBackends(), test_custom_stats_fixed_reset_all_cb(), test_custom_stats_fixed_snapshot_cb(), test_custom_stats_fixed_update(), test_slru_page_exists(), test_slru_page_read(), test_slru_page_readonly(), test_slru_page_write(), test_startup_lwlocks(), TransactionGroupUpdateXidStatus(), TransactionIdGetCommitTsData(), TransactionIdGetStatus(), TransactionIdIsInProgress(), TransactionIdSetPageStatus(), TransactionTreeSetCommitTsData(), TransferPredicateLocksToNewTarget(), TrimCLOG(), TrimMultiXact(), TruncateMultiXact(), TwoPhaseGetGXact(), TwoPhaseGetOldestXidInCommit(), TwoPhaseGetXidByVirtualXID(), update_cached_xid_range(), update_synced_slots_inactive_since(), UpdateLogicalDecodingStatusEndOfRecovery(), UpdateMinRecoveryPoint(), vac_truncate_clog(), vacuum_rel(), VacuumUpdateCosts(), VirtualXactLock(), VirtualXactLockTableCleanup(), VirtualXactLockTableInsert(), wait_for_table_state_change(), wait_for_worker_state_change(), WaitEventCustomNew(), WaitForAllTransactionsToFinish(), WaitForReplicationWorkerAttach(), WaitForWalSummarization(), wakeupWaiters(), WakeupWalSummarizer(), WalSummarizerMain(), WalSummarizerShutdown(), write_relcache_init_file(), xact_redo(), XidCacheRemoveRunningXids(), xlog_redo(), XLogBackgroundFlush(), XLogFlush(), XLogNeedsFlush(), and XLogReportParameters().

◆ LWLockReleaseAll()

void LWLockReleaseAll ( void  )
extern

◆ LWLockReleaseClearVar()

void LWLockReleaseClearVar ( LWLock lock,
pg_atomic_uint64 valptr,
uint64  val 
)
extern

Definition at line 1840 of file lwlock.c.

1841{
1842 /*
1843 * Note that pg_atomic_exchange_u64 is a full barrier, so we're guaranteed
1844 * that the variable is updated before releasing the lock.
1845 */
1847
1848 LWLockRelease(lock);
1849}
static uint64 pg_atomic_exchange_u64(volatile pg_atomic_uint64 *ptr, uint64 newval)
Definition atomics.h:513

References fb(), LWLockRelease(), pg_atomic_exchange_u64(), and val.

Referenced by WALInsertLockRelease().

◆ LWLockUpdateVar()

void LWLockUpdateVar ( LWLock lock,
pg_atomic_uint64 valptr,
uint64  val 
)
extern

Definition at line 1702 of file lwlock.c.

1703{
1706
1707 PRINT_LWDEBUG("LWLockUpdateVar", lock, LW_EXCLUSIVE);
1708
1709 /*
1710 * Note that pg_atomic_exchange_u64 is a full barrier, so we're guaranteed
1711 * that the variable is updated before waking up waiters.
1712 */
1714
1716
1717 LWLockWaitListLock(lock);
1718
1720
1721 /*
1722 * See if there are any LW_WAIT_UNTIL_FREE waiters that need to be woken
1723 * up. They are always in the front of the queue.
1724 */
1725 proclist_foreach_modify(iter, &lock->waiters, lwWaitLink)
1726 {
1727 PGPROC *waiter = GetPGProcByNumber(iter.cur);
1728
1729 if (waiter->lwWaitMode != LW_WAIT_UNTIL_FREE)
1730 break;
1731
1732 proclist_delete(&lock->waiters, iter.cur, lwWaitLink);
1733 proclist_push_tail(&wakeup, iter.cur, lwWaitLink);
1734
1735 /* see LWLockWakeup() */
1736 Assert(waiter->lwWaiting == LW_WS_WAITING);
1738 }
1739
1740 /* We are done updating shared state of the lock itself. */
1742
1743 /*
1744 * Awaken any waiters I removed from the queue.
1745 */
1746 proclist_foreach_modify(iter, &wakeup, lwWaitLink)
1747 {
1748 PGPROC *waiter = GetPGProcByNumber(iter.cur);
1749
1750 proclist_delete(&wakeup, iter.cur, lwWaitLink);
1751 /* check comment in LWLockWakeup() about this barrier */
1753 waiter->lwWaiting = LW_WS_NOT_WAITING;
1754 PGSemaphoreUnlock(waiter->sem);
1755 }
1756}
#define pg_write_barrier()
Definition atomics.h:155
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition atomics.h:237
static void LWLockWaitListLock(LWLock *lock)
Definition lwlock.c:835
static void LWLockWaitListUnlock(LWLock *lock)
Definition lwlock.c:891
#define GetPGProcByNumber(n)
Definition proc.h:504
#define proclist_delete(list, procno, link_member)
Definition proclist.h:187
#define proclist_push_tail(list, procno, link_member)
Definition proclist.h:191
#define proclist_foreach_modify(iter, lhead, link_member)
Definition proclist.h:206
uint8 lwWaitMode
Definition proc.h:284
static TimestampTz wakeup[NUM_WALRCV_WAKEUPS]

References Assert, proclist_mutable_iter::cur, fb(), GetPGProcByNumber, LW_EXCLUSIVE, LW_VAL_EXCLUSIVE, LW_WAIT_UNTIL_FREE, LW_WS_NOT_WAITING, LW_WS_PENDING_WAKEUP, LW_WS_WAITING, LWLockWaitListLock(), LWLockWaitListUnlock(), PGPROC::lwWaiting, PGPROC::lwWaitMode, pg_atomic_exchange_u64(), pg_atomic_read_u32(), pg_write_barrier, PGSemaphoreUnlock(), PRINT_LWDEBUG, proclist_delete, proclist_foreach_modify, proclist_init(), proclist_push_tail, PGPROC::sem, LWLock::state, val, LWLock::waiters, and wakeup.

Referenced by WALInsertLockAcquireExclusive(), and WALInsertLockUpdateInsertingAt().

◆ LWLockWaitForVar()

bool LWLockWaitForVar ( LWLock lock,
pg_atomic_uint64 valptr,
uint64  oldval,
uint64 newval 
)
extern

Definition at line 1566 of file lwlock.c.

1568{
1569 PGPROC *proc = MyProc;
1570 int extraWaits = 0;
1571 bool result = false;
1572#ifdef LWLOCK_STATS
1574
1576#endif
1577
1578 PRINT_LWDEBUG("LWLockWaitForVar", lock, LW_WAIT_UNTIL_FREE);
1579
1580 /*
1581 * Lock out cancel/die interrupts while we sleep on the lock. There is no
1582 * cleanup mechanism to remove us from the wait queue if we got
1583 * interrupted.
1584 */
1586
1587 /*
1588 * Loop here to check the lock's status after each time we are signaled.
1589 */
1590 for (;;)
1591 {
1592 bool mustwait;
1593
1595 &result);
1596
1597 if (!mustwait)
1598 break; /* the lock was free or value didn't match */
1599
1600 /*
1601 * Add myself to wait queue. Note that this is racy, somebody else
1602 * could wakeup before we're finished queuing. NB: We're using nearly
1603 * the same twice-in-a-row lock acquisition protocol as
1604 * LWLockAcquire(). Check its comments for details. The only
1605 * difference is that we also have to check the variable's values when
1606 * checking the state of the lock.
1607 */
1609
1610 /*
1611 * Clear LW_FLAG_WAKE_IN_PROGRESS flag, to make sure we get woken up
1612 * as soon as the lock is released.
1613 */
1615
1616 /*
1617 * We're now guaranteed to be woken up if necessary. Recheck the lock
1618 * and variables state.
1619 */
1621 &result);
1622
1623 /* Ok, no conflict after we queued ourselves. Undo queueing. */
1624 if (!mustwait)
1625 {
1626 LOG_LWDEBUG("LWLockWaitForVar", lock, "free, undoing queue");
1627
1628 LWLockDequeueSelf(lock);
1629 break;
1630 }
1631
1632 /*
1633 * Wait until awakened.
1634 *
1635 * It is possible that we get awakened for a reason other than being
1636 * signaled by LWLockRelease. If so, loop back and wait again. Once
1637 * we've gotten the LWLock, re-increment the sema by the number of
1638 * additional signals received.
1639 */
1640 LOG_LWDEBUG("LWLockWaitForVar", lock, "waiting");
1641
1642#ifdef LWLOCK_STATS
1643 lwstats->block_count++;
1644#endif
1645
1649
1650 for (;;)
1651 {
1652 PGSemaphoreLock(proc->sem);
1653 if (proc->lwWaiting == LW_WS_NOT_WAITING)
1654 break;
1655 extraWaits++;
1656 }
1657
1658#ifdef LOCK_DEBUG
1659 {
1660 /* not waiting anymore */
1662
1664 }
1665#endif
1666
1670
1671 LOG_LWDEBUG("LWLockWaitForVar", lock, "awakened");
1672
1673 /* Now loop back and check the status of the lock again. */
1674 }
1675
1676 /*
1677 * Fix the process wait semaphore's count for any absorbed wakeups.
1678 */
1679 while (extraWaits-- > 0)
1680 PGSemaphoreUnlock(proc->sem);
1681
1682 /*
1683 * Now okay to allow cancel/die interrupts.
1684 */
1686
1687 return result;
1688}
static bool LWLockConflictsWithVar(LWLock *lock, pg_atomic_uint64 *valptr, uint64 oldval, uint64 *newval, bool *result)
Definition lwlock.c:1505

References Assert, fb(), HOLD_INTERRUPTS, LOG_LWDEBUG, LW_EXCLUSIVE, LW_FLAG_WAKE_IN_PROGRESS, LW_WAIT_UNTIL_FREE, LW_WS_NOT_WAITING, LWLockConflictsWithVar(), LWLockDequeueSelf(), LWLockQueueSelf(), LWLockReportWaitEnd(), LWLockReportWaitStart(), PGPROC::lwWaiting, MAX_BACKENDS, MyProc, newval, pg_atomic_fetch_and_u32(), pg_atomic_fetch_sub_u32(), PG_USED_FOR_ASSERTS_ONLY, PGSemaphoreLock(), PGSemaphoreUnlock(), PRINT_LWDEBUG, result, RESUME_INTERRUPTS, PGPROC::sem, LWLock::state, and T_NAME.

Referenced by WaitXLogInsertionsToFinish().

◆ RequestNamedLWLockTranche()

void RequestNamedLWLockTranche ( const char tranche_name,
int  num_lwlocks 
)
extern

Definition at line 620 of file lwlock.c.

621{
623 MemoryContext oldcontext;
624
626 elog(FATAL, "cannot request additional LWLocks outside shmem_request_hook");
627
628 if (!tranche_name)
631 errmsg("tranche name cannot be NULL")));
632
633 if (strlen(tranche_name) >= NAMEDATALEN)
636 errmsg("tranche name too long"),
637 errdetail("LWLock tranche names must be no longer than %d bytes.",
638 NAMEDATALEN - 1)));
639
642 (errmsg("maximum number of tranches already registered"),
643 errdetail("No more than %d tranches may be registered.",
645
646 /* Check that the name isn't already in use */
648 {
649 if (strcmp(existing->tranche_name, tranche_name) == 0)
650 elog(ERROR, "requested tranche \"%s\" is already registered", tranche_name);
651 }
652
655 else
657
659 strlcpy(request->tranche_name, tranche_name, NAMEDATALEN);
660 request->num_lwlocks = num_lwlocks;
662
663 MemoryContextSwitchTo(oldcontext);
664}
#define FATAL
Definition elog.h:41
bool IsPostmasterEnvironment
Definition globals.c:121
List * lappend(List *list, void *datum)
Definition list.c:339
static List * NamedLWLockTrancheRequests
Definition lwlock.c:211
void * palloc0(Size size)
Definition mcxt.c:1417
MemoryContext TopMemoryContext
Definition mcxt.c:166
MemoryContext PostmasterContext
Definition mcxt.c:168
bool process_shmem_requests_in_progress
Definition miscinit.c:1792
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
static int list_length(const List *l)
Definition pg_list.h:152
#define foreach_ptr(type, var, lst)
Definition pg_list.h:501

References elog, ereport, errcode(), errdetail(), errmsg, ERROR, FATAL, fb(), foreach_ptr, IsPostmasterEnvironment, lappend(), list_length(), MAX_USER_DEFINED_TRANCHES, MemoryContextSwitchTo(), NAMEDATALEN, NamedLWLockTrancheRequests, palloc0(), PostmasterContext, process_shmem_requests_in_progress, strlcpy(), and TopMemoryContext.

Referenced by test_lwlock_tranches_shmem_request().

◆ StaticAssertDecl()

StaticAssertDecl ( sizeof(LWLock)<=  LWLOCK_PADDED_SIZE,
"Miscalculated LWLock padding"   
)

Variable Documentation

◆ MainLWLockArray