mirror of
https://github.com/postgres/postgres.git
synced 2025-11-21 00:42:43 +03:00
When trace_lwlocks is used, identify individual lwlocks by name.
Naming the individual lwlocks seems like something that may be useful for other types of debugging, monitoring, or instrumentation output, but this commit just implements it for the specific case of trace_lwlocks. Patch by me, reviewed by Amit Kapila and Kyotaro Horiguchi
This commit is contained in:
2
src/backend/storage/lmgr/.gitignore
vendored
Normal file
2
src/backend/storage/lmgr/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/lwlocknames.c
|
||||
/lwlocknames.h
|
||||
@@ -24,8 +24,17 @@ s_lock_test: s_lock.c $(top_builddir)/src/port/libpgport.a
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -DS_LOCK_TEST=1 $(srcdir)/s_lock.c \
|
||||
$(TASPATH) -L $(top_builddir)/src/port -lpgport -o s_lock_test
|
||||
|
||||
# see explanation in ../../parser/Makefile
|
||||
lwlocknames.c: lwlocknames.h ;
|
||||
|
||||
lwlocknames.h: $(top_srcdir)/src/backend/storage/lmgr/lwlocknames.txt generate-lwlocknames.pl
|
||||
$(PERL) $(srcdir)/generate-lwlocknames.pl $<
|
||||
|
||||
check: s_lock_test
|
||||
./s_lock_test
|
||||
|
||||
clean distclean maintainer-clean:
|
||||
clean distclean:
|
||||
rm -f s_lock_test
|
||||
|
||||
maintainer-clean: clean
|
||||
rm -f lwlocknames.h lwlocknames.c
|
||||
|
||||
67
src/backend/storage/lmgr/generate-lwlocknames.pl
Normal file
67
src/backend/storage/lmgr/generate-lwlocknames.pl
Normal file
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# Generate lwlocknames.h and lwlocknames.c from lwlocknames.txt
|
||||
# Copyright (c) 2000-2015, PostgreSQL Global Development Group
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
my $lastlockidx = -1;
|
||||
my $continue = "\n";
|
||||
|
||||
open my $lwlocknames, $ARGV[0] or die;
|
||||
|
||||
# Include PID in suffix in case parallel make runs this multiple times.
|
||||
my $htmp = "lwlocknames.h.tmp$$";
|
||||
my $ctmp = "lwlocknames.c.tmp$$";
|
||||
open H, '>', $htmp or die "Could not open $htmp: $!";
|
||||
open C, '>', $ctmp or die "Could not open $ctmp: $!";
|
||||
|
||||
my $autogen =
|
||||
"/* autogenerated from src/backend/storage/lmgr/lwlocknames.txt, do not edit */\n";
|
||||
print H $autogen;
|
||||
print H "/* there is deliberately not an #ifndef LWLOCKNAMES_H here */\n\n";
|
||||
print C $autogen, "\n";
|
||||
|
||||
print C "static char *MainLWLockNames[] = {";
|
||||
|
||||
while (<$lwlocknames>)
|
||||
{
|
||||
chomp;
|
||||
|
||||
# Skip comments
|
||||
next if /^#/;
|
||||
next if /^\s*$/;
|
||||
|
||||
die "unable to parse lwlocknames.txt"
|
||||
unless /^(\w+)\s+(\d+)$/;
|
||||
|
||||
(my $lockname, my $lockidx) = ($1, $2);
|
||||
|
||||
die "lwlocknames.txt not in order" if $lockidx < $lastlockidx;
|
||||
die "lwlocknames.txt has duplicates" if $lockidx == $lastlockidx;
|
||||
|
||||
while ($lastlockidx < $lockidx - 1)
|
||||
{
|
||||
++$lastlockidx;
|
||||
printf C "%s \"<unassigned:%d>\"", $continue, $lastlockidx;
|
||||
$continue = ",\n";
|
||||
}
|
||||
printf C "%s \"%s\"", $continue, $lockname;
|
||||
$lastlockidx = $lockidx;
|
||||
$continue = ",\n";
|
||||
|
||||
print H "#define $lockname (&MainLWLockArray[$lockidx].lock)\n";
|
||||
}
|
||||
|
||||
printf C "\n};\n";
|
||||
print H "\n";
|
||||
printf H "#define NUM_INDIVIDUAL_LWLOCKS %s\n", $lastlockidx + 1;
|
||||
|
||||
close H;
|
||||
close C;
|
||||
|
||||
rename($htmp, 'lwlocknames.h') || die "rename: $htmp: $!";
|
||||
rename($ctmp, 'lwlocknames.c') || die "rename: $ctmp: $!";
|
||||
|
||||
close $lwlocknames;
|
||||
@@ -95,6 +95,9 @@
|
||||
#include "utils/hsearch.h"
|
||||
#endif
|
||||
|
||||
/* Constants for lwlock names */
|
||||
#include "lwlocknames.c"
|
||||
|
||||
|
||||
/* We use the ShmemLock spinlock to protect LWLockAssign */
|
||||
extern slock_t *ShmemLock;
|
||||
@@ -183,18 +186,32 @@ PRINT_LWDEBUG(const char *where, LWLock *lock, LWLockMode mode)
|
||||
if (Trace_lwlocks)
|
||||
{
|
||||
uint32 state = pg_atomic_read_u32(&lock->state);
|
||||
int id = T_ID(lock);
|
||||
|
||||
ereport(LOG,
|
||||
(errhidestmt(true),
|
||||
errhidecontext(true),
|
||||
errmsg("%d: %s(%s %d): excl %u shared %u haswaiters %u waiters %u rOK %d",
|
||||
MyProcPid,
|
||||
where, T_NAME(lock), T_ID(lock),
|
||||
!!(state & LW_VAL_EXCLUSIVE),
|
||||
state & LW_SHARED_MASK,
|
||||
!!(state & LW_FLAG_HAS_WAITERS),
|
||||
pg_atomic_read_u32(&lock->nwaiters),
|
||||
!!(state & LW_FLAG_RELEASE_OK))));
|
||||
if (lock->tranche == 0 && id < NUM_INDIVIDUAL_LWLOCKS)
|
||||
ereport(LOG,
|
||||
(errhidestmt(true),
|
||||
errhidecontext(true),
|
||||
errmsg("%d: %s(%s): excl %u shared %u haswaiters %u waiters %u rOK %d",
|
||||
MyProcPid,
|
||||
where, MainLWLockNames[id],
|
||||
!!(state & LW_VAL_EXCLUSIVE),
|
||||
state & LW_SHARED_MASK,
|
||||
!!(state & LW_FLAG_HAS_WAITERS),
|
||||
pg_atomic_read_u32(&lock->nwaiters),
|
||||
!!(state & LW_FLAG_RELEASE_OK))));
|
||||
else
|
||||
ereport(LOG,
|
||||
(errhidestmt(true),
|
||||
errhidecontext(true),
|
||||
errmsg("%d: %s(%s %d): excl %u shared %u haswaiters %u waiters %u rOK %d",
|
||||
MyProcPid,
|
||||
where, T_NAME(lock), id,
|
||||
!!(state & LW_VAL_EXCLUSIVE),
|
||||
state & LW_SHARED_MASK,
|
||||
!!(state & LW_FLAG_HAS_WAITERS),
|
||||
pg_atomic_read_u32(&lock->nwaiters),
|
||||
!!(state & LW_FLAG_RELEASE_OK))));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,11 +221,20 @@ LOG_LWDEBUG(const char *where, LWLock *lock, const char *msg)
|
||||
/* hide statement & context here, otherwise the log is just too verbose */
|
||||
if (Trace_lwlocks)
|
||||
{
|
||||
ereport(LOG,
|
||||
(errhidestmt(true),
|
||||
errhidecontext(true),
|
||||
errmsg("%s(%s %d): %s", where,
|
||||
T_NAME(lock), T_ID(lock), msg)));
|
||||
int id = T_ID(lock);
|
||||
|
||||
if (lock->tranche == 0 && id < NUM_INDIVIDUAL_LWLOCKS)
|
||||
ereport(LOG,
|
||||
(errhidestmt(true),
|
||||
errhidecontext(true),
|
||||
errmsg("%s(%s): %s", where,
|
||||
MainLWLockNames[id], msg)));
|
||||
else
|
||||
ereport(LOG,
|
||||
(errhidestmt(true),
|
||||
errhidecontext(true),
|
||||
errmsg("%s(%s %d): %s", where,
|
||||
T_NAME(lock), id, msg)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
47
src/backend/storage/lmgr/lwlocknames.txt
Normal file
47
src/backend/storage/lmgr/lwlocknames.txt
Normal file
@@ -0,0 +1,47 @@
|
||||
# Some commonly-used locks have predefined positions within MainLWLockArray;
|
||||
# these are defined here. If you add a lock, add it to the end to avoid
|
||||
# renumbering the existing locks; if you remove a lock, consider leaving a gap
|
||||
# in the numbering sequence for the benefit of DTrace and other external
|
||||
# debugging scripts.
|
||||
|
||||
# 0 is available; was formerly BufFreelistLock
|
||||
ShmemIndexLock 1
|
||||
OidGenLock 2
|
||||
XidGenLock 3
|
||||
ProcArrayLock 4
|
||||
SInvalReadLock 5
|
||||
SInvalWriteLock 6
|
||||
WALBufMappingLock 7
|
||||
WALWriteLock 8
|
||||
ControlFileLock 9
|
||||
CheckpointLock 10
|
||||
CLogControlLock 11
|
||||
SubtransControlLock 12
|
||||
MultiXactGenLock 13
|
||||
MultiXactOffsetControlLock 14
|
||||
MultiXactMemberControlLock 15
|
||||
RelCacheInitLock 16
|
||||
CheckpointerCommLock 17
|
||||
TwoPhaseStateLock 18
|
||||
TablespaceCreateLock 19
|
||||
BtreeVacuumLock 20
|
||||
AddinShmemInitLock 21
|
||||
AutovacuumLock 22
|
||||
AutovacuumScheduleLock 23
|
||||
SyncScanLock 24
|
||||
RelationMappingLock 25
|
||||
AsyncCtlLock 26
|
||||
AsyncQueueLock 27
|
||||
SerializableXactHashLock 28
|
||||
SerializableFinishedListLock 29
|
||||
SerializablePredicateLockListLock 30
|
||||
OldSerXidLock 31
|
||||
SyncRepLock 32
|
||||
BackgroundWorkerLock 33
|
||||
DynamicSharedMemoryControlLock 34
|
||||
AutoFileLock 35
|
||||
ReplicationSlotAllocationLock 36
|
||||
ReplicationSlotControlLock 37
|
||||
CommitTsControlLock 38
|
||||
CommitTsLock 39
|
||||
ReplicationOriginLock 40
|
||||
Reference in New Issue
Block a user