PostgreSQL Source Code git master
Data Structures | Macros | Typedefs | Enumerations | Functions | Variables
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  NUM_BUFFER_PARTITIONS   128
 
#define  LOG2_NUM_LOCK_PARTITIONS   4
 
 
 
 
#define  BUFFER_MAPPING_LWLOCK_OFFSET   NUM_INDIVIDUAL_LWLOCKS
 
 
 
 
#define  PG_LWLOCK(id, name)
 
#define  PG_LWLOCKTRANCHE(id, name)   LWTRANCHE_##id,
 

Typedefs

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

Enumerations

 
 
enum   BuiltinTrancheIds { LWTRANCHE_INVALID = NUM_INDIVIDUAL_LWLOCKS - 1 , LWTRANCHE_FIRST_USER_DEFINED }
 

Functions

  StaticAssertDecl (sizeof(LWLock)<=LWLOCK_PADDED_SIZE, "Miscalculated LWLock padding")
 
 
 
 
void  LWLockRelease (LWLock *lock)
 
 
void  LWLockReleaseAll (void)
 
void  LWLockDisown (LWLock *lock)
 
 
void  ForEachLWLockHeldByMe (void(*callback)(LWLock *, LWLockMode, void *), void *context)
 
bool  LWLockHeldByMe (LWLock *lock)
 
bool  LWLockAnyHeldByMe (LWLock *lock, int nlocks, size_t stride)
 
 
bool  LWLockWaitForVar (LWLock *lock, pg_atomic_uint64 *valptr, uint64 oldval, uint64 *newval)
 
 
 
void  CreateLWLocks (void)
 
void  InitLWLockAccess (void)
 
const char *  GetLWLockIdentifier (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

 
 
 
 
 

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.

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 180 of file lwlock.h.

PG_LWLOCKTRANCHE

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

Definition at line 181 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

typedef struct LWLock LWLock

LWLockId

typedef LWLock* LWLockId

Definition at line 194 of file lwlock.h.

LWLockMode

typedef enum LWLockMode LWLockMode

LWLockPadded

typedef union LWLockPadded LWLockPadded

LWLockWaitState

NamedLWLockTrancheRequest

Definition at line 77 of file lwlock.h.

Enumeration Type Documentation

BuiltinTrancheIds

Enumerator
LWTRANCHE_INVALID 
LWTRANCHE_FIRST_USER_DEFINED 

Definition at line 172 of file lwlock.h.

173{
174 /*
175 * LWTRANCHE_INVALID is an unused value that only exists to initialize the
176 * rest of the tranches to appropriate values.
177 */
178 LWTRANCHE_INVALID = NUM_INDIVIDUAL_LWLOCKS - 1,
179
180#define PG_LWLOCK(id, name)
181#define PG_LWLOCKTRANCHE(id, name) LWTRANCHE_##id,
182#include "storage/lwlocklist.h"
183#undef PG_LWLOCK
184#undef PG_LWLOCKTRANCHE
185
BuiltinTrancheIds
Definition: lwlock.h:173
@ LWTRANCHE_FIRST_USER_DEFINED
Definition: lwlock.h:186
@ LWTRANCHE_INVALID
Definition: lwlock.h:178

LWLockMode

enum 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;
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

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  )

Definition at line 441 of file lwlock.c.

442{
444 {
445 Size spaceLocks = LWLockShmemSize();
446 char *ptr;
447
448 /* Allocate space */
449 ptr = (char *) ShmemAlloc(spaceLocks);
450
451 /* Initialize the dynamic-allocation counter for tranches */
452 LWLockCounter = (int *) ptr;
454 ptr += MAXALIGN(sizeof(int));
455
456 /* Initialize tranche names */
457 LWLockTrancheNames = (char **) ptr;
458 ptr += MAX_NAMED_TRANCHES * sizeof(char *);
459 for (int i = 0; i < MAX_NAMED_TRANCHES; i++)
460 {
461 LWLockTrancheNames[i] = ptr;
462 ptr += NAMEDATALEN;
463 }
464
465 /*
466 * Move named tranche requests to shared memory. This is done for the
467 * benefit of EXEC_BACKEND builds, which otherwise wouldn't be able to
468 * call GetNamedLWLockTranche() outside postmaster.
469 */
471 {
472 /*
473 * Save the pointer to the request array in postmaster's local
474 * memory. We'll need it if we ever need to re-initialize shared
475 * memory after a crash.
476 */
478
483 }
484
485 /* Ensure desired alignment of LWLock array */
486 ptr += LWLOCK_PADDED_SIZE - ((uintptr_t) ptr) % LWLOCK_PADDED_SIZE;
488
489 /* Initialize all LWLocks */
491 }
492}
#define MAXALIGN(LEN)
Definition: c.h:810
size_t Size
Definition: c.h:610
bool IsUnderPostmaster
Definition: globals.c:120
i
int i
Definition: isn.c:77
char ** LWLockTrancheNames
Definition: lwlock.c:154
int NamedLWLockTrancheRequests
Definition: lwlock.c:192
struct NamedLWLockTrancheRequest NamedLWLockTrancheRequest
static NamedLWLockTrancheRequest * LocalNamedLWLockTrancheRequestArray
Definition: lwlock.c:196
static void InitializeLWLocks(void)
Definition: lwlock.c:498
NamedLWLockTrancheRequest * NamedLWLockTrancheRequestArray
Definition: lwlock.c:193
LWLockPadded * MainLWLockArray
Definition: lwlock.c:161
int * LWLockCounter
Definition: lwlock.c:199
Size LWLockShmemSize(void)
Definition: lwlock.c:397
#define MAX_NAMED_TRANCHES
Definition: lwlock.c:204
#define LWLOCK_PADDED_SIZE
Definition: lwlock.h:62
#define NAMEDATALEN
void * ShmemAlloc(Size size)
Definition: shmem.c:152

References 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().

ForEachLWLockHeldByMe()

void ForEachLWLockHeldByMe ( void(*)(LWLock *, LWLockMode, void *)  callback,
void *  context 
)

Definition at line 1962 of file lwlock.c.

1964{
1965 int i;
1966
1967 for (i = 0; i < num_held_lwlocks; i++)
1968 callback(held_lwlocks[i].lock, held_lwlocks[i].mode, context);
1969}
static LWLockHandle held_lwlocks[MAX_SIMUL_LWLOCKS]
Definition: lwlock.c:178
static int num_held_lwlocks
Definition: lwlock.c:177
static PgChecksumMode mode
Definition: pg_checksums.c:55
static void callback(struct sockaddr *addr, struct sockaddr *mask, void *unused)
Definition: test_ifaddrs.c:46

References callback(), held_lwlocks, i, mode, and num_held_lwlocks.

GetLWLockIdentifier()

const char * GetLWLockIdentifier ( uint32  classId,
uint16  eventId 
)

Definition at line 773 of file lwlock.c.

774{
775 Assert(classId == PG_WAIT_LWLOCK);
776 /* The event IDs are just tranche numbers. */
777 return GetLWTrancheName(eventId);
778}
Assert(PointerIsAligned(start, uint64))
static const char * GetLWTrancheName(uint16 trancheId)
Definition: lwlock.c:737
#define PG_WAIT_LWLOCK
Definition: wait_classes.h:18

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

Referenced by pgstat_get_wait_event().

GetNamedLWLockTranche()

LWLockPadded * GetNamedLWLockTranche ( const char *  tranche_name )

Definition at line 566 of file lwlock.c.

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

References elog, ERROR, 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  )

