diff --git a/contrib/postgres_fdw/connection.c b/contrib/postgres_fdw/connection.c
index 43c7fc9..9f4efc3 100644
--- a/contrib/postgres_fdw/connection.c
+++ b/contrib/postgres_fdw/connection.c
@@ -496,7 +496,7 @@ pgfdw_get_result(PGconn *conn, const char *query)
wc = WaitLatchOrSocket(MyLatch,
WL_LATCH_SET | WL_SOCKET_READABLE,
PQsocket(conn),
- -1L);
+ -1L, LATCH_EXTENSION);
ResetLatch(MyLatch);
CHECK_FOR_INTERRUPTS();
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 2b2f7e3..f7f3a59 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -679,6 +679,16 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser
buffer in question.
+
+
+ Latch>: The server process is waiting for a latch.
+ Latch is an inter-process facility using boolean variables letting
+ a process sleep until it is set. Latches support several type of
+ operations, like postmaster death handling, timeout and socket
+ activity lookup, and are a useful replacement for sleep>
+ where signal handling matters.
+
+
@@ -1081,6 +1091,131 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser
BufferPin>
Waiting to acquire a pin on a buffer.
+
+ Latch>
+ ArchiverMain>
+ Waiting in main loop of the archiver process.
+
+
+ AutoVacuumMain>
+ Waiting in main loop of autovacuum launcher process.
+
+
+ BaseBackupThrottle>
+ Waiting during base backup when throttling activity.
+
+
+ BgWorkerStartup>
+ Waiting for background worker to start up.
+
+
+ BgWorkerShutdown>
+ Waiting for background worker to shut down.
+
+
+ BgWriterMain>
+ Waiting in main loop of background writer process background worker.
+
+
+ BgWriterHibernate>
+ Waiting in background writer process, hibernating.
+
+
+ CheckpointerMain>
+ Waiting in main loop of checkpointer process.
+
+
+ ExecuteGather>
+ Waiting for activity from child process when executing Gather> node.
+
+
+ Extension>
+ Waiting in the code path of an extension, should be used by custom plugins and modules
+
+
+ MessageQueuePutMessage>
+ Waiting to put new message in shared message queue.
+
+
+ MessageQueueSend>
+ Waiting to send bytes in shared message queue.
+
+
+ MessageQueueReceive>
+ Waiting to receive bytes in shared message queue.
+
+
+ MessageQueueInternal>
+ Waiting for other process to be attached in shared message queue.
+
+
+ ParallelFinish>
+ Waiting for parallel workers to finish computing.
+
+
+ PGSleep>
+ Waiting in process that called pg_sleep>.
+
+
+ PGStatMain>
+ Waiting in main loop of the statistics collector process.
+
+
+ ProcSleep>
+ Waiting for a specific lock.
+
+
+ ProcSignal>
+ Waiting for signal from another backend.
+
+
+ RecoveryApplyDelay>
+ Waiting to apply WAL at recovery because it is delayed.
+
+
+ RecoveryWALStream>
+ Waiting for WAL from a stram at recovery.
+
+
+ RecoveryWALAll>
+ Waiting for WAL from any kind of source (local, archive or stream) at recovery.
+
+
+ SSLOpenServer>
+ Waiting for SSL while attempting connection.
+
+
+ SyncRep>
+ Waiting for WAL commit during synchronous replication.
+
+
+ SysLoggerMain>
+ Waiting in main loop of syslogger process.
+
+
+ WALWriterMain>
+ Waiting in main loop of WAL writer process.
+
+
+ WALReceiverWaitStart>
+ Waiting for startup process to send initial data for streaming replication.
+
+
+ WALReceiverMain>
+ Waiting in main loop of WAL receiver process.
+
+
+ WALSenderMain>
+ Waiting in main loop of WAL sender process.
+
+
+ WALSenderWaitForWAL>
+ Waiting for WAL to be flushed in WAL sender process.
+
+
+ WALSenderWriteData>
+ Waiting for any activity when processing replies from WAL receiver in WAL sender process.
+
diff --git a/src/backend/access/transam/parallel.c b/src/backend/access/transam/parallel.c
index 934dba8..13805da 100644
--- a/src/backend/access/transam/parallel.c
+++ b/src/backend/access/transam/parallel.c
@@ -534,7 +534,8 @@ WaitForParallelWorkersToFinish(ParallelContext *pcxt)
if (!anyone_alive)
break;
- WaitLatch(&MyProc->procLatch, WL_LATCH_SET, -1);
+ WaitLatch(&MyProc->procLatch, WL_LATCH_SET, -1,
+ LATCH_PARALLEL_WAIT_FINISH);
ResetLatch(&MyProc->procLatch);
}
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index b473f19..a1afff9 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -5758,7 +5758,8 @@ recoveryApplyDelay(XLogReaderState *record)
WaitLatch(&XLogCtl->recoveryWakeupLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- secs * 1000L + microsecs / 1000);
+ secs * 1000L + microsecs / 1000,
+ LATCH_RECOVERY_APPLY_DELAY);
}
return true;
}
@@ -11296,7 +11297,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
WaitLatch(&XLogCtl->recoveryWakeupLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- wait_time);
+ wait_time, LATCH_RECOVERY_WAL_STREAM);
ResetLatch(&XLogCtl->recoveryWakeupLatch);
now = GetCurrentTimestamp();
}
@@ -11459,7 +11460,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
*/
WaitLatch(&XLogCtl->recoveryWakeupLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- 5000L);
+ 5000L, LATCH_RECOVERY_WAL_ALL);
ResetLatch(&XLogCtl->recoveryWakeupLatch);
break;
}
diff --git a/src/backend/executor/nodeGather.c b/src/backend/executor/nodeGather.c
index 3834ed6..98fa579 100644
--- a/src/backend/executor/nodeGather.c
+++ b/src/backend/executor/nodeGather.c
@@ -381,7 +381,7 @@ gather_readnext(GatherState *gatherstate)
return NULL;
/* Nothing to do except wait for developments. */
- WaitLatch(MyLatch, WL_LATCH_SET, 0);
+ WaitLatch(MyLatch, WL_LATCH_SET, 0, LATCH_EXECUTE_GATHER);
CHECK_FOR_INTERRUPTS();
ResetLatch(MyLatch);
}
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 95cceee..257c013 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -418,7 +418,8 @@ aloop:
else
waitfor = WL_SOCKET_WRITEABLE;
- WaitLatchOrSocket(MyLatch, waitfor, port->sock, 0);
+ WaitLatchOrSocket(MyLatch, waitfor, port->sock, 0,
+ LATCH_SSL_OPEN_SERVER);
goto aloop;
case SSL_ERROR_SYSCALL:
if (r < 0)
diff --git a/src/backend/libpq/pqmq.c b/src/backend/libpq/pqmq.c
index 350210b..fa0cad1 100644
--- a/src/backend/libpq/pqmq.c
+++ b/src/backend/libpq/pqmq.c
@@ -171,7 +171,7 @@ mq_putmessage(char msgtype, const char *s, size_t len)
if (result != SHM_MQ_WOULD_BLOCK)
break;
- WaitLatch(&MyProc->procLatch, WL_LATCH_SET, 0);
+ WaitLatch(&MyProc->procLatch, WL_LATCH_SET, 0, LATCH_MQ_PUT_MESSAGE);
CHECK_FOR_INTERRUPTS();
ResetLatch(&MyProc->procLatch);
}
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 6bdaac5..218f53b 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -598,7 +598,8 @@ AutoVacLauncherMain(int argc, char *argv[])
*/
rc = WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- (nap.tv_sec * 1000L) + (nap.tv_usec / 1000L));
+ (nap.tv_sec * 1000L) + (nap.tv_usec / 1000L),
+ LATCH_AUTOVACUUM_MAIN);
ResetLatch(MyLatch);
diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c
index 382edad..a605225 100644
--- a/src/backend/postmaster/bgworker.c
+++ b/src/backend/postmaster/bgworker.c
@@ -969,7 +969,8 @@ WaitForBackgroundWorkerStartup(BackgroundWorkerHandle *handle, pid_t *pidp)
break;
rc = WaitLatch(MyLatch,
- WL_LATCH_SET | WL_POSTMASTER_DEATH, 0);
+ WL_LATCH_SET | WL_POSTMASTER_DEATH, 0,
+ LATCH_BGWORKER_STARTUP);
if (rc & WL_POSTMASTER_DEATH)
{
@@ -1008,7 +1009,8 @@ WaitForBackgroundWorkerShutdown(BackgroundWorkerHandle *handle)
return status;
rc = WaitLatch(&MyProc->procLatch,
- WL_LATCH_SET | WL_POSTMASTER_DEATH, 0);
+ WL_LATCH_SET | WL_POSTMASTER_DEATH, 0,
+ LATCH_BGWORKER_SHUTDOWN);
if (rc & WL_POSTMASTER_DEATH)
return BGWH_POSTMASTER_DIED;
diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c
index 00f03d8..c3b5427 100644
--- a/src/backend/postmaster/bgwriter.c
+++ b/src/backend/postmaster/bgwriter.c
@@ -347,7 +347,8 @@ BackgroundWriterMain(void)
*/
rc = WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- BgWriterDelay /* ms */ );
+ BgWriterDelay /* ms */,
+ LATCH_BGWRITER_MAIN);
/*
* If no latch event and BgBufferSync says nothing's happening, extend
@@ -374,7 +375,8 @@ BackgroundWriterMain(void)
/* Sleep ... */
rc = WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- BgWriterDelay * HIBERNATE_FACTOR);
+ BgWriterDelay * HIBERNATE_FACTOR,
+ LATCH_BGWRITER_HIBERNATE);
/* Reset the notification request in case we timed out */
StrategyNotifyBgWriter(-1);
}
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index 8d4b353..f617f86 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -558,7 +558,8 @@ CheckpointerMain(void)
rc = WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- cur_timeout * 1000L /* convert to ms */ );
+ cur_timeout * 1000L /* convert to ms */,
+ LATCH_CHECKPOINTER_MAIN);
/*
* Emergency bailout if postmaster has died. This is to avoid the
diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c
index 1aa6466..3815a3c 100644
--- a/src/backend/postmaster/pgarch.c
+++ b/src/backend/postmaster/pgarch.c
@@ -390,7 +390,7 @@ pgarch_MainLoop(void)
rc = WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- timeout * 1000L);
+ timeout * 1000L, LATCH_ARCHIVER_MAIN);
if (rc & WL_TIMEOUT)
wakened = true;
}
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index 41f4374..bd9a58b 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -3150,6 +3150,9 @@ pgstat_get_wait_event_type(uint32 wait_event_info)
case WAIT_BUFFER_PIN:
event_type = "BufferPin";
break;
+ case WAIT_LATCH:
+ event_type = "Latch";
+ break;
default:
event_type = "???";
break;
@@ -3191,6 +3194,9 @@ pgstat_get_wait_event(uint32 wait_event_info)
case WAIT_BUFFER_PIN:
event_name = "BufferPin";
break;
+ case WAIT_LATCH:
+ event_name = GetLatchIdentifier(eventId);
+ break;
default:
event_name = "unknown wait event";
break;
@@ -3681,7 +3687,7 @@ PgstatCollectorMain(int argc, char *argv[])
wr = WaitLatchOrSocket(MyLatch,
WL_LATCH_SET | WL_POSTMASTER_DEATH | WL_SOCKET_READABLE,
pgStatSock,
- -1L);
+ -1L, LATCH_PGSTAT_MAIN);
#else
/*
@@ -3697,7 +3703,8 @@ PgstatCollectorMain(int argc, char *argv[])
wr = WaitLatchOrSocket(MyLatch,
WL_LATCH_SET | WL_POSTMASTER_DEATH | WL_SOCKET_READABLE | WL_TIMEOUT,
pgStatSock,
- 2 * 1000L /* msec */ );
+ 2 * 1000L /* msec */,
+ LATCH_PGSTAT_MAIN);
#endif
/*
diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c
index e7e488a..2aedd32 100644
--- a/src/backend/postmaster/syslogger.c
+++ b/src/backend/postmaster/syslogger.c
@@ -424,7 +424,8 @@ SysLoggerMain(int argc, char *argv[])
rc = WaitLatchOrSocket(MyLatch,
WL_LATCH_SET | WL_SOCKET_READABLE | cur_flags,
syslogPipe[0],
- cur_timeout);
+ cur_timeout,
+ LATCH_SYSLOGGER_MAIN);
if (rc & WL_SOCKET_READABLE)
{
@@ -475,7 +476,8 @@ SysLoggerMain(int argc, char *argv[])
(void) WaitLatch(MyLatch,
WL_LATCH_SET | cur_flags,
- cur_timeout);
+ cur_timeout,
+ LATCH_SYSLOGGER_MAIN);
EnterCriticalSection(&sysloggerSection);
#endif /* WIN32 */
diff --git a/src/backend/postmaster/walwriter.c b/src/backend/postmaster/walwriter.c
index 228190a..4b0a074 100644
--- a/src/backend/postmaster/walwriter.c
+++ b/src/backend/postmaster/walwriter.c
@@ -292,7 +292,8 @@ WalWriterMain(void)
rc = WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- cur_timeout);
+ cur_timeout,
+ LATCH_WALWRITER_MAIN);
/*
* Emergency bailout if postmaster has died. This is to avoid the
diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c
index 1008873..d7dfc27 100644
--- a/src/backend/replication/basebackup.c
+++ b/src/backend/replication/basebackup.c
@@ -1286,7 +1286,8 @@ throttle(size_t increment)
*/
wait_result = WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- (long) (sleep / 1000));
+ (long) (sleep / 1000),
+ LATCH_BASEBACKUP_THROTTLE);
if (wait_result & WL_LATCH_SET)
CHECK_FOR_INTERRUPTS();
diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c
index 959ca78..aab6a7b 100644
--- a/src/backend/replication/syncrep.c
+++ b/src/backend/replication/syncrep.c
@@ -265,7 +265,8 @@ SyncRepWaitForLSN(XLogRecPtr lsn, bool commit)
* Wait on latch. Any condition that should wake us up will set the
* latch, so no need for timeout.
*/
- WaitLatch(MyLatch, WL_LATCH_SET | WL_POSTMASTER_DEATH, -1);
+ WaitLatch(MyLatch, WL_LATCH_SET | WL_POSTMASTER_DEATH, -1,
+ LATCH_SYNC_REP);
}
/*
diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c
index 6fd5952..b5ac1bb 100644
--- a/src/backend/replication/walreceiver.c
+++ b/src/backend/replication/walreceiver.c
@@ -466,7 +466,8 @@ WalReceiverMain(void)
WL_POSTMASTER_DEATH | WL_SOCKET_READABLE |
WL_TIMEOUT | WL_LATCH_SET,
wait_fd,
- NAPTIME_PER_CYCLE);
+ NAPTIME_PER_CYCLE,
+ LATCH_WAL_RECEIVER_MAIN);
if (rc & WL_LATCH_SET)
{
ResetLatch(&walrcv->latch);
@@ -665,7 +666,8 @@ WalRcvWaitForStartPosition(XLogRecPtr *startpoint, TimeLineID *startpointTLI)
}
SpinLockRelease(&walrcv->mutex);
- WaitLatch(&walrcv->latch, WL_LATCH_SET | WL_POSTMASTER_DEATH, 0);
+ WaitLatch(&walrcv->latch, WL_LATCH_SET | WL_POSTMASTER_DEATH, 0,
+ LATCH_WAL_RECEIVER_WAIT_START);
}
if (update_process_title)
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 926a247..8094b3ce 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -1146,7 +1146,8 @@ WalSndWriteData(LogicalDecodingContext *ctx, XLogRecPtr lsn, TransactionId xid,
/* Sleep until something happens or we time out */
WaitLatchOrSocket(MyLatch, wakeEvents,
- MyProcPort->sock, sleeptime);
+ MyProcPort->sock, sleeptime,
+ LATCH_WAL_SENDER_WRITE_DATA);
}
/* reactivate latch so WalSndLoop knows to continue */
@@ -1272,7 +1273,8 @@ WalSndWaitForWal(XLogRecPtr loc)
/* Sleep until something happens or we time out */
WaitLatchOrSocket(MyLatch, wakeEvents,
- MyProcPort->sock, sleeptime);
+ MyProcPort->sock, sleeptime,
+ LATCH_WAL_SENDER_WAIT_WAL);
}
/* reactivate latch so WalSndLoop knows to continue */
@@ -1923,7 +1925,8 @@ WalSndLoop(WalSndSendDataCallback send_data)
/* Sleep until something happens or we time out */
WaitLatchOrSocket(MyLatch, wakeEvents,
- MyProcPort->sock, sleeptime);
+ MyProcPort->sock, sleeptime,
+ LATCH_WAL_SENDER_LOOP);
}
}
return;
diff --git a/src/backend/storage/ipc/latch.c b/src/backend/storage/ipc/latch.c
index 3fbe0e5..434a0fd 100644
--- a/src/backend/storage/ipc/latch.c
+++ b/src/backend/storage/ipc/latch.c
@@ -55,6 +55,7 @@
#endif
#include "miscadmin.h"
+#include "pgstat.h"
#include "portability/instr_time.h"
#include "postmaster/postmaster.h"
#include "storage/barrier.h"
@@ -297,9 +298,11 @@ DisownLatch(volatile Latch *latch)
* we return all of them in one call, but we will return at least one.
*/
int
-WaitLatch(volatile Latch *latch, int wakeEvents, long timeout)
+WaitLatch(volatile Latch *latch, int wakeEvents, long timeout,
+ LatchIdentifier eventId)
{
- return WaitLatchOrSocket(latch, wakeEvents, PGINVALID_SOCKET, timeout);
+ return WaitLatchOrSocket(latch, wakeEvents, PGINVALID_SOCKET, timeout,
+ eventId);
}
/*
@@ -316,13 +319,15 @@ WaitLatch(volatile Latch *latch, int wakeEvents, long timeout)
*/
int
WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
- long timeout)
+ long timeout, LatchIdentifier eventId)
{
int ret = 0;
int rc;
WaitEvent event;
WaitEventSet *set = CreateWaitEventSet(CurrentMemoryContext, 3);
+ pgstat_report_wait_start(WAIT_LATCH, (uint16) eventId);
+
if (wakeEvents & WL_TIMEOUT)
Assert(timeout >= 0);
else
@@ -356,6 +361,7 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
WL_SOCKET_WRITEABLE);
}
+ pgstat_report_wait_end();
FreeWaitEventSet(set);
return ret;
@@ -1485,6 +1491,119 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
}
#endif
+
+/*
+ * Return an identifier for a Latch depending on an event for statistics
+ * collector.
+ */
+const char *
+GetLatchIdentifier(uint16 eventId)
+{
+ const char *res;
+
+ switch (eventId)
+ {
+ case LATCH_ARCHIVER_MAIN:
+ res = "ArchiverMain";
+ break;
+ case LATCH_AUTOVACUUM_MAIN:
+ res = "AutoVacuumMain";
+ break;
+ case LATCH_BASEBACKUP_THROTTLE:
+ res = "BaseBackupThrottle";
+ break;
+ case LATCH_BGWORKER_STARTUP:
+ res = "BgWorkerStartup";
+ break;
+ case LATCH_BGWORKER_SHUTDOWN:
+ res = "BgWorkerShutdown";
+ break;
+ case LATCH_BGWRITER_MAIN:
+ res = "BgWriterMain";
+ break;
+ case LATCH_BGWRITER_HIBERNATE:
+ res = "BgWriterHibernate";
+ break;
+ case LATCH_CHECKPOINTER_MAIN:
+ res = "CheckpointerMain";
+ break;
+ case LATCH_EXECUTE_GATHER:
+ res = "ExecuteGather";
+ break;
+ case LATCH_EXTENSION:
+ res = "Extension";
+ break;
+ case LATCH_MQ_PUT_MESSAGE:
+ res = "MessageQueuePutMessage";
+ break;
+ case LATCH_MQ_SEND_BYTES:
+ res = "MessageQueueSend";
+ break;
+ case LATCH_MQ_RECEIVE_BYTES:
+ res = "MessageQueueReceive";
+ break;
+ case LATCH_MQ_WAIT_INTERNAL:
+ res = "MessageQueueInternal";
+ break;
+ case LATCH_PARALLEL_WAIT_FINISH:
+ res = "ParallelFinish";
+ break;
+ case LATCH_PG_SLEEP:
+ res = "PGSleep";
+ break;
+ case LATCH_PGSTAT_MAIN:
+ res = "PGStatMain";
+ break;
+ case LATCH_PROC_SLEEP:
+ res = "ProcSleep";
+ break;
+ case LATCH_PROC_SIGNAL:
+ res = "ProcSignal";
+ break;
+ case LATCH_RECOVERY_APPLY_DELAY:
+ res = "XLogApplyDelay";
+ break;
+ case LATCH_RECOVERY_WAL_STREAM:
+ res = "RecoveryWALStream";
+ break;
+ case LATCH_RECOVERY_WAL_ALL:
+ res = "XLogAfterAvailable";
+ break;
+ case LATCH_SSL_OPEN_SERVER:
+ res = "SSLOpenServer";
+ break;
+ case LATCH_SYNC_REP:
+ res = "SyncRep";
+ break;
+ case LATCH_SYSLOGGER_MAIN:
+ res = "SysLoggerMain";
+ break;
+ case LATCH_WALWRITER_MAIN:
+ res = "WALWriterMain";
+ break;
+ case LATCH_WAL_RECEIVER_WAIT_START:
+ res = "WALSenderWaitStart";
+ break;
+ case LATCH_WAL_RECEIVER_MAIN:
+ res = "WALReceiverMain";
+ break;
+ case LATCH_WAL_SENDER_LOOP:
+ res = "WALSenderMain";
+ break;
+ case LATCH_WAL_SENDER_WAIT_WAL:
+ res = "WALSenderWaitForWAL";
+ break;
+ case LATCH_WAL_SENDER_WRITE_DATA:
+ res = "WALSenderWriteData";
+ break;
+ default:
+ res = "???";
+ }
+
+ return res;
+}
+
+
/*
* SetLatch uses SIGUSR1 to wake up the process waiting on the latch.
*
diff --git a/src/backend/storage/ipc/shm_mq.c b/src/backend/storage/ipc/shm_mq.c
index 7d1c9cd..a9542c2 100644
--- a/src/backend/storage/ipc/shm_mq.c
+++ b/src/backend/storage/ipc/shm_mq.c
@@ -866,7 +866,7 @@ shm_mq_send_bytes(shm_mq_handle *mqh, Size nbytes, const void *data,
* at top of loop, because setting an already-set latch is much
* cheaper than setting one that has been reset.
*/
- WaitLatch(MyLatch, WL_LATCH_SET, 0);
+ WaitLatch(MyLatch, WL_LATCH_SET, 0, LATCH_MQ_SEND_BYTES);
/* An interrupt may have occurred while we were waiting. */
CHECK_FOR_INTERRUPTS();
@@ -963,7 +963,7 @@ shm_mq_receive_bytes(shm_mq *mq, Size bytes_needed, bool nowait,
* loop, because setting an already-set latch is much cheaper than
* setting one that has been reset.
*/
- WaitLatch(MyLatch, WL_LATCH_SET, 0);
+ WaitLatch(MyLatch, WL_LATCH_SET, 0, LATCH_MQ_RECEIVE_BYTES);
/* An interrupt may have occurred while we were waiting. */
CHECK_FOR_INTERRUPTS();
@@ -1062,7 +1062,7 @@ shm_mq_wait_internal(volatile shm_mq *mq, PGPROC *volatile * ptr,
}
/* Wait to be signalled. */
- WaitLatch(MyLatch, WL_LATCH_SET, 0);
+ WaitLatch(MyLatch, WL_LATCH_SET, 0, LATCH_MQ_WAIT_INTERNAL);
/* An interrupt may have occurred while we were waiting. */
CHECK_FOR_INTERRUPTS();
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index a66e07b..8f910d74 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -1216,7 +1216,7 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
}
else
{
- WaitLatch(MyLatch, WL_LATCH_SET, 0);
+ WaitLatch(MyLatch, WL_LATCH_SET, 0, LATCH_PROC_SLEEP);
ResetLatch(MyLatch);
/* check for deadlocks first, as that's probably log-worthy */
if (got_deadlock_timeout)
@@ -1728,7 +1728,7 @@ CheckDeadLockAlert(void)
void
ProcWaitForSignal(void)
{
- WaitLatch(MyLatch, WL_LATCH_SET, 0);
+ WaitLatch(MyLatch, WL_LATCH_SET, 0, LATCH_PROC_SIGNAL);
ResetLatch(MyLatch);
CHECK_FOR_INTERRUPTS();
}
diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c
index a44fa38..36de861 100644
--- a/src/backend/utils/adt/misc.c
+++ b/src/backend/utils/adt/misc.c
@@ -560,7 +560,7 @@ pg_sleep(PG_FUNCTION_ARGS)
(void) WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT,
- delay_ms);
+ delay_ms, LATCH_PG_SLEEP);
ResetLatch(MyLatch);
}
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 4be09fe..80db5ef 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -707,7 +707,8 @@ typedef enum WaitClass
WAIT_LWLOCK_NAMED,
WAIT_LWLOCK_TRANCHE,
WAIT_LOCK,
- WAIT_BUFFER_PIN
+ WAIT_BUFFER_PIN,
+ WAIT_LATCH
} WaitClass;
diff --git a/src/include/storage/latch.h b/src/include/storage/latch.h
index 85d211c..cf2c9e1 100644
--- a/src/include/storage/latch.h
+++ b/src/include/storage/latch.h
@@ -119,6 +119,45 @@ typedef struct WaitEvent
void *user_data; /* pointer provided in AddWaitEventToSet */
} WaitEvent;
+/*
+ * List of latch identifiers used when reporting activity to statistics
+ * collector.
+ */
+typedef enum LatchIdentifier
+{
+ LATCH_ARCHIVER_MAIN,
+ LATCH_AUTOVACUUM_MAIN,
+ LATCH_BASEBACKUP_THROTTLE,
+ LATCH_BGWORKER_STARTUP,
+ LATCH_BGWORKER_SHUTDOWN,
+ LATCH_BGWRITER_MAIN,
+ LATCH_BGWRITER_HIBERNATE,
+ LATCH_CHECKPOINTER_MAIN,
+ LATCH_EXECUTE_GATHER,
+ LATCH_EXTENSION,
+ LATCH_MQ_PUT_MESSAGE,
+ LATCH_MQ_SEND_BYTES,
+ LATCH_MQ_RECEIVE_BYTES,
+ LATCH_MQ_WAIT_INTERNAL,
+ LATCH_PARALLEL_WAIT_FINISH,
+ LATCH_PGSTAT_MAIN,
+ LATCH_PROC_SLEEP,
+ LATCH_PROC_SIGNAL,
+ LATCH_PG_SLEEP,
+ LATCH_SSL_OPEN_SERVER,
+ LATCH_SYNC_REP,
+ LATCH_SYSLOGGER_MAIN,
+ LATCH_RECOVERY_APPLY_DELAY,
+ LATCH_RECOVERY_WAL_ALL,
+ LATCH_RECOVERY_WAL_STREAM,
+ LATCH_WAL_RECEIVER_WAIT_START,
+ LATCH_WAL_RECEIVER_MAIN,
+ LATCH_WAL_SENDER_WRITE_DATA,
+ LATCH_WAL_SENDER_LOOP,
+ LATCH_WAL_SENDER_WAIT_WAL,
+ LATCH_WALWRITER_MAIN,
+} LatchIdentifier;
+
/* forward declaration to avoid exposing latch.c implementation details */
typedef struct WaitEventSet WaitEventSet;
@@ -140,9 +179,11 @@ extern int AddWaitEventToSet(WaitEventSet *set, uint32 events, pgsocket fd,
extern void ModifyWaitEvent(WaitEventSet *set, int pos, uint32 events, Latch *latch);
extern int WaitEventSetWait(WaitEventSet *set, long timeout, WaitEvent *occurred_events, int nevents);
-extern int WaitLatch(volatile Latch *latch, int wakeEvents, long timeout);
+extern int WaitLatch(volatile Latch *latch, int wakeEvents, long timeout,
+ LatchIdentifier eventId);
extern int WaitLatchOrSocket(volatile Latch *latch, int wakeEvents,
- pgsocket sock, long timeout);
+ pgsocket sock, long timeout, LatchIdentifier eventId);
+extern const char *GetLatchIdentifier(uint16 eventId);
/*
* Unix implementation uses SIGUSR1 for inter-process signaling.
diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c
index 5bd2820..2fd4e24 100644
--- a/src/test/modules/test_shm_mq/setup.c
+++ b/src/test/modules/test_shm_mq/setup.c
@@ -279,7 +279,7 @@ wait_for_workers_to_become_ready(worker_state *wstate,
}
/* Wait to be signalled. */
- WaitLatch(MyLatch, WL_LATCH_SET, 0);
+ WaitLatch(MyLatch, WL_LATCH_SET, 0, LATCH_EXTENSION);
/* An interrupt may have occurred while we were waiting. */
CHECK_FOR_INTERRUPTS();
diff --git a/src/test/modules/test_shm_mq/test.c b/src/test/modules/test_shm_mq/test.c
index 6948e20..a89a52a 100644
--- a/src/test/modules/test_shm_mq/test.c
+++ b/src/test/modules/test_shm_mq/test.c
@@ -230,7 +230,7 @@ test_shm_mq_pipelined(PG_FUNCTION_ARGS)
* have read or written data and therefore there may now be work
* for us to do.
*/
- WaitLatch(MyLatch, WL_LATCH_SET, 0);
+ WaitLatch(MyLatch, WL_LATCH_SET, 0, LATCH_EXTENSION);
CHECK_FOR_INTERRUPTS();
ResetLatch(MyLatch);
}
diff --git a/src/test/modules/worker_spi/worker_spi.c b/src/test/modules/worker_spi/worker_spi.c
index 314e371..af4549a 100644
--- a/src/test/modules/worker_spi/worker_spi.c
+++ b/src/test/modules/worker_spi/worker_spi.c
@@ -227,7 +227,8 @@ worker_spi_main(Datum main_arg)
*/
rc = WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- worker_spi_naptime * 1000L);
+ worker_spi_naptime * 1000L,
+ LATCH_EXTENSION);
ResetLatch(MyLatch);
/* emergency bailout if postmaster has died */