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 struct NamedLWLockTrancheRequest NamedLWLockTrancheRequest
 
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)
 
Size LWLockShmemSize (void)
 
void CreateLWLocks (void)
 
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
 
PGDLLIMPORT char ** LWLockTrancheNames
 
PGDLLIMPORT int NamedLWLockTrancheRequests
 
PGDLLIMPORT NamedLWLockTrancheRequestNamedLWLockTrancheRequestArray
 
PGDLLIMPORT intLWLockCounter
 

Macro Definition Documentation

◆ BUFFER_MAPPING_LWLOCK_OFFSET

#define BUFFER_MAPPING_LWLOCK_OFFSET   NUM_INDIVIDUAL_LWLOCKS

Definition at line 102 of file lwlock.h.

◆ LOCK_MANAGER_LWLOCK_OFFSET

#define LOCK_MANAGER_LWLOCK_OFFSET    (BUFFER_MAPPING_LWLOCK_OFFSET + NUM_BUFFER_PARTITIONS)

Definition at line 103 of file lwlock.h.

111{
113 LW_SHARED,
114 LW_WAIT_UNTIL_FREE, /* A special mode used in PGPROC->lwWaitMode,
115 * when waiting for lock to become free. Not
116 * to be used as LWLockAcquire argument */
117} LWLockMode;
118
119
120#ifdef LOCK_DEBUG
121extern PGDLLIMPORT bool Trace_lwlocks;
122#endif
123
124extern bool LWLockAcquire(LWLock *lock, LWLockMode mode);
126extern bool LWLockAcquireOrWait(LWLock *lock, LWLockMode mode);
127extern void LWLockRelease(LWLock *lock);
129extern void LWLockReleaseAll(void);
130extern bool LWLockHeldByMe(LWLock *lock);
131extern bool LWLockAnyHeldByMe(LWLock *lock, int nlocks, size_t stride);
132extern bool LWLockHeldByMeInMode(LWLock *lock, LWLockMode mode);
133
136
137extern Size LWLockShmemSize(void);
138extern void CreateLWLocks(void);
139extern void InitLWLockAccess(void);
140
141extern const char *GetLWLockIdentifier(uint32 classId, uint16 eventId);
142
143/*
144 * Extensions (or core code) can obtain an LWLocks by calling
145 * RequestNamedLWLockTranche() during postmaster startup. Subsequently,
146 * call GetNamedLWLockTranche() to obtain a pointer to an array containing
147 * the number of LWLocks requested.
148 */
149extern void RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks);
150extern LWLockPadded *GetNamedLWLockTranche(const char *tranche_name);
151
152/*
153 * There is another, more flexible method of obtaining lwlocks. First, call
154 * LWLockNewTrancheId to obtain a tranche ID; this allocates from a shared
155 * counter. Second, LWLockInitialize should be called just once per lwlock,
156 * passing the tranche ID as an argument.
157 */
158extern int LWLockNewTrancheId(const char *name);
159extern void LWLockInitialize(LWLock *lock, int tranche_id);
160
161/*
162 * Every tranche ID less than NUM_INDIVIDUAL_LWLOCKS is reserved; also,
163 * we reserve additional tranche IDs for builtin tranches not included in
164 * the set of individual LWLocks. A call to LWLockNewTrancheId will never
165 * return a value less than LWTRANCHE_FIRST_USER_DEFINED. The actual list of
166 * built-in tranches is kept in lwlocklist.h.
167 */
168typedef enum BuiltinTrancheIds
169{
170 /*
171 * LWTRANCHE_INVALID is an unused value that only exists to initialize the
172 * rest of the tranches to appropriate values.
173 */
175
176#define PG_LWLOCK(id, name)
177#define PG_LWLOCKTRANCHE(id, name) LWTRANCHE_##id,
178#include "storage/lwlocklist.h"
179#undef PG_LWLOCK
180#undef PG_LWLOCKTRANCHE
181
184
185/*
186 * Prior to PostgreSQL 9.4, we used an enum type called LWLockId to refer
187 * to LWLocks. New code should instead use LWLock *. However, for the
188 * convenience of third-party code, we include the following typedef.
189 */
190typedef LWLock *LWLockId;
191
192#endif /* LWLOCK_H */
#define PGDLLIMPORT
Definition c.h:1423
uint64_t uint64
Definition c.h:619
uint16_t uint16
Definition c.h:617
uint32_t uint32
Definition c.h:618
size_t Size
Definition c.h:691
#define newval
long val
Definition informix.c:689
void LWLockUpdateVar(LWLock *lock, pg_atomic_uint64 *valptr, uint64 val)
Definition lwlock.c:1729
bool LWLockHeldByMe(LWLock *lock)
Definition lwlock.c:1912
void LWLockReleaseClearVar(LWLock *lock, pg_atomic_uint64 *valptr, uint64 val)
Definition lwlock.c:1867
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1177
void CreateLWLocks(void)
Definition lwlock.c:442
int LWLockNewTrancheId(const char *name)
Definition lwlock.c:597
LWLockPadded * GetNamedLWLockTranche(const char *tranche_name)
Definition lwlock.c:567
bool LWLockHeldByMeInMode(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1956
bool LWLockWaitForVar(LWLock *lock, pg_atomic_uint64 *valptr, uint64 oldval, uint64 *newval)
Definition lwlock.c:1593
void RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks)
Definition lwlock.c:650
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1794
BuiltinTrancheIds
Definition lwlock.h:169
@ LWTRANCHE_FIRST_USER_DEFINED
Definition lwlock.h:182
@ LWTRANCHE_INVALID
Definition lwlock.h:174
void LWLockReleaseAll(void)
Definition lwlock.c:1893
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition lwlock.c:699
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1348
bool LWLockAcquireOrWait(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1405
LWLockMode
Definition lwlock.h:111
@ LW_SHARED
Definition lwlock.h:113
@ LW_WAIT_UNTIL_FREE
Definition lwlock.h:114
@ LW_EXCLUSIVE
Definition lwlock.h:112
LWLock * LWLockId
Definition lwlock.h:190
const char * GetLWLockIdentifier(uint32 classId, uint16 eventId)
Definition lwlock.c:774
Size LWLockShmemSize(void)
Definition lwlock.c:398
bool LWLockAnyHeldByMe(LWLock *lock, int nlocks, size_t stride)
Definition lwlock.c:1930
void InitLWLockAccess(void)
Definition lwlock.c:551
static PgChecksumMode mode
static int fb(int x)
const char * name

◆ LOG2_NUM_LOCK_PARTITIONS

#define LOG2_NUM_LOCK_PARTITIONS   4

Definition at line 94 of file lwlock.h.

◆ LOG2_NUM_PREDICATELOCK_PARTITIONS

#define LOG2_NUM_PREDICATELOCK_PARTITIONS   4

Definition at line 98 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 91 of file lwlock.h.

◆ NUM_FIXED_LWLOCKS

Definition at line 107 of file lwlock.h.

◆ NUM_LOCK_PARTITIONS

#define NUM_LOCK_PARTITIONS   (1 << LOG2_NUM_LOCK_PARTITIONS)

Definition at line 95 of file lwlock.h.

◆ NUM_PREDICATELOCK_PARTITIONS

#define NUM_PREDICATELOCK_PARTITIONS   (1 << LOG2_NUM_PREDICATELOCK_PARTITIONS)

Definition at line 99 of file lwlock.h.

◆ PG_LWLOCK

#define PG_LWLOCK (   id,
  name 
)

Definition at line 176 of file lwlock.h.

◆ PG_LWLOCKTRANCHE

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

Definition at line 177 of file lwlock.h.

◆ PREDICATELOCK_MANAGER_LWLOCK_OFFSET

#define PREDICATELOCK_MANAGER_LWLOCK_OFFSET    (LOCK_MANAGER_LWLOCK_OFFSET + NUM_LOCK_PARTITIONS)

Definition at line 105 of file lwlock.h.

Typedef Documentation

◆ BuiltinTrancheIds

◆ LWLock

◆ LWLockId

Definition at line 190 of file lwlock.h.

◆ LWLockMode

◆ LWLockPadded

◆ LWLockWaitState

◆ NamedLWLockTrancheRequest

Enumeration Type Documentation

◆ BuiltinTrancheIds

Enumerator
LWTRANCHE_INVALID 
LWTRANCHE_FIRST_USER_DEFINED 

Definition at line 168 of file lwlock.h.

169{
170 /*
171 * LWTRANCHE_INVALID is an unused value that only exists to initialize the
172 * rest of the tranches to appropriate values.
173 */
175
176#define PG_LWLOCK(id, name)
177#define PG_LWLOCKTRANCHE(id, name) LWTRANCHE_##id,
178#include "storage/lwlocklist.h"
179#undef PG_LWLOCK
180#undef PG_LWLOCKTRANCHE
181

◆ LWLockMode

Enumerator
LW_EXCLUSIVE 
LW_SHARED 
LW_WAIT_UNTIL_FREE 

Definition at line 110 of file lwlock.h.

111{
113 LW_SHARED,
114 LW_WAIT_UNTIL_FREE, /* A special mode used in PGPROC->lwWaitMode,
115 * when waiting for lock to become free. Not
116 * to be used as LWLockAcquire argument */
117} 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

◆ CreateLWLocks()

void CreateLWLocks ( void  )
extern

Definition at line 442 of file lwlock.c.

443{
445 {
447 char *ptr;
448
449 /* Allocate space */
450 ptr = (char *) ShmemAlloc(spaceLocks);
451
452 /* Initialize the dynamic-allocation counter for tranches */
453 LWLockCounter = (int *) ptr;
455 ptr += MAXALIGN(sizeof(int));
456
457 /* Initialize tranche names */
458 LWLockTrancheNames = (char **) ptr;
459 ptr += MAX_NAMED_TRANCHES * sizeof(char *);
460 for (int i = 0; i < MAX_NAMED_TRANCHES; i++)
461 {
462 LWLockTrancheNames[i] = ptr;
463 ptr += NAMEDATALEN;
464 }
465
466 /*
467 * Move named tranche requests to shared memory. This is done for the
468 * benefit of EXEC_BACKEND builds, which otherwise wouldn't be able to
469 * call GetNamedLWLockTranche() outside postmaster.
470 */
472 {
473 /*
474 * Save the pointer to the request array in postmaster's local
475 * memory. We'll need it if we ever need to re-initialize shared
476 * memory after a crash.
477 */
479
484 }
485
486 /* Ensure desired alignment of LWLock array */
489
490 /* Initialize all LWLocks */
492 }
493}
#define MAXALIGN(LEN)
Definition c.h:898
bool IsUnderPostmaster
Definition globals.c:120
int i
Definition isn.c:77
char ** LWLockTrancheNames
Definition lwlock.c:155
int NamedLWLockTrancheRequests
Definition lwlock.c:193
static NamedLWLockTrancheRequest * LocalNamedLWLockTrancheRequestArray
Definition lwlock.c:197
static void InitializeLWLocks(void)
Definition lwlock.c:499
NamedLWLockTrancheRequest * NamedLWLockTrancheRequestArray
Definition lwlock.c:194
LWLockPadded * MainLWLockArray
Definition lwlock.c:162
int * LWLockCounter
Definition lwlock.c:200
Size LWLockShmemSize(void)
Definition lwlock.c:398
#define MAX_NAMED_TRANCHES
Definition lwlock.c:205
#define LWLOCK_PADDED_SIZE
Definition lwlock.h:62
#define NAMEDATALEN
void * ShmemAlloc(Size size)
Definition shmem.c:185

References fb(), i, InitializeLWLocks(), IsUnderPostmaster, LocalNamedLWLockTrancheRequestArray, LWLOCK_PADDED_SIZE, LWLockCounter, LWLockShmemSize(), LWLockTrancheNames, LWTRANCHE_FIRST_USER_DEFINED, MainLWLockArray, MAX_NAMED_TRANCHES, MAXALIGN, NAMEDATALEN, NamedLWLockTrancheRequestArray, NamedLWLockTrancheRequests, and ShmemAlloc().

Referenced by CreateOrAttachShmemStructs().

◆ GetLWLockIdentifier()

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

Definition at line 774 of file lwlock.c.

775{
776 Assert(classId == PG_WAIT_LWLOCK);
777 /* The event IDs are just tranche numbers. */
779}
#define Assert(condition)
Definition c.h:945
static const char * GetLWTrancheName(uint16 trancheId)
Definition lwlock.c:738
#define PG_WAIT_LWLOCK

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

Referenced by pgstat_get_wait_event().

◆ GetNamedLWLockTranche()

LWLockPadded * GetNamedLWLockTranche ( const char tranche_name)
extern

Definition at line 567 of file lwlock.c.

568{
569 int lock_pos;
570 int i;
571
572 /*
573 * Obtain the position of base address of LWLock belonging to requested
574 * tranche_name in MainLWLockArray. LWLocks for named tranches are placed
575 * in MainLWLockArray after fixed locks.
576 */
578 for (i = 0; i < NamedLWLockTrancheRequests; i++)
579 {
580 if (strcmp(NamedLWLockTrancheRequestArray[i].tranche_name,
581 tranche_name) == 0)
582 return &MainLWLockArray[lock_pos];
583
585 }
586
587 elog(ERROR, "requested tranche is not registered");
588
589 /* just to keep compiler quiet */
590 return NULL;
591}
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define NUM_FIXED_LWLOCKS
Definition lwlock.h:107

References elog, ERROR, fb(), i, MainLWLockArray, NamedLWLockTrancheRequestArray, NamedLWLockTrancheRequests, NUM_FIXED_LWLOCKS, and NamedLWLockTrancheRequest::num_lwlocks.

Referenced by pgss_shmem_startup(), and test_lwlock_tranche_lookup().

◆ InitLWLockAccess()

void InitLWLockAccess ( void  )
extern

Definition at line 551 of file lwlock.c.

552{
553#ifdef LWLOCK_STATS
555#endif
556}

References fb().

Referenced by InitAuxiliaryProcess(), and InitProcess().

◆ LWLockAcquire()

bool LWLockAcquire ( LWLock lock,
LWLockMode  mode 
)
extern

Definition at line 1177 of file lwlock.c.

1178{
1179 PGPROC *proc = MyProc;
1180 bool result = true;
1181 int extraWaits = 0;
1182#ifdef LWLOCK_STATS
1184
1186#endif
1187
1189
1190 PRINT_LWDEBUG("LWLockAcquire", lock, mode);
1191
1192#ifdef LWLOCK_STATS
1193 /* Count lock acquisition attempts */
1194 if (mode == LW_EXCLUSIVE)
1195 lwstats->ex_acquire_count++;
1196 else
1197 lwstats->sh_acquire_count++;
1198#endif /* LWLOCK_STATS */
1199
1200 /*
1201 * We can't wait if we haven't got a PGPROC. This should only occur
1202 * during bootstrap or shared memory initialization. Put an Assert here
1203 * to catch unsafe coding practices.
1204 */
1205 Assert(!(proc == NULL && IsUnderPostmaster));
1206
1207 /* Ensure we will have room to remember the lock */
1209 elog(ERROR, "too many LWLocks taken");
1210
1211 /*
1212 * Lock out cancel/die interrupts until we exit the code section protected
1213 * by the LWLock. This ensures that interrupts will not interfere with
1214 * manipulations of data structures in shared memory.
1215 */
1217
1218 /*
1219 * Loop here to try to acquire lock after each time we are signaled by
1220 * LWLockRelease.
1221 *
1222 * NOTE: it might seem better to have LWLockRelease actually grant us the
1223 * lock, rather than retrying and possibly having to go back to sleep. But
1224 * in practice that is no good because it means a process swap for every
1225 * lock acquisition when two or more processes are contending for the same
1226 * lock. Since LWLocks are normally used to protect not-very-long
1227 * sections of computation, a process needs to be able to acquire and
1228 * release the same lock many times during a single CPU time slice, even
1229 * in the presence of contention. The efficiency of being able to do that
1230 * outweighs the inefficiency of sometimes wasting a process dispatch
1231 * cycle because the lock is not free when a released waiter finally gets
1232 * to run. See pgsql-hackers archives for 29-Dec-01.
1233 */
1234 for (;;)
1235 {
1236 bool mustwait;
1237
1238 /*
1239 * Try to grab the lock the first time, we're not in the waitqueue
1240 * yet/anymore.
1241 */
1243
1244 if (!mustwait)
1245 {
1246 LOG_LWDEBUG("LWLockAcquire", lock, "immediately acquired lock");
1247 break; /* got the lock */
1248 }
1249
1250 /*
1251 * Ok, at this point we couldn't grab the lock on the first try. We
1252 * cannot simply queue ourselves to the end of the list and wait to be
1253 * woken up because by now the lock could long have been released.
1254 * Instead add us to the queue and try to grab the lock again. If we
1255 * succeed we need to revert the queuing and be happy, otherwise we
1256 * recheck the lock. If we still couldn't grab it, we know that the
1257 * other locker will see our queue entries when releasing since they
1258 * existed before we checked for the lock.
1259 */
1260
1261 /* add to the queue */
1262 LWLockQueueSelf(lock, mode);
1263
1264 /* we're now guaranteed to be woken up if necessary */
1266
1267 /* ok, grabbed the lock the second time round, need to undo queueing */
1268 if (!mustwait)
1269 {
1270 LOG_LWDEBUG("LWLockAcquire", lock, "acquired, undoing queue");
1271
1272 LWLockDequeueSelf(lock);
1273 break;
1274 }
1275
1276 /*
1277 * Wait until awakened.
1278 *
1279 * It is possible that we get awakened for a reason other than being
1280 * signaled by LWLockRelease. If so, loop back and wait again. Once
1281 * we've gotten the LWLock, re-increment the sema by the number of
1282 * additional signals received.
1283 */
1284 LOG_LWDEBUG("LWLockAcquire", lock, "waiting");
1285
1286#ifdef LWLOCK_STATS
1287 lwstats->block_count++;
1288#endif
1289
1293
1294 for (;;)
1295 {
1296 PGSemaphoreLock(proc->sem);
1297 if (proc->lwWaiting == LW_WS_NOT_WAITING)
1298 break;
1299 extraWaits++;
1300 }
1301
1302 /* Retrying, allow LWLockRelease to release waiters again. */
1304
1305#ifdef LOCK_DEBUG
1306 {
1307 /* not waiting anymore */
1309
1311 }
1312#endif
1313
1317
1318 LOG_LWDEBUG("LWLockAcquire", lock, "awakened");
1319
1320 /* Now loop back and try to acquire lock again. */
1321 result = false;
1322 }
1323
1326
1327 /* Add lock to list of locks held by this backend */
1330
1331 /*
1332 * Fix the process wait semaphore's count for any absorbed wakeups.
1333 */
1334 while (extraWaits-- > 0)
1335 PGSemaphoreUnlock(proc->sem);
1336
1337 return result;
1338}
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:243
static LWLockHandle held_lwlocks[MAX_SIMUL_LWLOCKS]
Definition lwlock.c:179
static bool LWLockAttemptLock(LWLock *lock, LWLockMode mode)
Definition lwlock.c:791
static void LWLockReportWaitEnd(void)
Definition lwlock.c:729
#define MAX_SIMUL_LWLOCKS
Definition lwlock.c:169
#define T_NAME(lock)
Definition lwlock.c:212
static int num_held_lwlocks
Definition lwlock.c:178
#define LOG_LWDEBUG(a, b, c)
Definition lwlock.c:277
static void LWLockQueueSelf(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1045
#define PRINT_LWDEBUG(a, b, c)
Definition lwlock.c:276
static void LWLockReportWaitStart(LWLock *lock)
Definition lwlock.c:720
#define LW_FLAG_WAKE_IN_PROGRESS
Definition lwlock.c:96
static void LWLockDequeueSelf(LWLock *lock)
Definition lwlock.c:1088
#define HOLD_INTERRUPTS()
Definition miscadmin.h:134
void PGSemaphoreUnlock(PGSemaphore sema)
Definition posix_sema.c:335
void PGSemaphoreLock(PGSemaphore sema)
Definition posix_sema.c:315
#define MAX_BACKENDS
Definition procnumber.h:39
PGPROC * MyProc
Definition proc.c:68
LWLockMode mode
Definition lwlock.c:175
LWLock * lock
Definition lwlock.c:174
pg_atomic_uint32 state
Definition lwlock.h:44
Definition proc.h:176
PGSemaphore sem
Definition proc.h:255
uint8 lwWaiting
Definition proc.h:280

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, 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(), 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(), 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(), injection_shmem_startup(), InjectionPointAttach(), InjectionPointDetach(), InjectionPointList(), InstallXLogFileSegment(), InvalidateBuffer(), InvalidateObsoleteReplicationSlots(), InvalidatePossiblyObsoleteSlot(), InvalidateVictimBuffer(), IoWorkerMain(), IsInstallXLogFileSegmentActive(), IsLogicalDecodingEnabled(), IsXLogLogicalInfoEnabled(), KnownAssignedXidsCompress(), KnownAssignedXidsReset(), 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_get_replication_slots(), pg_get_shmem_allocations(), pg_get_shmem_allocations_numa(), pg_notification_queue_usage(), pg_show_replication_origin_status(), pg_stat_get_subscription(), pg_stat_statements_internal(), pg_xact_status(), pgaio_worker_die(), pgaio_worker_register(), pgss_shmem_startup(), 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_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(), PredicateLockTwoPhaseFinish(), PrefetchSharedBuffer(), PrescanPreparedTransactions(), ProcArrayAdd(), ProcArrayApplyRecoveryInfo(), ProcArrayApplyXidAssignment(), ProcArrayClearTransaction(), ProcArrayEndTransaction(), ProcArrayGetReplicationSlotXmin(), ProcArrayGroupClearXid(), ProcArrayInstallImportedXmin(), ProcArrayInstallRestoredXmin(), ProcArrayRemove(), ProcArraySetReplicationSlotXmin(), ProcessSequencesForSync(), 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(), SerialInit(), SerialSetActiveSerXmin(), set_indexsafe_procflags(), set_val_in_shmem(), SetCommitTsLimit(), 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(), 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_aio_shmem_startup(), 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(), 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(), 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 1405 of file lwlock.c.

1406{
1407 PGPROC *proc = MyProc;
1408 bool mustwait;
1409 int extraWaits = 0;
1410#ifdef LWLOCK_STATS
1412
1414#endif
1415
1417
1418 PRINT_LWDEBUG("LWLockAcquireOrWait", lock, mode);
1419
1420 /* Ensure we will have room to remember the lock */
1422 elog(ERROR, "too many LWLocks taken");
1423
1424 /*
1425 * Lock out cancel/die interrupts until we exit the code section protected
1426 * by the LWLock. This ensures that interrupts will not interfere with
1427 * manipulations of data structures in shared memory.
1428 */
1430
1431 /*
1432 * NB: We're using nearly the same twice-in-a-row lock acquisition
1433 * protocol as LWLockAcquire(). Check its comments for details.
1434 */
1436
1437 if (mustwait)
1438 {
1440
1442
1443 if (mustwait)
1444 {
1445 /*
1446 * Wait until awakened. Like in LWLockAcquire, be prepared for
1447 * bogus wakeups.
1448 */
1449 LOG_LWDEBUG("LWLockAcquireOrWait", lock, "waiting");
1450
1451#ifdef LWLOCK_STATS
1452 lwstats->block_count++;
1453#endif
1454
1458
1459 for (;;)
1460 {
1461 PGSemaphoreLock(proc->sem);
1462 if (proc->lwWaiting == LW_WS_NOT_WAITING)
1463 break;
1464 extraWaits++;
1465 }
1466
1467#ifdef LOCK_DEBUG
1468 {
1469 /* not waiting anymore */
1471
1473 }
1474#endif
1478
1479 LOG_LWDEBUG("LWLockAcquireOrWait", lock, "awakened");
1480 }
1481 else
1482 {
1483 LOG_LWDEBUG("LWLockAcquireOrWait", lock, "acquired, undoing queue");
1484
1485 /*
1486 * Got lock in the second attempt, undo queueing. We need to treat
1487 * this as having successfully acquired the lock, otherwise we'd
1488 * not necessarily wake up people we've prevented from acquiring
1489 * the lock.
1490 */
1491 LWLockDequeueSelf(lock);
1492 }
1493 }
1494
1495 /*
1496 * Fix the process wait semaphore's count for any absorbed wakeups.
1497 */
1498 while (extraWaits-- > 0)
1499 PGSemaphoreUnlock(proc->sem);
1500
1501 if (mustwait)
1502 {
1503 /* Failed to get lock, so release interrupt holdoff */
1505 LOG_LWDEBUG("LWLockAcquireOrWait", lock, "failed");
1508 }
1509 else
1510 {
1511 LOG_LWDEBUG("LWLockAcquireOrWait", lock, "succeeded");
1512 /* Add lock to list of locks held by this backend */
1517 }
1518
1519 return !mustwait;
1520}
#define RESUME_INTERRUPTS()
Definition miscadmin.h:136

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 1930 of file lwlock.c.

1931{
1932 char *held_lock_addr;
1933 char *begin;
1934 char *end;
1935 int i;
1936
1937 begin = (char *) lock;
1938 end = begin + nlocks * stride;
1939 for (i = 0; i < num_held_lwlocks; i++)
1940 {
1941 held_lock_addr = (char *) held_lwlocks[i].lock;
1942 if (held_lock_addr >= begin &&
1943 held_lock_addr < end &&
1944 (held_lock_addr - begin) % stride == 0)
1945 return true;
1946 }
1947 return false;
1948}

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

◆ LWLockConditionalAcquire()

bool LWLockConditionalAcquire ( LWLock lock,
LWLockMode  mode 
)
extern

Definition at line 1348 of file lwlock.c.

1349{
1350 bool mustwait;
1351
1353
1354 PRINT_LWDEBUG("LWLockConditionalAcquire", lock, mode);
1355
1356 /* Ensure we will have room to remember the lock */
1358 elog(ERROR, "too many LWLocks taken");
1359
1360 /*
1361 * Lock out cancel/die interrupts until we exit the code section protected
1362 * by the LWLock. This ensures that interrupts will not interfere with
1363 * manipulations of data structures in shared memory.
1364 */
1366
1367 /* Check for the lock */
1369
1370 if (mustwait)
1371 {
1372 /* Failed to get lock, so release interrupt holdoff */
1374
1375 LOG_LWDEBUG("LWLockConditionalAcquire", lock, "failed");
1378 }
1379 else
1380 {
1381 /* Add lock to list of locks held by this backend */
1386 }
1387 return !mustwait;
1388}

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_internal(), pgstat_io_flush_cb(), pgstat_lock_entry(), pgstat_lock_entry_shared(), pgstat_slru_flush_cb(), pgstat_wal_flush_cb(), ProcArrayEndTransaction(), SimpleLruWaitIO(), ss_report_location(), TransactionIdSetPageStatus(), and XLogNeedsFlush().

◆ LWLockHeldByMe()

◆ LWLockHeldByMeInMode()

◆ LWLockInitialize()

◆ LWLockNewTrancheId()

int LWLockNewTrancheId ( const char name)
extern

Definition at line 597 of file lwlock.c.

598{
599 int result;
600
601 if (!name)
604 errmsg("tranche name cannot be NULL")));
605
606 if (strlen(name) >= NAMEDATALEN)
609 errmsg("tranche name too long"),
610 errdetail("LWLock tranche names must be no longer than %d bytes.",
611 NAMEDATALEN - 1)));
612
613 /*
614 * We use the ShmemLock spinlock to protect LWLockCounter and
615 * LWLockTrancheNames.
616 */
618
620 {
623 (errmsg("maximum number of tranches already registered"),
624 errdetail("No more than %d tranches may be registered.",
626 }
627
628 result = (*LWLockCounter)++;
631
633
634 return result;
635}
int errcode(int sqlerrcode)
Definition elog.c:874
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define ereport(elevel,...)
Definition elog.h:150
static int LocalLWLockCounter
Definition lwlock.c:203
static char * errmsg
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition strlcpy.c:45
slock_t * ShmemLock
Definition shmem.c:108
static void SpinLockRelease(volatile slock_t *lock)
Definition spin.h:62
static void SpinLockAcquire(volatile slock_t *lock)
Definition spin.h:56

References ereport, errcode(), errdetail(), errmsg, ERROR, fb(), LocalLWLockCounter, LWLockCounter, LWLockTrancheNames, LWTRANCHE_FIRST_USER_DEFINED, MAX_NAMED_TRANCHES, name, NAMEDATALEN, ShmemLock, SpinLockAcquire(), SpinLockRelease(), and strlcpy().

Referenced by apw_init_state(), GetNamedDSA(), GetNamedDSHash(), init_tdr_dsm(), init_tranche(), InitializeLWLocks(), test_basic(), test_create(), test_empty(), test_lwlock_tranche_creation(), test_lwlock_tranches(), test_random(), and test_slru_shmem_startup().

◆ LWLockRelease()

void LWLockRelease ( LWLock lock)
extern

Definition at line 1794 of file lwlock.c.

1795{
1798 bool check_waiters;
1799 int i;
1800
1801 /*
1802 * Remove lock from list of locks held. Usually, but not always, it will
1803 * be the latest-acquired lock; so search array backwards.
1804 */
1805 for (i = num_held_lwlocks; --i >= 0;)
1806 if (lock == held_lwlocks[i].lock)
1807 break;
1808
1809 if (i < 0)
1810 elog(ERROR, "lock %s is not held", T_NAME(lock));
1811
1813
1815 for (; i < num_held_lwlocks; i++)
1816 held_lwlocks[i] = held_lwlocks[i + 1];
1817
1818 PRINT_LWDEBUG("LWLockRelease", lock, mode);
1819
1820 /*
1821 * Release my hold on lock, after that it can immediately be acquired by
1822 * others, even if we still have to wakeup other waiters.
1823 */
1824 if (mode == LW_EXCLUSIVE)
1826 else
1828
1829 /* nobody else can have that kind of lock */
1831
1834
1835 /*
1836 * Check if we're still waiting for backends to get scheduled, if so,
1837 * don't wake them up again.
1838 */
1839 if ((oldstate & LW_FLAG_HAS_WAITERS) &&
1841 (oldstate & LW_LOCK_MASK) == 0)
1842 check_waiters = true;
1843 else
1844 check_waiters = false;
1845
1846 /*
1847 * As waking up waiters requires the spinlock to be acquired, only do so
1848 * if necessary.
1849 */
1850 if (check_waiters)
1851 {
1852 /* XXX: remove before commit? */
1853 LOG_LWDEBUG("LWLockRelease", lock, "releasing waiters");
1854 LWLockWakeup(lock);
1855 }
1856
1857 /*
1858 * Now okay to allow cancel/die interrupts.
1859 */
1861}
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:102
static void LWLockWakeup(LWLock *lock)
Definition lwlock.c:931
#define LW_VAL_SHARED
Definition lwlock.c:103
#define LW_LOCK_MASK
Definition lwlock.c:107
#define LW_FLAG_HAS_WAITERS
Definition lwlock.c:95

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(), 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(), 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(), injection_shmem_startup(), InjectionPointAttach(), InjectionPointDetach(), InjectionPointList(), InstallXLogFileSegment(), InvalidateBuffer(), InvalidateObsoleteReplicationSlots(), InvalidatePossiblyObsoleteSlot(), InvalidateVictimBuffer(), IoWorkerMain(), IsInstallXLogFileSegmentActive(), IsLogicalDecodingEnabled(), IsXLogLogicalInfoEnabled(), KnownAssignedXidsCompress(), KnownAssignedXidsReset(), 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_get_replication_slots(), pg_get_shmem_allocations(), pg_get_shmem_allocations_numa(), pg_notification_queue_usage(), pg_show_replication_origin_status(), pg_stat_get_subscription(), pg_stat_statements_internal(), pg_xact_status(), pgaio_worker_die(), pgaio_worker_register(), pgaio_worker_submit_internal(), pgss_shmem_startup(), 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_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(), PredicateLockTwoPhaseFinish(), PrefetchSharedBuffer(), PrescanPreparedTransactions(), ProcArrayAdd(), ProcArrayApplyRecoveryInfo(), ProcArrayApplyXidAssignment(), ProcArrayClearTransaction(), ProcArrayEndTransaction(), ProcArrayGetReplicationSlotXmin(), ProcArrayGroupClearXid(), ProcArrayInstallImportedXmin(), ProcArrayInstallRestoredXmin(), ProcArrayRemove(), ProcArraySetReplicationSlotXmin(), ProcessSequencesForSync(), 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(), SerialInit(), SerialSetActiveSerXmin(), set_indexsafe_procflags(), set_val_in_shmem(), SetCommitTsLimit(), 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(), 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_aio_shmem_startup(), 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(), 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(), 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 1867 of file lwlock.c.

1868{
1869 /*
1870 * Note that pg_atomic_exchange_u64 is a full barrier, so we're guaranteed
1871 * that the variable is updated before releasing the lock.
1872 */
1874
1875 LWLockRelease(lock);
1876}
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().

◆ LWLockShmemSize()

Size LWLockShmemSize ( void  )
extern

Definition at line 398 of file lwlock.c.

399{
400 Size size;
401 int numLocks = NUM_FIXED_LWLOCKS;
402
403 /*
404 * If re-initializing shared memory, the request array will no longer be
405 * accessible, so switch to the copy in postmaster's local memory. We'll
406 * copy it back into shared memory later when CreateLWLocks() is called
407 * again.
408 */
411
412 /* Calculate total number of locks needed in the main array. */
413 numLocks += NumLWLocksForNamedTranches();
414
415 /* Space for dynamic allocation counter. */
416 size = MAXALIGN(sizeof(int));
417
418 /* Space for named tranches. */
419 size = add_size(size, mul_size(MAX_NAMED_TRANCHES, sizeof(char *)));
421
422 /*
423 * Make space for named tranche requests. This is done for the benefit of
424 * EXEC_BACKEND builds, which otherwise wouldn't be able to call
425 * GetNamedLWLockTranche() outside postmaster.
426 */
429
430 /* Space for the LWLock array, plus room for cache line alignment. */
431 size = add_size(size, LWLOCK_PADDED_SIZE);
432 size = add_size(size, mul_size(numLocks, sizeof(LWLockPadded)));
433
434 return size;
435}
static int NumLWLocksForNamedTranches(void)
Definition lwlock.c:383
Size add_size(Size s1, Size s2)
Definition shmem.c:485
Size mul_size(Size s1, Size s2)
Definition shmem.c:500

References add_size(), LocalNamedLWLockTrancheRequestArray, LWLOCK_PADDED_SIZE, MAX_NAMED_TRANCHES, MAXALIGN, mul_size(), NAMEDATALEN, NamedLWLockTrancheRequestArray, NamedLWLockTrancheRequests, NUM_FIXED_LWLOCKS, and NumLWLocksForNamedTranches().

Referenced by CalculateShmemSize(), and CreateLWLocks().

◆ LWLockUpdateVar()

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

Definition at line 1729 of file lwlock.c.

1730{
1733
1734 PRINT_LWDEBUG("LWLockUpdateVar", lock, LW_EXCLUSIVE);
1735
1736 /*
1737 * Note that pg_atomic_exchange_u64 is a full barrier, so we're guaranteed
1738 * that the variable is updated before waking up waiters.
1739 */
1741
1743
1744 LWLockWaitListLock(lock);
1745
1747
1748 /*
1749 * See if there are any LW_WAIT_UNTIL_FREE waiters that need to be woken
1750 * up. They are always in the front of the queue.
1751 */
1752 proclist_foreach_modify(iter, &lock->waiters, lwWaitLink)
1753 {
1754 PGPROC *waiter = GetPGProcByNumber(iter.cur);
1755
1756 if (waiter->lwWaitMode != LW_WAIT_UNTIL_FREE)
1757 break;
1758
1759 proclist_delete(&lock->waiters, iter.cur, lwWaitLink);
1760 proclist_push_tail(&wakeup, iter.cur, lwWaitLink);
1761
1762 /* see LWLockWakeup() */
1763 Assert(waiter->lwWaiting == LW_WS_WAITING);
1765 }
1766
1767 /* We are done updating shared state of the lock itself. */
1769
1770 /*
1771 * Awaken any waiters I removed from the queue.
1772 */
1773 proclist_foreach_modify(iter, &wakeup, lwWaitLink)
1774 {
1775 PGPROC *waiter = GetPGProcByNumber(iter.cur);
1776
1777 proclist_delete(&wakeup, iter.cur, lwWaitLink);
1778 /* check comment in LWLockWakeup() about this barrier */
1780 waiter->lwWaiting = LW_WS_NOT_WAITING;
1781 PGSemaphoreUnlock(waiter->sem);
1782 }
1783}
#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:862
static void LWLockWaitListUnlock(LWLock *lock)
Definition lwlock.c:918
#define GetPGProcByNumber(n)
Definition proc.h:501
#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:281
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 1593 of file lwlock.c.

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

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, 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 650 of file lwlock.c.

651{
654
656 elog(FATAL, "cannot request additional LWLocks outside shmem_request_hook");
657
658 if (!tranche_name)
661 errmsg("tranche name cannot be NULL")));
662
663 if (strlen(tranche_name) >= NAMEDATALEN)
666 errmsg("tranche name too long"),
667 errdetail("LWLock tranche names must be no longer than %d bytes.",
668 NAMEDATALEN - 1)));
669
671 {
676 * sizeof(NamedLWLockTrancheRequest));
677 }
678
680 {
682
685 i * sizeof(NamedLWLockTrancheRequest));
687 }
688
690 strlcpy(request->tranche_name, tranche_name, NAMEDATALEN);
691 request->num_lwlocks = num_lwlocks;
693}
#define FATAL
Definition elog.h:41
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition mcxt.c:1232
void * repalloc(void *pointer, Size size)
Definition mcxt.c:1632
MemoryContext TopMemoryContext
Definition mcxt.c:166
bool process_shmem_requests_in_progress
Definition miscinit.c:1791
static uint32 pg_nextpower2_32(uint32 num)

References elog, ereport, errcode(), errdetail(), errmsg, ERROR, FATAL, fb(), i, MemoryContextAlloc(), NAMEDATALEN, NamedLWLockTrancheRequestArray, NamedLWLockTrancheRequests, pg_nextpower2_32(), process_shmem_requests_in_progress, repalloc(), strlcpy(), and TopMemoryContext.

Referenced by pgss_shmem_request(), and test_lwlock_tranches_shmem_request().

◆ StaticAssertDecl()

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

Variable Documentation

◆ LWLockCounter

PGDLLIMPORT int* LWLockCounter
extern

Definition at line 200 of file lwlock.c.

Referenced by CreateLWLocks(), GetLWTrancheName(), and LWLockNewTrancheId().

◆ LWLockTrancheNames

PGDLLIMPORT char** LWLockTrancheNames
extern

Definition at line 155 of file lwlock.c.

Referenced by CreateLWLocks(), GetLWTrancheName(), and LWLockNewTrancheId().

◆ MainLWLockArray

◆ NamedLWLockTrancheRequestArray

◆ NamedLWLockTrancheRequests