Definition at line 550 of file lwlock.c.

551{
552#ifdef LWLOCK_STATS
553 init_lwlock_stats();
554#endif
555}

Referenced by InitAuxiliaryProcess(), and InitProcess().

LWLockAcquire()

bool LWLockAcquire ( LWLocklock,
LWLockMode  mode 
)

Definition at line 1174 of file lwlock.c.

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

References Assert(), elog, ERROR, held_lwlocks, HOLD_INTERRUPTS, IsUnderPostmaster, LWLockHandle::lock, LOG_LWDEBUG, LW_EXCLUSIVE, LW_FLAG_RELEASE_OK, 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_or_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(), AbsorbSyncRequests(), ActivateCommitTs(), AdvanceNextFullTransactionIdPastXid(), AdvanceOldestClogXid(), AdvanceOldestCommitTsXid(), AdvanceXLInsertBuffer(), alloc_object(), AlterSystemSetConfigFile(), ApplyLauncherMain(), apw_detach_shmem(), apw_dump_now(), apw_load_buffers(), asyncQueueAddEntries(), asyncQueueAdvanceTail(), asyncQueueReadAllNotifications(), asyncQueueUnregister(), AtAbort_Twophase(), AtEOXact_LogicalRepWorkers(), AtPrepare_PredicateLocks(), attach_internal(), autoprewarm_main(), autoprewarm_start_worker(), AutoVacLauncherMain(), AutoVacuumRequestWork(), AutoVacWorkerMain(), BackendPidGetProc(), BackendXidGetPid(), BecomeLockGroupLeader(), BecomeLockGroupMember(), btparallelrescan(), BufferAlloc(), CancelDBBackends(), check_for_freed_segments(), CheckDeadLock(), CheckForSerializableConflictOut(), 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(), destroy_superblock(), 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_pin(), dsa_release_in_place(), dsa_set_size_limit(), dsa_trim(), dsa_unpin(), dshash_delete_key(), dshash_dump(), dshash_find(), dshash_find_or_insert(), dshash_seq_next(), dsm_attach(), dsm_create(), dsm_detach(), dsm_pin_segment(), dsm_unpin_segment(), ensure_active_superblock(), entry_reset(), EvictUnpinnedBufferInternal(), Exec_ListenPreCommit(), ExecParallelHashMergeCounters(), ExecParallelHashPopChunkQueue(), ExecParallelHashTupleAlloc(), ExecParallelHashTuplePrealloc(), ExpireAllKnownAssignedTransactionIds(), ExpireOldKnownAssignedTransactionIds(), ExpireTreeKnownAssignedTransactionIds(), ExtendBufferedRelShared(), ExtendCLOG(), ExtendCommitTs(), ExtendMultiXactMember(), ExtendMultiXactOffset(), ExtendSUBTRANS(), FastPathGetRelationLockEntry(), FastPathTransferRelationLocks(), FindAndDropRelationBuffers(), FindDeletedTupleInLocalRel(), FinishPreparedTransaction(), FlushDatabaseBuffers(), FlushRelationBuffers(), FlushRelationsAllBuffers(), 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(), InitWalSender(), injection_shmem_startup(), injection_stats_fixed_reset_all_cb(), injection_stats_fixed_snapshot_cb(), InjectionPointAttach(), InjectionPointDetach(), InjectionPointList(), InstallXLogFileSegment(), InvalidateBuffer(), InvalidateObsoleteReplicationSlots(), InvalidatePossiblyObsoleteSlot(), InvalidateVictimBuffer(), IoWorkerMain(), IsInstallXLogFileSegmentActive(), KnownAssignedXidsCompress(), KnownAssignedXidsReset(), lock_twophase_recover(), LockAcquireExtended(), LockBuffer(), LockErrorCleanup(), LockGXact(), LockHasWaiters(), LockRefindAndRelease(), LockRelease(), LockReleaseAll(), LockWaiterCount(), logicalrep_launcher_attach_dshmem(), logicalrep_pa_worker_stop(), 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(), MaybeExtendOffsetSlru(), 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(), 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_lock_entry(), pgstat_lock_entry_shared(), pgstat_report_inj_fixed(), 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(), process_syncing_tables_for_apply(), ProcKill(), ProcNumberGetTransactionIds(), ProcSleep(), ReachedEndOfBackup(), read_relmap_file(), ReadMultiXactIdRange(), ReadNextFullTransactionId(), ReadNextMultiXactId(), ReadReplicationSlot(), RecordNewMultiXact(), RecoverPreparedTransactions(), RegisterDynamicBackgroundWorker(), RegisterPredicateLockingXid(), RelationCacheInitFilePreInvalidate(), RelationMapCopy(), RelationMapFinishBootstrap(), ReleaseOneSerializableXact(), ReleasePredicateLocks(), relmap_redo(), RemoveScratchTarget(), ReplicationOriginExitCleanup(), ReplicationSlotAcquire(), ReplicationSlotCleanup(), ReplicationSlotCreate(), ReplicationSlotDropPtr(), ReplicationSlotName(), ReplicationSlotRelease(), ReplicationSlotsComputeLogicalRestartLSN(), ReplicationSlotsComputeRequiredLSN(), ReplicationSlotsComputeRequiredXmin(), ReplicationSlotsCountDBSlots(), ReplicationSlotsDropDBSlots(), replorigin_advance(), replorigin_get_progress(), replorigin_session_advance(), replorigin_session_get_progress(), replorigin_session_reset(), replorigin_session_setup(), replorigin_state_clear(), resize(), RestoreScratchTarget(), restoreTwoPhaseData(), SaveSlotToPath(), SearchNamedReplicationSlot(), SerialAdd(), SerialGetMinConflictCommitSeqNo(), SerialInit(), SerialSetActiveSerXmin(), set_indexsafe_procflags(), set_val_in_shmem(), SetCommitTsLimit(), SetInstallXLogFileSegmentActive(), SetMultiXactIdLimit(), SetNextObjectId(), SetOffsetVacuumLimit(), SetTransactionIdLimit(), SetXidCommitTsInPage(), SharedInvalBackendInit(), ShmemInitStruct(), SICleanupQueue(), SIGetDataEntries(), SignalBackends(), SignalVirtualTransaction(), 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(), SyncOneBuffer(), SyncRepCancelWait(), SyncRepCleanupAtProcExit(), SyncRepReleaseWaiters(), SyncRepUpdateSyncStandbysDefined(), SyncRepWaitForLSN(), TablespaceCreateDbspace(), tbm_shared_iterate(), TerminateBackgroundWorker(), TerminateOtherDBBackends(), test_aio_shmem_startup(), 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(), UpdateMinRecoveryPoint(), vac_truncate_clog(), vacuum_rel(), VacuumUpdateCosts(), validate_sync_standby_slots(), VirtualXactLock(), VirtualXactLockTableCleanup(), VirtualXactLockTableInsert(), wait_for_relation_state_change(), wait_for_worker_state_change(), WaitEventCustomNew(), WaitForReplicationWorkerAttach(), WaitForWalSummarization(), WakeupWalSummarizer(), WALInsertLockAcquire(), WALInsertLockAcquireExclusive(), WalSummarizerMain(), WalSummarizerShutdown(), write_relcache_init_file(), xact_redo(), XidCacheRemoveRunningXids(), xlog_redo(), XLogBackgroundFlush(), XLogReportParameters(), XLogShutdownWalRcv(), and ZeroAndLockBuffer().

