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:
Robert Haas 2015-09-11 13:58:28 -04:00
parent a1b2888517
commit aa65de042f
9 changed files with 200 additions and 68 deletions

View File

@ -106,7 +106,7 @@ endif
endif # aix
# Update the commonly used headers before building the subdirectories
$(SUBDIRS:%=%-recursive): $(top_builddir)/src/include/parser/gram.h $(top_builddir)/src/include/catalog/schemapg.h $(top_builddir)/src/include/utils/fmgroids.h $(top_builddir)/src/include/utils/errcodes.h $(top_builddir)/src/include/utils/probes.h
$(SUBDIRS:%=%-recursive): $(top_builddir)/src/include/parser/gram.h $(top_builddir)/src/include/catalog/schemapg.h $(top_builddir)/src/include/storage/lwlocknames.h $(top_builddir)/src/include/utils/fmgroids.h $(top_builddir)/src/include/utils/errcodes.h $(top_builddir)/src/include/utils/probes.h
# run this unconditionally to avoid needing to know its dependencies here:
submake-schemapg:
@ -135,6 +135,9 @@ postgres.o: $(OBJS)
parser/gram.h: parser/gram.y
$(MAKE) -C parser gram.h
storage/lmgr/lwlocknames.h: storage/lmgr/generate-lwlocknames.pl storage/lmgr/lwlocknames.txt
$(MAKE) -C storage/lmgr lwlocknames.h
utils/fmgroids.h: utils/Gen_fmgrtab.pl catalog/Catalog.pm $(top_srcdir)/src/include/catalog/pg_proc.h
$(MAKE) -C utils fmgroids.h
@ -165,6 +168,11 @@ $(top_builddir)/src/include/catalog/schemapg.h: catalog/schemapg.h
cd '$(dir $@)' && rm -f $(notdir $@) && \
$(LN_S) "$$prereqdir/$(notdir $<)" .
$(top_builddir)/src/include/storage/lwlocknames.h: storage/lmgr/lwlocknames.h
prereqdir=`cd '$(dir $<)' >/dev/null && pwd` && \
cd '$(dir $@)' && rm -f $(notdir $@) && \
$(LN_S) "$$prereqdir/$(notdir $<)" .
$(top_builddir)/src/include/utils/errcodes.h: utils/errcodes.h
prereqdir=`cd '$(dir $<)' >/dev/null && pwd` && \
cd '$(dir $@)' && rm -f $(notdir $@) && \
@ -192,6 +200,7 @@ distprep:
$(MAKE) -C bootstrap bootparse.c bootscanner.c
$(MAKE) -C catalog schemapg.h postgres.bki postgres.description postgres.shdescription
$(MAKE) -C replication repl_gram.c repl_scanner.c
$(MAKE) -C storage lwlocknames.h
$(MAKE) -C utils fmgrtab.c fmgroids.h errcodes.h
$(MAKE) -C utils/misc guc-file.c
$(MAKE) -C utils/sort qsort_tuple.c
@ -282,6 +291,7 @@ clean:
rm -f $(LOCALOBJS) postgres$(X) $(POSTGRES_IMP) \
$(top_builddir)/src/include/parser/gram.h \
$(top_builddir)/src/include/catalog/schemapg.h \
$(top_builddir)/src/include/storage/lwlocknames.h \
$(top_builddir)/src/include/utils/fmgroids.h \
$(top_builddir)/src/include/utils/probes.h
ifeq ($(PORTNAME), cygwin)
@ -307,6 +317,8 @@ maintainer-clean: distclean
catalog/postgres.shdescription \
replication/repl_gram.c \
replication/repl_scanner.c \
storage/lmgr/lwlocknames.c \
storage/lmgr/lwlocknames.h \
utils/fmgroids.h \
utils/fmgrtab.c \
utils/errcodes.h \

2
src/backend/storage/lmgr/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/lwlocknames.c
/lwlocknames.h

View File

@ -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

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

View File

@ -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)));
}
}

View 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

1
src/include/storage/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/lwlocknames.h

View File

