96#define LW_FLAG_HAS_WAITERS ((uint32) 1 << 31)
97#define LW_FLAG_WAKE_IN_PROGRESS ((uint32) 1 << 30)
98#define LW_FLAG_LOCKED ((uint32) 1 << 29)
100#define LW_FLAG_MASK (((1<<LW_FLAG_BITS)-1)<<(32-LW_FLAG_BITS))
103#define LW_VAL_EXCLUSIVE (MAX_BACKENDS + 1)
104#define LW_VAL_SHARED 1
107#define LW_SHARED_MASK MAX_BACKENDS
108#define LW_LOCK_MASK (MAX_BACKENDS | LW_VAL_EXCLUSIVE)
112 "MAX_BACKENDS + 1 needs to be a power of 2");
115 "MAX_BACKENDS and LW_FLAG_MASK overlap");
118 "LW_VAL_EXCLUSIVE and LW_FLAG_MASK overlap");
138#define PG_LWLOCK(id, lockname) [id] = CppAsString(lockname),
139#define PG_LWLOCKTRANCHE(id, lockname) [LWTRANCHE_##id] = CppAsString(lockname),
142#undef PG_LWLOCKTRANCHE
147 "missing entries in BuiltinTrancheNames[]");
157#define MAX_SIMUL_LWLOCKS 200
170#define MAX_USER_DEFINED_TRANCHES 256
229#define T_NAME(lock) \
230 GetLWTrancheName((lock)->tranche)
267 errmsg_internal(
"%d: %s(%s %p): excl %u shared %u haswaiters %u waiters %u waking %d",
288 T_NAME(lock), lock, msg)));
293#define PRINT_LWDEBUG(a,b,c) ((void)0)
294#define LOG_LWDEBUG(a,b,c) ((void)0)
352 "PID %d lwlock %s %p: shacq %u exacq %u blk %u spindelay %u dequeue self %u\n",
378 MemSet(&key, 0,
sizeof(key));
387 lwstats->dequeue_self_count = 0;
406 numLocks +=
request->num_lwlocks;
494 for (
int i = 0;
i <
request->num_lwlocks;
i++)
547 elog(
ERROR,
"requested tranche was not registered with RequestNamedLWLockTranche()");
552 elog(
ERROR,
"requested tranche is not registered");
569 errmsg(
"tranche name cannot be NULL")));
574 errmsg(
"tranche name too long"),
575 errdetail(
"LWLock tranche names must be no longer than %d bytes.",
585 (
errmsg(
"maximum number of tranches already registered"),
586 errdetail(
"No more than %d tranches may be registered.",
626 elog(
FATAL,
"cannot request additional LWLocks outside shmem_request_hook");
631 errmsg(
"tranche name cannot be NULL")));
636 errmsg(
"tranche name too long"),
637 errdetail(
"LWLock tranche names must be no longer than %d bytes.",
642 (
errmsg(
"maximum number of tranches already registered"),
643 errdetail(
"No more than %d tranches may be registered.",
650 elog(
ERROR,
"requested tranche \"%s\" is already registered", tranche_name);
660 request->num_lwlocks = num_lwlocks;
880 lwstats->spin_delay_count += delays;
993 LOG_LWDEBUG(
"LWLockRelease", lock,
"release waiter");
1026 elog(
PANIC,
"cannot wait without a PGPROC structure");
1029 elog(
PANIC,
"queueing for lock while waiting on another one");
1070 lwstats->dequeue_self_count++;
1219 LOG_LWDEBUG(
"LWLockAcquire", lock,
"immediately acquired lock");
1243 LOG_LWDEBUG(
"LWLockAcquire", lock,
"acquired, undoing queue");
1348 LOG_LWDEBUG(
"LWLockConditionalAcquire", lock,
"failed");
1422 LOG_LWDEBUG(
"LWLockAcquireOrWait", lock,
"waiting");
1452 LOG_LWDEBUG(
"LWLockAcquireOrWait", lock,
"awakened");
1456 LOG_LWDEBUG(
"LWLockAcquireOrWait", lock,
"acquired, undoing queue");
1478 LOG_LWDEBUG(
"LWLockAcquireOrWait", lock,
"failed");
1484 LOG_LWDEBUG(
"LWLockAcquireOrWait", lock,
"succeeded");
1626 LOG_LWDEBUG(
"LWLockWaitForVar", lock,
"free, undoing queue");
1671 LOG_LWDEBUG(
"LWLockWaitForVar", lock,
"awakened");
1826 LOG_LWDEBUG(
"LWLockRelease", lock,
"releasing waiters");
1910 begin = (
char *) lock;
1911 end = begin + nlocks *
stride;
Datum idx(PG_FUNCTION_ARGS)
static uint32 pg_atomic_fetch_and_u32(volatile pg_atomic_uint32 *ptr, uint32 and_)
static bool pg_atomic_compare_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 *expected, uint32 newval)
static uint32 pg_atomic_fetch_or_u32(volatile pg_atomic_uint32 *ptr, uint32 or_)
static uint32 pg_atomic_sub_fetch_u32(volatile pg_atomic_uint32 *ptr, int32 sub_)
static uint32 pg_atomic_fetch_sub_u32(volatile pg_atomic_uint32 *ptr, int32 sub_)
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
#define pg_write_barrier()
static uint32 pg_atomic_fetch_add_u32(volatile pg_atomic_uint32 *ptr, int32 add_)
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
static uint64 pg_atomic_read_u64(volatile pg_atomic_uint64 *ptr)
static uint64 pg_atomic_exchange_u64(volatile pg_atomic_uint64 *ptr, uint64 newval)
#define PG_USED_FOR_ASSERTS_ONLY
#define Assert(condition)
#define MemSet(start, val, len)
#define StaticAssertDecl(condition, errmessage)
#define fprintf(file, fmt, msg)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
void * hash_seq_search(HASH_SEQ_STATUS *status)
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
int errcode(int sqlerrcode)
int int errhidestmt(bool hide_stmt)
int errdetail(const char *fmt,...) pg_attribute_printf(1
int int errmsg_internal(const char *fmt,...) pg_attribute_printf(1
int errhidecontext(bool hide_ctx)
#define ereport(elevel,...)
bool IsPostmasterEnvironment
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
List * lappend(List *list, void *datum)
void LWLockUpdateVar(LWLock *lock, pg_atomic_uint64 *valptr, uint64 val)
static void LWLockWakeup(LWLock *lock)
bool LWLockHeldByMe(LWLock *lock)
static LWLockHandle held_lwlocks[MAX_SIMUL_LWLOCKS]
void LWLockReleaseClearVar(LWLock *lock, pg_atomic_uint64 *valptr, uint64 val)
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
#define MAX_USER_DEFINED_TRANCHES
static List * NamedLWLockTrancheRequests
int LWLockNewTrancheId(const char *name)
static bool LWLockAttemptLock(LWLock *lock, LWLockMode mode)
static void LWLockWaitListLock(LWLock *lock)
LWLockPadded * GetNamedLWLockTranche(const char *tranche_name)
bool LWLockHeldByMeInMode(LWLock *lock, LWLockMode mode)
static LWLockTrancheShmemData * LWLockTranches
static void LWLockReportWaitEnd(void)
static void LWLockShmemRequest(void *arg)
bool LWLockWaitForVar(LWLock *lock, pg_atomic_uint64 *valptr, uint64 oldval, uint64 *newval)
static const char * GetLWTrancheName(uint16 trancheId)
void RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks)
static int LocalNumUserDefinedTranches
#define LW_FLAG_HAS_WAITERS
#define MAX_SIMUL_LWLOCKS
static int NumLWLocksForNamedTranches(void)
void LWLockRelease(LWLock *lock)
static int num_held_lwlocks
void LWLockReleaseAll(void)
void LWLockInitialize(LWLock *lock, int tranche_id)
static const char *const BuiltinTrancheNames[]
static void LWLockWaitListUnlock(LWLock *lock)
#define LOG_LWDEBUG(a, b, c)
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
bool LWLockAcquireOrWait(LWLock *lock, LWLockMode mode)
static void LWLockQueueSelf(LWLock *lock, LWLockMode mode)
#define PRINT_LWDEBUG(a, b, c)
static void LWLockReportWaitStart(LWLock *lock)
LWLockPadded * MainLWLockArray
static int num_main_array_locks
const ShmemCallbacks LWLockCallbacks
#define LW_FLAG_WAKE_IN_PROGRESS
const char * GetLWLockIdentifier(uint32 classId, uint16 eventId)
static void LWLockDequeueSelf(LWLock *lock)
bool LWLockAnyHeldByMe(LWLock *lock, int nlocks, size_t stride)
static void LWLockShmemInit(void *arg)
static bool LWLockConflictsWithVar(LWLock *lock, pg_atomic_uint64 *valptr, uint64 oldval, uint64 *newval, bool *result)
void InitLWLockAccess(void)
#define BUFFER_MAPPING_LWLOCK_OFFSET
#define NUM_LOCK_PARTITIONS
@ LWTRANCHE_FIRST_USER_DEFINED
#define LOCK_MANAGER_LWLOCK_OFFSET
#define NUM_BUFFER_PARTITIONS
#define PREDICATELOCK_MANAGER_LWLOCK_OFFSET
#define NUM_FIXED_LWLOCKS
#define NUM_PREDICATELOCK_PARTITIONS
void * palloc0(Size size)
MemoryContext TopMemoryContext
MemoryContext PostmasterContext
void MemoryContextDelete(MemoryContext context)
void MemoryContextAllowInCriticalSection(MemoryContext context, bool allow)
#define AllocSetContextCreate
#define ALLOCSET_DEFAULT_SIZES
#define RESUME_INTERRUPTS()
#define HOLD_INTERRUPTS()
bool process_shmem_requests_in_progress
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
static PgChecksumMode mode
static int list_length(const List *l)
#define foreach_ptr(type, var, lst)
size_t strlcpy(char *dst, const char *src, size_t siz)
void PGSemaphoreUnlock(PGSemaphore sema)
void PGSemaphoreLock(PGSemaphore sema)
#define GetPGProcByNumber(n)
#define proclist_delete(list, procno, link_member)
static void proclist_init(proclist_head *list)
#define proclist_push_tail(list, procno, link_member)
#define proclist_push_head(list, procno, link_member)
#define proclist_foreach_modify(iter, lhead, link_member)
static bool proclist_is_empty(const proclist_head *list)
void perform_spin_delay(SpinDelayStatus *status)
void finish_spin_delay(SpinDelayStatus *status)
#define init_local_spin_delay(status)
#define SHMEM_ATTACH_UNKNOWN_SIZE
#define ShmemRequestStruct(...)
static void SpinLockRelease(volatile slock_t *lock)
static void SpinLockAcquire(volatile slock_t *lock)
static void SpinLockInit(volatile slock_t *lock)
struct LWLockTrancheShmemData::@23 user_defined[MAX_USER_DEFINED_TRANCHES]
char tranche_name[NAMEDATALEN]
ShmemRequestCallback request_fn
static void pgstat_report_wait_start(uint32 wait_event_info)
static void pgstat_report_wait_end(void)
static TimestampTz wakeup[NUM_WALRCV_WAKEUPS]