LWLockAcquireOrWait()

bool LWLockAcquireOrWait ( LWLocklock,
LWLockMode  mode 
)

Definition at line 1402 of file lwlock.c.

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

References Assert(), elog, ERROR, 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 ( LWLocklock,
int  nlocks,
size_t  stride 
)

Definition at line 1995 of file lwlock.c.

1996{
1997 char *held_lock_addr;
1998 char *begin;
1999 char *end;
2000 int i;
2001
2002 begin = (char *) lock;
2003 end = begin + nlocks * stride;
2004 for (i = 0; i < num_held_lwlocks; i++)
2005 {
2006 held_lock_addr = (char *) held_lwlocks[i].lock;
2007 if (held_lock_addr >= begin &&
2008 held_lock_addr < end &&
2009 (held_lock_addr - begin) % stride == 0)
2010 return true;
2011 }
2012 return false;
2013}

References held_lwlocks, i, and num_held_lwlocks.

LWLockConditionalAcquire()

bool LWLockConditionalAcquire ( LWLocklock,
LWLockMode  mode 
)

Definition at line 1345 of file lwlock.c.

1346{
1347 bool mustwait;
1348
1350
1351 PRINT_LWDEBUG("LWLockConditionalAcquire", lock, mode);
1352
1353 /* Ensure we will have room to remember the lock */
1355 elog(ERROR, "too many LWLocks taken");
1356
1357 /*
1358 * Lock out cancel/die interrupts until we exit the code section protected
1359 * by the LWLock. This ensures that interrupts will not interfere with
1360 * manipulations of data structures in shared memory.
1361 */
1363
1364 /* Check for the lock */
1365 mustwait = LWLockAttemptLock(lock, mode);
1366
1367 if (mustwait)
1368 {
1369 /* Failed to get lock, so release interrupt holdoff */
1371
1372 LOG_LWDEBUG("LWLockConditionalAcquire", lock, "failed");
1373 if (TRACE_POSTGRESQL_LWLOCK_CONDACQUIRE_FAIL_ENABLED())
1374 TRACE_POSTGRESQL_LWLOCK_CONDACQUIRE_FAIL(T_NAME(lock), mode);
1375 }
1376 else
1377 {
1378 /* Add lock to list of locks held by this backend */
1381 if (TRACE_POSTGRESQL_LWLOCK_CONDACQUIRE_ENABLED())
1382 TRACE_POSTGRESQL_LWLOCK_CONDACQUIRE(T_NAME(lock), mode);
1383 }
1384 return !mustwait;
1385}