@ -91,56 +91,8 @@ typedef union LWLockPadded
} LWLockPadded;
extern PGDLLIMPORT LWLockPadded *MainLWLockArray;
/*
* Some commonly-used locks have predefined positions within MainLWLockArray;
* defining macros here makes it much easier to keep track of these. 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 */
#define ShmemIndexLock (&MainLWLockArray[1].lock)
#define OidGenLock (&MainLWLockArray[2].lock)
#define XidGenLock (&MainLWLockArray[3].lock)
#define ProcArrayLock (&MainLWLockArray[4].lock)
#define SInvalReadLock (&MainLWLockArray[5].lock)
#define SInvalWriteLock (&MainLWLockArray[6].lock)
#define WALBufMappingLock (&MainLWLockArray[7].lock)
#define WALWriteLock (&MainLWLockArray[8].lock)
#define ControlFileLock (&MainLWLockArray[9].lock)
#define CheckpointLock (&MainLWLockArray[10].lock)
#define CLogControlLock (&MainLWLockArray[11].lock)
#define SubtransControlLock (&MainLWLockArray[12].lock)
#define MultiXactGenLock (&MainLWLockArray[13].lock)
#define MultiXactOffsetControlLock (&MainLWLockArray[14].lock)
#define MultiXactMemberControlLock (&MainLWLockArray[15].lock)
#define RelCacheInitLock (&MainLWLockArray[16].lock)
#define CheckpointerCommLock (&MainLWLockArray[17].lock)
#define TwoPhaseStateLock (&MainLWLockArray[18].lock)
#define TablespaceCreateLock (&MainLWLockArray[19].lock)
#define BtreeVacuumLock (&MainLWLockArray[20].lock)
#define AddinShmemInitLock (&MainLWLockArray[21].lock)
#define AutovacuumLock (&MainLWLockArray[22].lock)
#define AutovacuumScheduleLock (&MainLWLockArray[23].lock)
#define SyncScanLock (&MainLWLockArray[24].lock)
#define RelationMappingLock (&MainLWLockArray[25].lock)
#define AsyncCtlLock (&MainLWLockArray[26].lock)
#define AsyncQueueLock (&MainLWLockArray[27].lock)
#define SerializableXactHashLock (&MainLWLockArray[28].lock)
#define SerializableFinishedListLock (&MainLWLockArray[29].lock)
#define SerializablePredicateLockListLock (&MainLWLockArray[30].lock)
#define OldSerXidLock (&MainLWLockArray[31].lock)
#define SyncRepLock (&MainLWLockArray[32].lock)
#define BackgroundWorkerLock (&MainLWLockArray[33].lock)
#define DynamicSharedMemoryControlLock (&MainLWLockArray[34].lock)
#define AutoFileLock (&MainLWLockArray[35].lock)
#define ReplicationSlotAllocationLock (&MainLWLockArray[36].lock)
#define ReplicationSlotControlLock (&MainLWLockArray[37].lock)
#define CommitTsControlLock (&MainLWLockArray[38].lock)
#define CommitTsLock (&MainLWLockArray[39].lock)
#define ReplicationOriginLock (&MainLWLockArray[40].lock)
#define NUM_INDIVIDUAL_LWLOCKS 41
/* Names for fixed lwlocks */
#include "lwlocknames.h"
/*
* It's a bit odd to declare NUM_BUFFER_PARTITIONS and NUM_LOCK_PARTITIONS

View File

@ -285,6 +285,22 @@ s{PG_VERSION_STR "[^"]+"}{__STRINGIFY(x) #x\n#define __STRINGIFY2(z) __STRINGIFY
'src/include/utils/fmgroids.h');
}
if (IsNewer(
'src/include/storage/lwlocknames.h', 'src/backend/storage/lmgr/lwlocknames.txt'))
{
print "Generating lwlocknames.c and lwlocknames.h...\n";
chdir('src/backend/storage/lmgr');
system('perl generate-lwlocknames.pl lwlocknames.txt');
chdir('../../../..');
}
if (IsNewer(
'src/include/storage/lwlocknames.h',
'src/backend/storage/lmgr/lwlocknames.h'))
{
copyFile('src/backend/storage/lmgr/lwlocknames.h',
'src/include/storage/lwlocknames.h');
}
if (IsNewer('src/include/utils/probes.h', 'src/backend/utils/probes.d'))
{
print "Generating probes.h...\n";