#include "access/xact.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
+#include "pgstat.h"
#include "storage/latch.h"
#include "utils/hsearch.h"
#include "utils/memutils.h"
wc = WaitLatchOrSocket(MyLatch,
WL_LATCH_SET | WL_SOCKET_READABLE,
PQsocket(conn),
- -1L);
+ -1L, WAIT_EXTENSION);
ResetLatch(MyLatch);
CHECK_FOR_INTERRUPTS();
buffer in question.
</para>
</listitem>
+ <listitem>
+ <para>
+ <literal>Activity</>: The server process is idle. This is used by
+ system processes waiting for activity in their main processing loop.
+ <literal>wait_event</> will identify the specific wait point.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>Extension</>: The server process is waiting for activity
+ in an extension module. This category is useful for modules to
+ track custom waiting points.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>Client</>: The server process is waiting for some activity
+ on a socket from user applications, and that the server expects
+ something to happen that is independent from its internal processes.
+ <literal>wait_event</> will identify the specific wait point.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>IPC</>: The server process is waiting for some activity
+ from another process in the server. <literal>wait_event</> will
+ identify the specific wait point.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>Timeout</>: The server process is waiting for a timeout
+ to expire. <literal>wait_event</> will identify the specific wait
+ point.
+ </para>
+ </listitem>
</itemizedlist>
</entry>
</row>
<entry><literal>BufferPin</></entry>
<entry>Waiting to acquire a pin on a buffer.</entry>
</row>
+ <row>
+ <entry morerows="11"><literal>Activity</></entry>
+ <entry><literal>ArchiverMain</></entry>
+ <entry>Waiting in main loop of the archiver process.</entry>
+ </row>
+ <row>
+ <entry><literal>AutoVacuumMain</></entry>
+ <entry>Waiting in main loop of autovacuum launcher process.</entry>
+ </row>
+ <row>
+ <entry><literal>BgWriterHibernate</></entry>
+ <entry>Waiting in background writer process, hibernating.</entry>
+ </row>
+ <row>
+ <entry><literal>BgWriterMain</></entry>
+ <entry>Waiting in main loop of background writer process background worker.</entry>
+ </row>
+ <row>
+ <entry><literal>CheckpointerMain</></entry>
+ <entry>Waiting in main loop of checkpointer process.</entry>
+ </row>
+ <row>
+ <entry><literal>PgStatMain</></entry>
+ <entry>Waiting in main loop of the statistics collector process.</entry>
+ </row>
+ <row>
+ <entry><literal>RecoveryWalAll</></entry>
+ <entry>Waiting for WAL from any kind of source (local, archive or stream) at recovery.</entry>
+ </row>
+ <row>
+ <entry><literal>RecoveryWalStream</></entry>
+ <entry>Waiting for WAL from a stream at recovery.</entry>
+ </row>
+ <row>
+ <entry><literal>SysLoggerMain</></entry>
+ <entry>Waiting in main loop of syslogger process.</entry>
+ </row>
+ <row>
+ <entry><literal>WalReceiverMain</></entry>
+ <entry>Waiting in main loop of WAL receiver process.</entry>
+ </row>
+ <row>
+ <entry><literal>WalSenderMain</></entry>
+ <entry>Waiting in main loop of WAL sender process.</entry>
+ </row>
+ <row>
+ <entry><literal>WalWriterMain</></entry>
+ <entry>Waiting in main loop of WAL writer process.</entry>
+ </row>
+ <row>
+ <entry morerows="5"><literal>Client</></entry>
+ <entry><literal>ClientRead</></entry>
+ <entry>Waiting to read data from the client.</entry>
+ </row>
+ <row>
+ <entry><literal>ClientWrite</></entry>
+ <entry>Waiting to write data from the client.</entry>
+ </row>
+ <row>
+ <entry><literal>SSLOpenServer</></entry>
+ <entry>Waiting for SSL while attempting connection.</entry>
+ </row>
+ <row>
+ <entry><literal>WalReceiverWaitStart</></entry>
+ <entry>Waiting for startup process to send initial data for streaming replication.</entry>
+ </row>
+ <row>
+ <entry><literal>WalSenderWaitForWAL</></entry>
+ <entry>Waiting for WAL to be flushed in WAL sender process.</entry>
+ </row>
+ <row>
+ <entry><literal>WalSenderWriteData</></entry>
+ <entry>Waiting for any activity when processing replies from WAL receiver in WAL sender process.</entry>
+ </row>
+ <row>
+ <entry><literal>Extension</></entry>
+ <entry><literal>Extension</></entry>
+ <entry>Waiting in an extension.</entry>
+ </row>
+ <row>
+ <entry morerows="9"><literal>IPC</></entry>
+ <entry><literal>BgWorkerShutdown</></entry>
+ <entry>Waiting for background worker to shut down.</entry>
+ </row>
+ <row>
+ <entry><literal>BgWorkerStartup</></entry>
+ <entry>Waiting for background worker to start up.</entry>
+ </row>
+ <row>
+ <entry><literal>ExecuteGather</></entry>
+ <entry>Waiting for activity from child process when executing <literal>Gather</> node.</entry>
+ </row>
+ <row>
+ <entry><literal>MessageQueueInternal</></entry>
+ <entry>Waiting for other process to be attached in shared message queue.</entry>
+ </row>
+ <row>
+ <entry><literal>MessageQueuePutMessage</></entry>
+ <entry>Waiting to write a protoocol message to a shared message queue.</entry>
+ </row>
+ <row>
+ <entry><literal>MessageQueueReceive</></entry>
+ <entry>Waiting to receive bytes from a shared message queue.</entry>
+ </row>
+ <row>
+ <entry><literal>MessageQueueSend</></entry>
+ <entry>Waiting to send bytes to a shared message queue.</entry>
+ </row>
+ <row>
+ <entry><literal>ParallelFinish</></entry>
+ <entry>Waiting for parallel workers to finish computing.</entry>
+ </row>
+ <row>
+ <entry><literal>SafeSnapshot</></entry>
+ <entry>Waiting for a snapshot for a <literal>READ ONLY DEFERRABLE</> transaction.</entry>
+ </row>
+ <row>
+ <entry><literal>SyncRep</></entry>
+ <entry>Waiting for confirmation from remote server during synchronous replication.</entry>
+ </row>
+ <row>
+ <entry morerows="2"><literal>Timeout</></entry>
+ <entry><literal>BaseBackupThrottle</></entry>
+ <entry>Waiting during base backup when throttling activity.</entry>
+ </row>
+ <row>
+ <entry><literal>PgSleep</></entry>
+ <entry>Waiting in process that called <function>pg_sleep</>.</entry>
+ </row>
+ <row>
+ <entry><literal>RecoveryApplyDelay</></entry>
+ <entry>Waiting to apply WAL at recovery because it is delayed.</entry>
+ </row>
</tbody>
</tgroup>
</table>
#include "libpq/pqmq.h"
#include "miscadmin.h"
#include "optimizer/planmain.h"
+#include "pgstat.h"
#include "storage/ipc.h"
#include "storage/sinval.h"
#include "storage/spin.h"
if (!anyone_alive)
break;
- WaitLatch(&MyProc->procLatch, WL_LATCH_SET, -1);
+ WaitLatch(&MyProc->procLatch, WL_LATCH_SET, -1,
+ WAIT_EVENT_PARALLEL_FINISH);
ResetLatch(&MyProc->procLatch);
}
WaitLatch(&XLogCtl->recoveryWakeupLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- secs * 1000L + microsecs / 1000);
+ secs * 1000L + microsecs / 1000,
+ WAIT_EVENT_RECOVERY_APPLY_DELAY);
}
return true;
}
WaitLatch(&XLogCtl->recoveryWakeupLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- wait_time);
+ wait_time, WAIT_EVENT_RECOVERY_WAL_STREAM);
ResetLatch(&XLogCtl->recoveryWakeupLatch);
now = GetCurrentTimestamp();
}
*/
WaitLatch(&XLogCtl->recoveryWakeupLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- 5000L);
+ 5000L, WAIT_EVENT_RECOVERY_WAL_ALL);
ResetLatch(&XLogCtl->recoveryWakeupLatch);
break;
}
#include "executor/nodeSubplan.h"
#include "executor/tqueue.h"
#include "miscadmin.h"
+#include "pgstat.h"
#include "utils/memutils.h"
#include "utils/rel.h"
return NULL;
/* Nothing to do except wait for developments. */
- WaitLatch(MyLatch, WL_LATCH_SET, 0);
+ WaitLatch(MyLatch, WL_LATCH_SET, 0, WAIT_EVENT_EXECUTE_GATHER);
ResetLatch(MyLatch);
nvisited = 0;
}
#include "libpq/libpq.h"
#include "miscadmin.h"
+#include "pgstat.h"
#include "storage/latch.h"
#include "tcop/tcopprot.h"
#include "utils/memutils.h"
else
waitfor = WL_SOCKET_WRITEABLE;
- WaitLatchOrSocket(MyLatch, waitfor, port->sock, 0);
+ WaitLatchOrSocket(MyLatch, waitfor, port->sock, 0,
+ WAIT_EVENT_SSL_OPEN_SERVER);
goto aloop;
case SSL_ERROR_SYSCALL:
if (r < 0)
#include "libpq/libpq.h"
#include "miscadmin.h"
+#include "pgstat.h"
#include "tcop/tcopprot.h"
#include "utils/memutils.h"
#include "storage/ipc.h"
ModifyWaitEvent(FeBeWaitSet, 0, waitfor, NULL);
- WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1);
+ WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1,
+ WAIT_EVENT_CLIENT_READ);
/*
* If the postmaster has died, it's not safe to continue running,
ModifyWaitEvent(FeBeWaitSet, 0, waitfor, NULL);
- WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1);
+ WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1,
+ WAIT_EVENT_CLIENT_WRITE);
/* See comments in secure_read. */
if (event.events & WL_POSTMASTER_DEATH)
#include "libpq/pqformat.h"
#include "libpq/pqmq.h"
#include "miscadmin.h"
+#include "pgstat.h"
#include "tcop/tcopprot.h"
#include "utils/builtins.h"
if (result != SHM_MQ_WOULD_BLOCK)
break;
- WaitLatch(&MyProc->procLatch, WL_LATCH_SET, 0);
+ WaitLatch(&MyProc->procLatch, WL_LATCH_SET, 0,
+ WAIT_EVENT_MQ_PUT_MESSAGE);
ResetLatch(&MyProc->procLatch);
CHECK_FOR_INTERRUPTS();
}
*/
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),
+ WAIT_EVENT_AUTOVACUUM_MAIN);
ResetLatch(MyLatch);
#include "libpq/pqsignal.h"
#include "postmaster/bgworker_internals.h"
#include "postmaster/postmaster.h"
+#include "pgstat.h"
#include "storage/barrier.h"
#include "storage/dsm.h"
#include "storage/ipc.h"
break;
rc = WaitLatch(MyLatch,
- WL_LATCH_SET | WL_POSTMASTER_DEATH, 0);
+ WL_LATCH_SET | WL_POSTMASTER_DEATH, 0,
+ WAIT_EVENT_BGWORKER_STARTUP);
if (rc & WL_POSTMASTER_DEATH)
{
break;
rc = WaitLatch(&MyProc->procLatch,
- WL_LATCH_SET | WL_POSTMASTER_DEATH, 0);
+ WL_LATCH_SET | WL_POSTMASTER_DEATH, 0,
+ WAIT_EVENT_BGWORKER_SHUTDOWN);
if (rc & WL_POSTMASTER_DEATH)
{
*/
rc = WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- BgWriterDelay /* ms */ );
+ BgWriterDelay /* ms */, WAIT_EVENT_BGWRITER_MAIN);
/*
* If no latch event and BgBufferSync says nothing's happening, extend
/* Sleep ... */
rc = WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- BgWriterDelay * HIBERNATE_FACTOR);
+ BgWriterDelay * HIBERNATE_FACTOR,
+ WAIT_EVENT_BGWRITER_HIBERNATE);
/* Reset the notification request in case we timed out */
StrategyNotifyBgWriter(-1);
}
rc = WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- cur_timeout * 1000L /* convert to ms */ );
+ cur_timeout * 1000L /* convert to ms */,
+ WAIT_EVENT_CHECKPOINTER_MAIN);
/*
* Emergency bailout if postmaster has died. This is to avoid the
rc = WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- timeout * 1000L);
+ timeout * 1000L,
+ WAIT_EVENT_ARCHIVER_MAIN);
if (rc & WL_TIMEOUT)
wakened = true;
}
static void pgstat_setup_memcxt(void);
+static const char *pgstat_get_wait_activity(WaitEventActivity w);
+static const char *pgstat_get_wait_client(WaitEventClient w);
+static const char *pgstat_get_wait_ipc(WaitEventIPC w);
+static const char *pgstat_get_wait_timeout(WaitEventTimeout w);
+
static void pgstat_setheader(PgStat_MsgHdr *hdr, StatMsgType mtype);
static void pgstat_send(void *msg, int len);
const char *
pgstat_get_wait_event_type(uint32 wait_event_info)
{
- uint8 classId;
+ uint32 classId;
const char *event_type;
/* report process as not waiting. */
if (wait_event_info == 0)
return NULL;
- wait_event_info = wait_event_info >> 24;
- classId = wait_event_info & 0XFF;
+ classId = wait_event_info & 0xFF000000;
switch (classId)
{
case WAIT_BUFFER_PIN:
event_type = "BufferPin";
break;
+ case WAIT_ACTIVITY:
+ event_type = "Activity";
+ break;
+ case WAIT_CLIENT:
+ event_type = "Client";
+ break;
+ case WAIT_EXTENSION:
+ event_type = "Extension";
+ break;
+ case WAIT_IPC:
+ event_type = "IPC";
+ break;
+ case WAIT_TIMEOUT:
+ event_type = "Timeout";
+ break;
default:
event_type = "???";
break;
const char *
pgstat_get_wait_event(uint32 wait_event_info)
{
- uint8 classId;
+ uint32 classId;
uint16 eventId;
const char *event_name;
if (wait_event_info == 0)
return NULL;
- eventId = wait_event_info & ((1 << 24) - 1);
- wait_event_info = wait_event_info >> 24;
- classId = wait_event_info & 0XFF;
+ classId = wait_event_info & 0xFF000000;
+ eventId = wait_event_info & 0x0000FFFF;
switch (classId)
{
case WAIT_BUFFER_PIN:
event_name = "BufferPin";
break;
+ case WAIT_ACTIVITY:
+ {
+ WaitEventActivity w = (WaitEventActivity) wait_event_info;
+
+ event_name = pgstat_get_wait_activity(w);
+ break;
+ }
+ case WAIT_CLIENT:
+ {
+ WaitEventClient w = (WaitEventClient) wait_event_info;
+
+ event_name = pgstat_get_wait_client(w);
+ break;
+ }
+ case WAIT_EXTENSION:
+ event_name = "Extension";
+ break;
+ case WAIT_IPC:
+ {
+ WaitEventIPC w = (WaitEventIPC) wait_event_info;
+
+ event_name = pgstat_get_wait_ipc(w);
+ break;
+ }
+ case WAIT_TIMEOUT:
+ {
+ WaitEventTimeout w = (WaitEventTimeout) wait_event_info;
+
+ event_name = pgstat_get_wait_timeout(w);
+ break;
+ }
default:
event_name = "unknown wait event";
break;
return event_name;
}
+/* ----------
+ * pgstat_get_wait_activity() -
+ *
+ * Convert WaitEventActivity to string.
+ * ----------
+ */
+static const char *
+pgstat_get_wait_activity(WaitEventActivity w)
+{
+ const char *event_name = "unknown wait event";
+
+ switch (w)
+ {
+ case WAIT_EVENT_ARCHIVER_MAIN:
+ event_name = "ArchiverMain";
+ break;
+ case WAIT_EVENT_AUTOVACUUM_MAIN:
+ event_name = "AutoVacuumMain";
+ break;
+ case WAIT_EVENT_BGWRITER_HIBERNATE:
+ event_name = "BgWriterHibernate";
+ break;
+ case WAIT_EVENT_BGWRITER_MAIN:
+ event_name = "BgWriterMain";
+ break;
+ case WAIT_EVENT_CHECKPOINTER_MAIN:
+ event_name = "CheckpointerMain";
+ break;
+ case WAIT_EVENT_PGSTAT_MAIN:
+ event_name = "PgStatMain";
+ break;
+ case WAIT_EVENT_RECOVERY_WAL_ALL:
+ event_name = "RecoveryWalAll";
+ break;
+ case WAIT_EVENT_RECOVERY_WAL_STREAM:
+ event_name = "RecoveryWalStream";
+ break;
+ case WAIT_EVENT_SYSLOGGER_MAIN:
+ event_name = "SysLoggerMain";
+ break;
+ case WAIT_EVENT_WAL_RECEIVER_MAIN:
+ event_name = "WalReceiverMain";
+ break;
+ case WAIT_EVENT_WAL_SENDER_MAIN:
+ event_name = "WalSenderMain";
+ break;
+ case WAIT_EVENT_WAL_WRITER_MAIN:
+ event_name = "WalWriterMain";
+ break;
+ /* no default case, so that compiler will warn */
+ }
+
+ return event_name;
+}
+
+/* ----------
+ * pgstat_get_wait_client() -
+ *
+ * Convert WaitEventClient to string.
+ * ----------
+ */
+static const char *
+pgstat_get_wait_client(WaitEventClient w)
+{
+ const char *event_name = "unknown wait event";
+
+ switch (w)
+ {
+ case WAIT_EVENT_CLIENT_READ:
+ event_name = "ClientRead";
+ break;
+ case WAIT_EVENT_CLIENT_WRITE:
+ event_name = "ClientWrite";
+ break;
+ case WAIT_EVENT_SSL_OPEN_SERVER:
+ event_name = "SSLOpenServer";
+ break;
+ case WAIT_EVENT_WAL_RECEIVER_WAIT_START:
+ event_name = "WalReceiverWaitStart";
+ break;
+ case WAIT_EVENT_WAL_SENDER_WAIT_WAL:
+ event_name = "WalSenderWaitForWAL";
+ break;
+ case WAIT_EVENT_WAL_SENDER_WRITE_DATA:
+ event_name = "WalSenderWriteData";
+ break;
+ /* no default case, so that compiler will warn */
+ }
+
+ return event_name;
+}
+
+/* ----------
+ * pgstat_get_wait_ipc() -
+ *
+ * Convert WaitEventIPC to string.
+ * ----------
+ */
+static const char *
+pgstat_get_wait_ipc(WaitEventIPC w)
+{
+ const char *event_name = "unknown wait event";
+
+ switch (w)
+ {
+ case WAIT_EVENT_BGWORKER_SHUTDOWN:
+ event_name = "BgWorkerShutdown";
+ break;
+ case WAIT_EVENT_BGWORKER_STARTUP:
+ event_name = "BgWorkerStartup";
+ break;
+ case WAIT_EVENT_EXECUTE_GATHER:
+ event_name = "ExecuteGather";
+ break;
+ case WAIT_EVENT_MQ_INTERNAL:
+ event_name = "MessageQueueInternal";
+ break;
+ case WAIT_EVENT_MQ_PUT_MESSAGE:
+ event_name = "MessageQueuePutMessage";
+ break;
+ case WAIT_EVENT_MQ_RECEIVE:
+ event_name = "MessageQueueReceive";
+ break;
+ case WAIT_EVENT_MQ_SEND:
+ event_name = "MessageQueueSend";
+ break;
+ case WAIT_EVENT_PARALLEL_FINISH:
+ event_name = "ParallelFinish";
+ break;
+ case WAIT_EVENT_SAFE_SNAPSHOT:
+ event_name = "SafeSnapshot";
+ break;
+ case WAIT_EVENT_SYNC_REP:
+ event_name = "SyncRep";
+ break;
+ /* no default case, so that compiler will warn */
+ }
+
+ return event_name;
+}
+
+/* ----------
+ * pgstat_get_wait_timeout() -
+ *
+ * Convert WaitEventTimeout to string.
+ * ----------
+ */
+static const char *
+pgstat_get_wait_timeout(WaitEventTimeout w)
+{
+ const char *event_name = "unknown wait event";
+
+ switch (w)
+ {
+ case WAIT_EVENT_BASE_BACKUP_THROTTLE:
+ event_name = "BaseBackupThrottle";
+ break;
+ case WAIT_EVENT_PG_SLEEP:
+ event_name = "PgSleep";
+ break;
+ case WAIT_EVENT_RECOVERY_APPLY_DELAY:
+ event_name = "RecoveryApplyDelay";
+ break;
+ /* no default case, so that compiler will warn */
+ }
+
+ return event_name;
+}
+
/* ----------
* pgstat_get_backend_current_activity() -
*
#ifndef WIN32
wr = WaitLatchOrSocket(MyLatch,
WL_LATCH_SET | WL_POSTMASTER_DEATH | WL_SOCKET_READABLE,
- pgStatSock,
- -1L);
+ pgStatSock, -1L,
+ WAIT_EVENT_PGSTAT_MAIN);
#else
/*
#include "libpq/pqsignal.h"
#include "miscadmin.h"
#include "nodes/pg_list.h"
+#include "pgstat.h"
#include "pgtime.h"
#include "postmaster/fork_process.h"
#include "postmaster/postmaster.h"
rc = WaitLatchOrSocket(MyLatch,
WL_LATCH_SET | WL_SOCKET_READABLE | cur_flags,
syslogPipe[0],
- cur_timeout);
+ cur_timeout,
+ WAIT_EVENT_SYSLOGGER_MAIN);
if (rc & WL_SOCKET_READABLE)
{
rc = WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- cur_timeout);
+ cur_timeout,
+ WAIT_EVENT_WAL_WRITER_MAIN);
/*
* Emergency bailout if postmaster has died. This is to avoid the
*/
wait_result = WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- (long) (sleep / 1000));
+ (long) (sleep / 1000),
+ WAIT_EVENT_BASE_BACKUP_THROTTLE);
if (wait_result & WL_LATCH_SET)
CHECK_FOR_INTERRUPTS();
#include "access/xact.h"
#include "miscadmin.h"
+#include "pgstat.h"
#include "replication/syncrep.h"
#include "replication/walsender.h"
#include "replication/walsender_private.h"
* 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,
+ WAIT_EVENT_SYNC_REP);
}
/*
#include "libpq/pqformat.h"
#include "libpq/pqsignal.h"
#include "miscadmin.h"
+#include "pgstat.h"
#include "replication/walreceiver.h"
#include "replication/walsender.h"
#include "storage/ipc.h"
WL_POSTMASTER_DEATH | WL_SOCKET_READABLE |
WL_TIMEOUT | WL_LATCH_SET,
wait_fd,
- NAPTIME_PER_CYCLE);
+ NAPTIME_PER_CYCLE,
+ WAIT_EVENT_WAL_RECEIVER_MAIN);
if (rc & WL_LATCH_SET)
{
ResetLatch(&walrcv->latch);
}
SpinLockRelease(&walrcv->mutex);
- WaitLatch(&walrcv->latch, WL_LATCH_SET | WL_POSTMASTER_DEATH, 0);
+ WaitLatch(&walrcv->latch, WL_LATCH_SET | WL_POSTMASTER_DEATH, 0,
+ WAIT_EVENT_WAL_RECEIVER_WAIT_START);
}
if (update_process_title)
/* Sleep until something happens or we time out */
WaitLatchOrSocket(MyLatch, wakeEvents,
- MyProcPort->sock, sleeptime);
+ MyProcPort->sock, sleeptime,
+ WAIT_EVENT_WAL_SENDER_WRITE_DATA);
}
/* reactivate latch so WalSndLoop knows to continue */
/* Sleep until something happens or we time out */
WaitLatchOrSocket(MyLatch, wakeEvents,
- MyProcPort->sock, sleeptime);
+ MyProcPort->sock, sleeptime,
+ WAIT_EVENT_WAL_SENDER_WAIT_WAL);
}
/* reactivate latch so WalSndLoop knows to continue */
/* Sleep until something happens or we time out */
WaitLatchOrSocket(MyLatch, wakeEvents,
- MyProcPort->sock, sleeptime);
+ MyProcPort->sock, sleeptime,
+ WAIT_EVENT_WAL_SENDER_MAIN);
}
}
return;
UnlockBufHdr(bufHdr, buf_state);
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
- /* Report the wait */
- pgstat_report_wait_start(WAIT_BUFFER_PIN, 0);
-
/* Wait to be signaled by UnpinBuffer() */
if (InHotStandby)
{
SetStartupBufferPinWaitBufId(-1);
}
else
- ProcWaitForSignal();
-
- pgstat_report_wait_end();
+ ProcWaitForSignal(WAIT_BUFFER_PIN);
/*
* Remove flag marking us as waiter. Normally this will not be set
#endif
#include "miscadmin.h"
+#include "pgstat.h"
#include "portability/instr_time.h"
#include "postmaster/postmaster.h"
#include "storage/barrier.h"
* 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,
+ uint32 wait_event_info)
{
- return WaitLatchOrSocket(latch, wakeEvents, PGINVALID_SOCKET, timeout);
+ return WaitLatchOrSocket(latch, wakeEvents, PGINVALID_SOCKET, timeout,
+ wait_event_info);
}
/*
*/
int
WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
- long timeout)
+ long timeout, uint32 wait_event_info)
{
int ret = 0;
int rc;
AddWaitEventToSet(set, ev, sock, NULL, NULL);
}
- rc = WaitEventSetWait(set, timeout, &event, 1);
+ rc = WaitEventSetWait(set, timeout, &event, 1, wait_event_info);
if (rc == 0)
ret |= WL_TIMEOUT;
*/
int
WaitEventSetWait(WaitEventSet *set, long timeout,
- WaitEvent *occurred_events, int nevents)
+ WaitEvent *occurred_events, int nevents,
+ uint32 wait_event_info)
{
int returned_events = 0;
instr_time start_time;
cur_timeout = timeout;
}
+ pgstat_report_wait_start(wait_event_info);
+
#ifndef WIN32
waiting = true;
#else
waiting = false;
#endif
+ pgstat_report_wait_end();
+
return returned_events;
}
#include "postgres.h"
#include "miscadmin.h"
+#include "pgstat.h"
#include "postmaster/bgworker.h"
#include "storage/procsignal.h"
#include "storage/shm_mq.h"
* 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, WAIT_EVENT_MQ_SEND);
/* Reset the latch so we don't spin. */
ResetLatch(MyLatch);
* 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, WAIT_EVENT_MQ_RECEIVE);
/* Reset the latch so we don't spin. */
ResetLatch(MyLatch);
}
/* Wait to be signalled. */
- WaitLatch(MyLatch, WL_LATCH_SET, 0);
+ WaitLatch(MyLatch, WL_LATCH_SET, 0, WAIT_EVENT_MQ_INTERNAL);
/* Reset the latch so we don't spin. */
ResetLatch(MyLatch);
#include "access/xlog.h"
#include "access/xloginsert.h"
#include "miscadmin.h"
+#include "pgstat.h"
#include "storage/bufmgr.h"
#include "storage/lmgr.h"
#include "storage/proc.h"
}
/* Wait to be signaled by the release of the Relation Lock */
- ProcWaitForSignal();
+ ProcWaitForSignal(WAIT_LOCK | locktag.locktag_type);
/*
* Clear any timeout requests established above. We assume here that the
}
/* Wait to be signaled by UnpinBuffer() */
- ProcWaitForSignal();
+ ProcWaitForSignal(WAIT_BUFFER_PIN);
/*
* Clear any timeout requests established above. We assume here that the
set_ps_display(new_status, false);
new_status[len] = '\0'; /* truncate off " waiting" */
}
- pgstat_report_wait_start(WAIT_LOCK, locallock->tag.lock.locktag_type);
awaitedLock = locallock;
awaitedOwner = owner;
/* In this path, awaitedLock remains set until LockErrorCleanup */
/* Report change to non-waiting status */
- pgstat_report_wait_end();
if (update_process_title)
{
set_ps_display(new_status, false);
awaitedLock = NULL;
/* Report change to non-waiting status */
- pgstat_report_wait_end();
if (update_process_title)
{
set_ps_display(new_status, false);
int lockId = T_ID(lock);
if (lock->tranche == 0)
- pgstat_report_wait_start(WAIT_LWLOCK_NAMED, (uint16) lockId);
+ pgstat_report_wait_start(WAIT_LWLOCK_NAMED | (uint16) lockId);
else
- pgstat_report_wait_start(WAIT_LWLOCK_TRANCHE, lock->tranche);
+ pgstat_report_wait_start(WAIT_LWLOCK_TRANCHE | lock->tranche);
}
/*
* Return an identifier for an LWLock based on the wait class and event.
*/
const char *
-GetLWLockIdentifier(uint8 classId, uint16 eventId)
+GetLWLockIdentifier(uint32 classId, uint16 eventId)
{
if (classId == WAIT_LWLOCK_NAMED)
return MainLWLockNames[eventId];
#include "access/xact.h"
#include "access/xlog.h"
#include "miscadmin.h"
+#include "pgstat.h"
#include "storage/bufmgr.h"
#include "storage/predicate.h"
#include "storage/predicate_internals.h"
SxactIsROUnsafe(MySerializableXact)))
{
LWLockRelease(SerializableXactHashLock);
- ProcWaitForSignal();
+ ProcWaitForSignal(WAIT_EVENT_SAFE_SNAPSHOT);
LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
}
MySerializableXact->flags &= ~SXACT_FLAG_DEFERRABLE_WAITING;
#include "access/twophase.h"
#include "access/xact.h"
#include "miscadmin.h"
+#include "pgstat.h"
#include "postmaster/autovacuum.h"
#include "replication/slot.h"
#include "replication/syncrep.h"
}
else
{
- WaitLatch(MyLatch, WL_LATCH_SET, 0);
+ WaitLatch(MyLatch, WL_LATCH_SET, 0,
+ WAIT_LOCK | locallock->tag.lock.locktag_type);
ResetLatch(MyLatch);
/* check for deadlocks first, as that's probably log-worthy */
if (got_deadlock_timeout)
* wait again if not.
*/
void
-ProcWaitForSignal(void)
+ProcWaitForSignal(uint32 wait_event_info)
{
- WaitLatch(MyLatch, WL_LATCH_SET, 0);
+ WaitLatch(MyLatch, WL_LATCH_SET, 0, wait_event_info);
ResetLatch(MyLatch);
CHECK_FOR_INTERRUPTS();
}
#include "common/keywords.h"
#include "funcapi.h"
#include "miscadmin.h"
+#include "pgstat.h"
#include "parser/scansup.h"
#include "postmaster/syslogger.h"
#include "rewrite/rewriteHandler.h"
(void) WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT,
- delay_ms);
+ delay_ms,
+ WAIT_EVENT_PG_SLEEP);
ResetLatch(MyLatch);
}
* Wait Classes
* ----------
*/
-typedef enum WaitClass
+#define WAIT_LWLOCK_NAMED 0x01000000U
+#define WAIT_LWLOCK_TRANCHE 0x02000000U
+#define WAIT_LOCK 0x03000000U
+#define WAIT_BUFFER_PIN 0x04000000U
+#define WAIT_ACTIVITY 0x05000000U
+#define WAIT_CLIENT 0x06000000U
+#define WAIT_EXTENSION 0x07000000U
+#define WAIT_IPC 0x08000000U
+#define WAIT_TIMEOUT 0x09000000U
+
+/* ----------
+ * Wait Events - Activity
+ *
+ * Use this category when a process is waiting because it has no work to do,
+ * unless the "Client" or "Timeout" category describes the situation better.
+ * Typically, this should only be used for background processes.
+ * ----------
+ */
+typedef enum
{
- WAIT_UNDEFINED,
- WAIT_LWLOCK_NAMED,
- WAIT_LWLOCK_TRANCHE,
- WAIT_LOCK,
- WAIT_BUFFER_PIN
-} WaitClass;
+ WAIT_EVENT_ARCHIVER_MAIN = WAIT_ACTIVITY,
+ WAIT_EVENT_AUTOVACUUM_MAIN,
+ WAIT_EVENT_BGWRITER_HIBERNATE,
+ WAIT_EVENT_BGWRITER_MAIN,
+ WAIT_EVENT_CHECKPOINTER_MAIN,
+ WAIT_EVENT_PGSTAT_MAIN,
+ WAIT_EVENT_RECOVERY_WAL_ALL,
+ WAIT_EVENT_RECOVERY_WAL_STREAM,
+ WAIT_EVENT_SYSLOGGER_MAIN,
+ WAIT_EVENT_WAL_RECEIVER_MAIN,
+ WAIT_EVENT_WAL_SENDER_MAIN,
+ WAIT_EVENT_WAL_WRITER_MAIN,
+} WaitEventActivity;
+/* ----------
+ * Wait Events - Client
+ *
+ * Use this category when a process is waiting to send data to or receive data
+ * from the frontend process to which it is connected. This is never used for
+ * a background process, which has no client connection.
+ * ----------
+ */
+typedef enum
+{
+ WAIT_EVENT_CLIENT_READ = WAIT_CLIENT,
+ WAIT_EVENT_CLIENT_WRITE,
+ WAIT_EVENT_SSL_OPEN_SERVER,
+ WAIT_EVENT_WAL_RECEIVER_WAIT_START,
+ WAIT_EVENT_WAL_SENDER_WAIT_WAL,
+ WAIT_EVENT_WAL_SENDER_WRITE_DATA,
+} WaitEventClient;
+
+/* ----------
+ * Wait Events - IPC
+ *
+ * Use this category when a process cannot complete the work it is doing because
+ * it is waiting for a notification from another process.
+ * ----------
+ */
+typedef enum
+{
+ WAIT_EVENT_BGWORKER_SHUTDOWN = WAIT_IPC,
+ WAIT_EVENT_BGWORKER_STARTUP,
+ WAIT_EVENT_EXECUTE_GATHER,
+ WAIT_EVENT_MQ_INTERNAL,
+ WAIT_EVENT_MQ_PUT_MESSAGE,
+ WAIT_EVENT_MQ_RECEIVE,
+ WAIT_EVENT_MQ_SEND,
+ WAIT_EVENT_PARALLEL_FINISH,
+ WAIT_EVENT_SAFE_SNAPSHOT,
+ WAIT_EVENT_SYNC_REP
+} WaitEventIPC;
+
+/* ----------
+ * Wait Events - Timeout
+ *
+ * Use this category when a process is waiting for a timeout to expire.
+ * ----------
+ */
+typedef enum
+{
+ WAIT_EVENT_BASE_BACKUP_THROTTLE = WAIT_TIMEOUT,
+ WAIT_EVENT_PG_SLEEP,
+ WAIT_EVENT_RECOVERY_APPLY_DELAY
+} WaitEventTimeout;
/* ----------
* Command type for progress reporting purposes
* ----------
*/
static inline void
-pgstat_report_wait_start(uint8 classId, uint16 eventId)
+pgstat_report_wait_start(uint32 wait_event_info)
{
volatile PGPROC *proc = MyProc;
- uint32 wait_event_val;
if (!pgstat_track_activities || !proc)
return;
- wait_event_val = classId;
- wait_event_val <<= 24;
- wait_event_val |= eventId;
-
/*
* Since this is a four-byte field which is always read and written as
* four-bytes, updates are atomic.
*/
- proc->wait_event_info = wait_event_val;
+ proc->wait_event_info = wait_event_info;
}
/* ----------
Latch *latch, void *user_data);
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 WaitEventSetWait(WaitEventSet *set, long timeout,
+ WaitEvent *occurred_events, int nevents,
+ uint32 wait_event_info);
+extern int WaitLatch(volatile Latch *latch, int wakeEvents, long timeout,
+ uint32 wait_event_info);
extern int WaitLatchOrSocket(volatile Latch *latch, int wakeEvents,
- pgsocket sock, long timeout);
+ pgsocket sock, long timeout, uint32 wait_event_info);
/*
* Unix implementation uses SIGUSR1 for inter-process signaling.
extern void CreateLWLocks(void);
extern void InitLWLockAccess(void);
-extern const char *GetLWLockIdentifier(uint8 classId, uint16 eventId);
+extern const char *GetLWLockIdentifier(uint32 classId, uint16 eventId);
/*
* Extensions (or core code) can obtain an LWLocks by calling
extern bool IsWaitingForLock(void);
extern void LockErrorCleanup(void);
-extern void ProcWaitForSignal(void);
+extern void ProcWaitForSignal(uint32 wait_event_info);
extern void ProcSendSignal(int pid);
extern void BecomeLockGroupLeader(void);
#include "postgres.h"
#include "miscadmin.h"
+#include "pgstat.h"
#include "postmaster/bgworker.h"
#include "storage/procsignal.h"
#include "storage/shm_toc.h"
}
/* Wait to be signalled. */
- WaitLatch(MyLatch, WL_LATCH_SET, 0);
+ WaitLatch(MyLatch, WL_LATCH_SET, 0, WAIT_EXTENSION);
/* Reset the latch so we don't spin. */
ResetLatch(MyLatch);
#include "fmgr.h"
#include "miscadmin.h"
+#include "pgstat.h"
#include "test_shm_mq.h"
* 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, WAIT_EXTENSION);
ResetLatch(MyLatch);
CHECK_FOR_INTERRUPTS();
}