References Assert(), elog, ERROR, 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 ConditionalLockBuffer(), GetVictimBuffer(), 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().

LWLockDisown()

void LWLockDisown ( LWLocklock )

Definition at line 1883 of file lwlock.c.

1884{
1886
1888}
static LWLockMode LWLockDisownInternal(LWLock *lock)
Definition: lwlock.c:1800

References LWLockDisownInternal(), and RESUME_INTERRUPTS.

Referenced by buffer_stage_common().

LWLockHeldByMe()

bool LWLockHeldByMe ( LWLocklock )

Definition at line 1977 of file lwlock.c.

1978{
1979 int i;
1980
1981 for (i = 0; i < num_held_lwlocks; i++)
1982 {
1983 if (held_lwlocks[i].lock == lock)
1984 return true;
1985 }
1986 return false;
1987}

References held_lwlocks, i, and num_held_lwlocks.

Referenced by alloc_object(), autovac_recalculate_workers_for_balance(), buffer_stage_common(), check_for_freed_segments_locked(), CompactCheckpointerRequestQueue(), delete_item(), DeleteLockTarget(), dshash_dump(), ensure_active_superblock(), FlushOneBuffer(), get_best_segment(), GetLockHoldersAndWaiters(), GetOldestSafeDecodingTransactionId(), GetSnapshotDataReuse(), init_span(), InvalidatePossiblyObsoleteSlot(), logicalrep_pa_worker_count(), logicalrep_sync_worker_count(), logicalrep_worker_find(), logicalrep_worker_wakeup_ptr(), logicalrep_workers_find(), MaintainLatestCompletedXid(), MaintainLatestCompletedXidRecovery(), make_new_segment(), MarkBufferDirtyHint(), OnConflict_CheckForSerializationFailure(), ProcArrayEndTransaction(), ProcArraySetReplicationSlotXmin(), ProcSleep(), ReleaseOneSerializableXact(), RemoveScratchTarget(), RemoveTargetIfNoLongerUsed(), resize(), RestoreScratchTarget(), SetNewSxactGlobalXmin(), SlruSelectLRUPage(), test_slru_page_readonly(), TransactionIdInRecentPast(), TwoPhaseGetGXact(), UnpinBufferNoOwner(), and VacuumUpdateCosts().

LWLockHeldByMeInMode()

bool LWLockHeldByMeInMode ( LWLocklock,
LWLockMode  mode 
)

Definition at line 2021 of file lwlock.c.

2022{
2023 int i;
2024
2025 for (i = 0; i < num_held_lwlocks; i++)
2026 {
2027 if (held_lwlocks[i].lock == lock && held_lwlocks[i].mode == mode)
2028 return true;
2029 }
2030 return false;
2031}

References held_lwlocks, i, mode, and num_held_lwlocks.

Referenced by BufferIsDirty(), BufferIsExclusiveLocked(), DeleteLockTarget(), dshash_delete_current(), dshash_delete_entry(), dshash_seq_next(), InvalidatePossiblyObsoleteSlot(), IsBufferCleanupOK(), JoinWaitQueue(), logicalrep_worker_cleanup(), logicalrep_worker_stop_internal(), MarkAsPreparingGuts(), MarkBufferDirty(), pgstat_create_replslot(), pgstat_drop_replslot(), PrepareRedoAdd(), PrepareRedoRemoveFull(), ProcArrayEndTransactionInternal(), ProcessTwoPhaseBuffer(), RemoveGXact(), SimpleLruReadPage(), SimpleLruZeroPage(), SlruInternalWritePage(), SyncRepWakeQueue(), TransactionIdSetPageStatusInternal(), TransactionIdSetStatusBit(), TransferPredicateLocksToNewTarget(), and write_relmap_file().

LWLockInitialize()

void LWLockInitialize ( LWLocklock,
int  tranche_id 
)

Definition at line 698 of file lwlock.c.

699{
700 /* verify the tranche_id is valid */
701 (void) GetLWTrancheName(tranche_id);
702
704#ifdef LOCK_DEBUG
705 pg_atomic_init_u32(&lock->nwaiters, 0);
706#endif
707 lock->tranche = tranche_id;
708 proclist_init(&lock->waiters);
709}
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 GetLWTrancheName(), LW_FLAG_RELEASE_OK, pg_atomic_init_u32(), proclist_init(), LWLock::state, LWLock::tranche, and LWLock::waiters.

Referenced by apw_init_state(), btinitparallelscan(), BufferManagerShmemInit(), create_internal(), dshash_create(), ExecAppendInitializeDSM(), ExecHashJoinInitializeDSM(), init_tdr_dsm(), InitializeLWLocks(), InitProcGlobal(), injection_stats_fixed_init_shmem_cb(), pgstat_archiver_init_shmem_cb(), pgstat_bgwriter_init_shmem_cb(), pgstat_checkpointer_init_shmem_cb(), pgstat_init_entry(), pgstat_io_init_shmem_cb(), pgstat_slru_init_shmem_cb(), pgstat_wal_init_shmem_cb(), PredicateLockShmemInit(), ReplicationOriginShmemInit(), ReplicationSlotsShmemInit(), SimpleLruInit(), sts_initialize(), tbm_prepare_shared_iterate(), test_lwlock_initialize(), and XLOGShmemInit().

LWLockNewTrancheId()

int LWLockNewTrancheId ( const char *  name )

Definition at line 596 of file lwlock.c.

597{
598 int result;
599
600 if (!name)
602 (errcode(ERRCODE_INVALID_NAME),
603 errmsg("tranche name cannot be NULL")));
604
605 if (strlen(name) >= NAMEDATALEN)
607 (errcode(ERRCODE_NAME_TOO_LONG),
608 errmsg("tranche name too long"),
609 errdetail("LWLock tranche names must be no longer than %d bytes.",
610 NAMEDATALEN - 1)));
611
612 /*
613 * We use the ShmemLock spinlock to protect LWLockCounter and
614 * LWLockTrancheNames.
615 */
617
619 {
622 (errmsg("maximum number of tranches already registered"),
623 errdetail("No more than %d tranches may be registered.",
625 }
626
627 result = (*LWLockCounter)++;
630
632
633 return result;
634}
int errdetail(const char *fmt,...)
Definition: elog.c:1207
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ereport(elevel,...)
Definition: elog.h:150
static int LocalLWLockCounter
Definition: lwlock.c:202
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
slock_t * ShmemLock
Definition: shmem.c:88
#define SpinLockRelease(lock)
Definition: spin.h:61
#define SpinLockAcquire(lock)
Definition: spin.h:59
const char * name

References ereport, errcode(), errdetail(), errmsg(), ERROR, 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(), InitializeLWLocks(), test_basic(), test_create(), test_dsa_basic(), test_dsa_resowners(), test_empty(), test_lwlock_tranche_creation(), test_lwlock_tranches(), test_random(), and test_slru_shmem_startup().

LWLockRelease()

void LWLockRelease ( LWLocklock )

Definition at line 1894 of file lwlock.c.

1895{
1897
1898 mode = LWLockDisownInternal(lock);
1899
1900 PRINT_LWDEBUG("LWLockRelease", lock, mode);
1901
1903
1904 /*
1905 * Now okay to allow cancel/die interrupts.
1906 */
1908}
static void LWLockReleaseInternal(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1830

References LWLockDisownInternal(), LWLockReleaseInternal(), mode, PRINT_LWDEBUG, and RESUME_INTERRUPTS.

Referenced by _bt_end_vacuum(), _bt_parallel_done(), _bt_parallel_primscan_schedule(), _bt_parallel_release(), _bt_parallel_seize(), _bt_start_vacuum(), _bt_vacuum_cycleid(), AbsorbSyncRequests(), ActivateCommitTs(), AdvanceNextFullTransactionIdPastXid(), AdvanceOldestClogXid(), AdvanceOldestCommitTsXid(), AdvanceXLInsertBuffer(), alloc_object(), AlterSystemSetConfigFile(), ApplyLauncherMain(), apw_detach_shmem(), apw_dump_now(), apw_load_buffers(), asyncQueueAddEntries(), asyncQueueAdvanceTail(), asyncQueueReadAllNotifications(), asyncQueueUnregister(), AtAbort_Twophase(), AtEOXact_LogicalRepWorkers(), AtPrepare_PredicateLocks(), attach_internal(), autoprewarm_main(), autoprewarm_start_worker(), AutoVacLauncherMain(), AutoVacuumRequestWork(), AutoVacWorkerMain(), BackendPidGetProc(), BackendXidGetPid(), BecomeLockGroupLeader(), BecomeLockGroupMember(), btparallelrescan(), BufferAlloc(), CancelDBBackends(), check_for_freed_segments(), CheckDeadLock(), CheckForSerializableConflictOut(), 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(), destroy_superblock(), 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_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(), dshash_release_lock(), dshash_seq_next(), dshash_seq_term(), dsm_attach(), dsm_create(), dsm_detach(), dsm_pin_segment(), dsm_unpin_segment(), ensure_active_superblock(), entry_reset(), EvictUnpinnedBufferInternal(), Exec_ListenPreCommit(), ExecParallelHashMergeCounters(), ExecParallelHashPopChunkQueue(), ExecParallelHashTupleAlloc(), ExecParallelHashTuplePrealloc(), ExpireAllKnownAssignedTransactionIds(), ExpireOldKnownAssignedTransactionIds(), ExpireTreeKnownAssignedTransactionIds(), ExtendBufferedRelShared(), ExtendCLOG(), ExtendCommitTs(), ExtendMultiXactMember(), ExtendMultiXactOffset(), ExtendSUBTRANS(), FastPathGetRelationLockEntry(), FastPathTransferRelationLocks(), find_multixact_start(), FindAndDropRelationBuffers(), FindDeletedTupleInLocalRel(), FinishPreparedTransaction(), FlushDatabaseBuffers(), FlushRelationBuffers(), FlushRelationsAllBuffers(), 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(), GetVictimBuffer(), GetVirtualXIDsDelayingChkpt(), GetWaitEventCustomIdentifier(), GetWaitEventCustomNames(), GetWalSummarizerState(), HaveVirtualXIDsDelayingChkpt(), init_conflict_slot_xmin(), init_dsm_registry(), InitWalSender(), injection_shmem_startup(), injection_stats_fixed_reset_all_cb(), injection_stats_fixed_snapshot_cb(), InjectionPointAttach(), InjectionPointDetach(), InjectionPointList(), InstallXLogFileSegment(), InvalidateBuffer(), InvalidateObsoleteReplicationSlots(), InvalidatePossiblyObsoleteSlot(), InvalidateVictimBuffer(), IoWorkerMain(), IsInstallXLogFileSegmentActive(), KnownAssignedXidsCompress(), KnownAssignedXidsReset(), lock_twophase_recover(), LockAcquireExtended(), LockBuffer(), LockErrorCleanup(), LockGXact(), LockHasWaiters(), LockRefindAndRelease(), LockRelease(), LockReleaseAll(), LockWaiterCount(), logicalrep_launcher_attach_dshmem(), logicalrep_pa_worker_stop(), 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(), MaybeExtendOffsetSlru(), 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_report_inj_fixed(), 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(), process_syncing_tables_for_apply(), ProcKill(), ProcNumberGetTransactionIds(), ProcSleep(), ReachedEndOfBackup(), read_relmap_file(), ReadMultiXactIdRange(), ReadNextFullTransactionId(), ReadNextMultiXactId(), ReadReplicationSlot(), RecordNewMultiXact(), RecoverPreparedTransactions(), RegisterDynamicBackgroundWorker(), RegisterPredicateLockingXid(), RelationCacheInitFilePostInvalidate(), RelationMapCopy(), RelationMapFinishBootstrap(), ReleaseOneSerializableXact(), ReleasePredicateLocks(), relmap_redo(), RemoveScratchTarget(), ReplicationOriginExitCleanup(), ReplicationSlotAcquire(), ReplicationSlotCleanup(), ReplicationSlotCreate(), ReplicationSlotDropPtr(), ReplicationSlotName(), ReplicationSlotRelease(), ReplicationSlotsComputeLogicalRestartLSN(), ReplicationSlotsComputeRequiredLSN(), ReplicationSlotsComputeRequiredXmin(), ReplicationSlotsCountDBSlots(), ReplicationSlotsDropDBSlots(), replorigin_advance(), replorigin_get_progress(), replorigin_session_advance(), replorigin_session_get_progress(), replorigin_session_reset(), replorigin_session_setup(), replorigin_state_clear(), resize(), RestoreScratchTarget(), restoreTwoPhaseData(), SaveSlotToPath(), SearchNamedReplicationSlot(), SerialAdd(), SerialGetMinConflictCommitSeqNo(), SerialInit(), SerialSetActiveSerXmin(), set_indexsafe_procflags(), set_val_in_shmem(), SetCommitTsLimit(), SetInstallXLogFileSegmentActive(), SetMultiXactIdLimit(), SetNextObjectId(), SetOffsetVacuumLimit(), SetTransactionIdLimit(), SetXidCommitTsInPage(), SharedInvalBackendInit(), ShmemInitStruct(), SICleanupQueue(), SIGetDataEntries(), SignalBackends(), SignalVirtualTransaction(), 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(), SyncOneBuffer(), SyncRepCancelWait(), SyncRepCleanupAtProcExit(), SyncRepReleaseWaiters(), SyncRepUpdateSyncStandbysDefined(), SyncRepWaitForLSN(), TablespaceCreateDbspace(), tbm_shared_iterate(), TerminateBackgroundWorker(), TerminateOtherDBBackends(), test_aio_shmem_startup(), 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(), UpdateMinRecoveryPoint(), vac_truncate_clog(), vacuum_rel(), VacuumUpdateCosts(), validate_sync_standby_slots(), VirtualXactLock(), VirtualXactLockTableCleanup(), VirtualXactLockTableInsert(), wait_for_relation_state_change(), wait_for_worker_state_change(), WaitEventCustomNew(), WaitForReplicationWorkerAttach(), WaitForWalSummarization(), WakeupWalSummarizer(), WalSummarizerMain(), WalSummarizerShutdown(), write_relcache_init_file(), xact_redo(), XidCacheRemoveRunningXids(), xlog_redo(), XLogBackgroundFlush(), XLogFlush(), XLogNeedsFlush(), XLogReportParameters(), and XLogShutdownWalRcv().

LWLockReleaseAll()

void LWLockReleaseAll ( void  )

Definition at line 1945 of file lwlock.c.

1946{
1947 while (num_held_lwlocks > 0)
1948 {
1949 HOLD_INTERRUPTS(); /* match the upcoming RESUME_INTERRUPTS */
1950
1952 }
1953}
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1894

References held_lwlocks, HOLD_INTERRUPTS, LWLockRelease(), and num_held_lwlocks.

Referenced by AbortSubTransaction(), AbortTransaction(), AutoVacLauncherMain(), AuxiliaryProcKill(), BackgroundWriterMain(), CheckpointerMain(), IoWorkerMain(), pgarch_archiveXlog(), ProcKill(), ShutdownAuxiliaryProcess(), WalSndErrorCleanup(), WalSummarizerMain(), and WalWriterMain().

LWLockReleaseClearVar()

void LWLockReleaseClearVar ( LWLocklock,
pg_atomic_uint64valptr,
uint64  val 
)

Definition at line 1923 of file lwlock.c.

1924{
1925 /*
1926 * Note that pg_atomic_exchange_u64 is a full barrier, so we're guaranteed
1927 * that the variable is updated before releasing the lock.
1928 */
1929 pg_atomic_exchange_u64(valptr, val);
1930
1931 LWLockRelease(lock);
1932}
static uint64 pg_atomic_exchange_u64(volatile pg_atomic_uint64 *ptr, uint64 newval)
Definition: atomics.h:501
long val
Definition: informix.c:689

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

Referenced by WALInsertLockRelease().

LWLockReleaseDisowned()

void LWLockReleaseDisowned ( LWLocklock,
LWLockMode  mode 
)

Definition at line 1914 of file lwlock.c.

1915{
1917}

References LWLockReleaseInternal(), and mode.

LWLockShmemSize()

Size LWLockShmemSize ( void  )

Definition at line 397 of file lwlock.c.

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

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 ( LWLocklock,
pg_atomic_uint64valptr,
uint64  val 
)

Definition at line 1726 of file lwlock.c.

1727{
1730
1731 PRINT_LWDEBUG("LWLockUpdateVar", lock, LW_EXCLUSIVE);
1732
1733 /*
1734 * Note that pg_atomic_exchange_u64 is a full barrier, so we're guaranteed
1735 * that the variable is updated before waking up waiters.
1736 */
1737 pg_atomic_exchange_u64(valptr, val);
1738
1740
1741 LWLockWaitListLock(lock);
1742
1744
1745 /*
1746 * See if there are any LW_WAIT_UNTIL_FREE waiters that need to be woken
1747 * up. They are always in the front of the queue.
1748 */
1749 proclist_foreach_modify(iter, &lock->waiters, lwWaitLink)
1750 {
1751 PGPROC *waiter = GetPGProcByNumber(iter.cur);
1752
1753 if (waiter->lwWaitMode != LW_WAIT_UNTIL_FREE)
1754 break;
1755
1756 proclist_delete(&lock->waiters, iter.cur, lwWaitLink);
1757 proclist_push_tail(&wakeup, iter.cur, lwWaitLink);
1758
1759 /* see LWLockWakeup() */
1760 Assert(waiter->lwWaiting == LW_WS_WAITING);
1762 }
1763
1764 /* We are done updating shared state of the lock itself. */
1766
1767 /*
1768 * Awaken any waiters I removed from the queue.
1769 */
1770 proclist_foreach_modify(iter, &wakeup, lwWaitLink)
1771 {
1772 PGPROC *waiter = GetPGProcByNumber(iter.cur);
1773
1774 proclist_delete(&wakeup, iter.cur, lwWaitLink);
1775 /* check comment in LWLockWakeup() about this barrier */
1777 waiter->lwWaiting = LW_WS_NOT_WAITING;
1778 PGSemaphoreUnlock(waiter->sem);
1779 }
1780}
#define pg_write_barrier()
Definition: atomics.h:155
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:237
#define LW_VAL_EXCLUSIVE
Definition: lwlock.c:101
static void LWLockWaitListLock(LWLock *lock)
Definition: lwlock.c:861
static void LWLockWaitListUnlock(LWLock *lock)
Definition: lwlock.c:913
#define GetPGProcByNumber(n)
Definition: proc.h:440
#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:241
static TimestampTz wakeup[NUM_WALRCV_WAKEUPS]
Definition: walreceiver.c:130

References Assert(), proclist_mutable_iter::cur, 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 ( LWLocklock,
pg_atomic_uint64valptr,
uint64  oldval,
uint64newval 
)

Definition at line 1590 of file lwlock.c.

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

References Assert(), HOLD_INTERRUPTS, LOG_LWDEBUG, LW_EXCLUSIVE, LW_FLAG_RELEASE_OK, LW_WAIT_UNTIL_FREE, LW_WS_NOT_WAITING, LWLockConflictsWithVar(), LWLockDequeueSelf(), LWLockQueueSelf(), LWLockReportWaitEnd(), LWLockReportWaitStart(), PGPROC::lwWaiting, MAX_BACKENDS, MyProc, newval, pg_atomic_fetch_or_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 
)

Definition at line 649 of file lwlock.c.

650{
652 static int NamedLWLockTrancheRequestsAllocated;
653
655 elog(FATAL, "cannot request additional LWLocks outside shmem_request_hook");
656
657 if (!tranche_name)
659 (errcode(ERRCODE_INVALID_NAME),
660 errmsg("tranche name cannot be NULL")));
661
662 if (strlen(tranche_name) >= NAMEDATALEN)
664 (errcode(ERRCODE_NAME_TOO_LONG),
665 errmsg("tranche name too long"),
666 errdetail("LWLock tranche names must be no longer than %d bytes.",
667 NAMEDATALEN - 1)));
668
670 {
671 NamedLWLockTrancheRequestsAllocated = 16;
674 NamedLWLockTrancheRequestsAllocated
675 * sizeof(NamedLWLockTrancheRequest));
676 }
677
678 if (NamedLWLockTrancheRequests >= NamedLWLockTrancheRequestsAllocated)
679 {
681
684 i * sizeof(NamedLWLockTrancheRequest));
685 NamedLWLockTrancheRequestsAllocated = i;
686 }
687
689 strlcpy(request->tranche_name, tranche_name, NAMEDATALEN);
690 request->num_lwlocks = num_lwlocks;
692}
#define FATAL
Definition: elog.h:41
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1229
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1610
MemoryContext TopMemoryContext
Definition: mcxt.c:166
bool process_shmem_requests_in_progress
Definition: miscinit.c:1790
static uint32 pg_nextpower2_32(uint32 num)
Definition: pg_bitutils.h:189
char tranche_name[NAMEDATALEN]
Definition: lwlock.c:183

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

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

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

LWLockTrancheNames

PGDLLIMPORT char** LWLockTrancheNames
extern

Definition at line 154 of file lwlock.c.

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

MainLWLockArray

NamedLWLockTrancheRequestArray

NamedLWLockTrancheRequests

AltStyle によって変換されたページ (->オリジナル) /