On Wed, Sep 28, 2016 at 9:39 AM, Thomas Munro
<thomas.mu...@enterprisedb.com> wrote:
> Ok, if they really are independent then shouldn't we take advantage of
> that at call sites where we might be idle but we might also be waiting
> for the network?  For example we could do this:
>
>             /* Sleep until something happens or we time out */
>             WaitLatchOrSocket(MyLatch, wakeEvents,
>                               MyProcPort->sock, sleeptime,
>                               pq_is_send_pending() ? WAIT_CLIENT :
> WAIT_ACTIVITY,
>                               WE_WAL_SENDER_MAIN);

Yes, we can do fancy things with this API. Extensions could do the
same, the important thing being to have generic enough event
categories (take class).

> Isn't WE_WAL_SENDER_WAIT_WAL primarily WAIT_IPC, not WAIT_CLIENT?  Or
> perhaps "pq_is_send_pending() ? WAIT_CLIENT : WAIT_IPC".
>
> Actually, I'm still not sold on "Activity" and "Client".  I think
> "Idle" and "Network" would be better.  Everybody knows intuitively
> what "Idle" means.  "Network" is better than "Client" because it
> avoids confusion about user applications vs replication connections or
> clients vs servers.

Personally I am buying the argument of Robert instead. The class of an
event means what it is waiting for, not in which state in it waiting
for something. "Idle" means that the process *is* idle, not that it is
waiting for something.

> +        <listitem>
> +         <para>
> +          <literal>Activity</>: The server process is waiting for some
> +          activity to happen on a socket.  This is mainly used system 
> processes
> +          in their main processing loop.  <literal>wait_event</> will 
> identify
> +          the type of activity waited for.
> +         </para>
> +        </listitem>
>
> "The server process is waiting for some activity to happen on a
> socket."  Not true: could be a latch, or both.
>
> I think what this category is really getting at is that the server
> process is idle.  Everything in it could otherwise go in the IPC or
> Client categories on the basis that it's mainly waiting for a socket
> or a latch, but we're deciding to separate the wait points
> representing "idleness" and put them here.
>
> How about:  "The server process is idle.  This is used by system
> processes waiting for activity in their main processing loop.
> <literal>wait_event</a> will identify the specific wait point."

You have a better way to word things than I do.

> +        <listitem>
> +         <para>
> +          <literal>Client</>: The server process is waiting for some activity
> +          on a socket from a client process, and that the server expects
> +          something to happen that is independent from its internal 
> processes.
> +          <literal>wait_event</> will identify the type of client activity
> +          waited for.
> +         </para>
> +        </listitem>
>
> Is it worth spelling out that "client process" here doesn't just mean
> user applications, it's also remote PostgreSQL servers doing
> replication?  "wait_event" doesn't really identify the type of client
> activity waited for, it identifies the code that is waiting.

Okay, switched to "user applications", and precised that this is a
wait point that wait_event tracks.

> +        <listitem>
> +         <para>
> +          <literal>Extension</>: The server process is waiting for activity
> +          in a plugin or an extension.  This category is useful for plugin
> +          and module developers to track custom waiting points.
> +         </para>
> +        </listitem>
>
> Plugin, extension, module?  How about just "extension"?  Why developers?

Let's say "extension module", this is used in a couple of places in the docs.


> +        <listitem>
> +         <para>
> +          <literal>IPC</>: The server process is waiting for some activity
> +          from an auxilliary process.  <literal>wait_event</> will identify
> +          the type of activity waited for.
> +         </para>
> +        </listitem>
>
> s/auxilliary/auxiliary/, but I wouldn't it be better to say something
> more general like "from another process in the cluster"?  Background
> workers are not generally called auxiliary processes, and some of
> these wait points are waiting for those.

There was the same typo in latch.h, still "from another process" looks better.
-- 
Michael
diff --git a/contrib/postgres_fdw/connection.c b/contrib/postgres_fdw/connection.c
index 8ca1c1c..9222b73 100644
--- a/contrib/postgres_fdw/connection.c
+++ b/contrib/postgres_fdw/connection.c
@@ -17,6 +17,7 @@
 #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"
@@ -496,7 +497,9 @@ pgfdw_get_result(PGconn *conn, const char *query)
 			wc = WaitLatchOrSocket(MyLatch,
 								   WL_LATCH_SET | WL_SOCKET_READABLE,
 								   PQsocket(conn),
-								   -1L);
+								   -1L,
+								   WAIT_EXTENSION,
+								   WE_EXTENSION);
 			ResetLatch(MyLatch);
 
 			CHECK_FOR_INTERRUPTS();
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index f400785..bb975c1 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -679,6 +679,42 @@ postgres   27093  0.0  0.0  30096  2752 ?        Ss   11:34   0:00 postgres: ser
           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>
@@ -1085,6 +1121,143 @@ postgres   27093  0.0  0.0  30096  2752 ?        Ss   11:34   0:00 postgres: ser
          <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>SecureRead</></entry>
+         <entry>Waiting to read data from a secure connection.</entry>
+        </row>
+        <row>
+         <entry><literal>SecureWrite</></entry>
+         <entry>Waiting to write data to a secure connection.</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 the code path of an extension, should be used by custom plugins and modules</entry>
+        </row>
+        <row>
+         <entry morerows="10"><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 put new message in shared message queue.</entry>
+        </row>
+        <row>
+         <entry><literal>MessageQueueReceive</></entry>
+         <entry>Waiting to receive bytes in shared message queue.</entry>
+        </row>
+        <row>
+         <entry><literal>MessageQueueSend</></entry>
+         <entry>Waiting to send bytes in shared message queue.</entry>
+        </row>
+        <row>
+         <entry><literal>ParallelFinish</></entry>
+         <entry>Waiting for parallel workers to finish computing.</entry>
+        </row>
+        <row>
+         <entry><literal>ProcSignal</></entry>
+         <entry>Waiting for signal from another backend.</entry>
+        </row>
+        <row>
+         <entry><literal>ProcSleep</></entry>
+         <entry>Waiting for a specific lock.</entry>
+        </row>
+        <row>
+         <entry><literal>SyncRep</></entry>
+         <entry>Waiting for WAL commit 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>
diff --git a/src/backend/access/transam/parallel.c b/src/backend/access/transam/parallel.c
index cde0ed3..63d4969 100644
--- a/src/backend/access/transam/parallel.c
+++ b/src/backend/access/transam/parallel.c
@@ -24,6 +24,7 @@
 #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"
@@ -540,7 +541,8 @@ WaitForParallelWorkersToFinish(ParallelContext *pcxt)
 		if (!anyone_alive)
 			break;
 
-		WaitLatch(&MyProc->procLatch, WL_LATCH_SET, -1);
+		WaitLatch(&MyProc->procLatch, WL_LATCH_SET, -1,
+				  WAIT_IPC, WE_PARALLEL_FINISH);
 		ResetLatch(&MyProc->procLatch);
 	}
 
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index c1b9a97..e65fd0a 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -5827,7 +5827,8 @@ recoveryApplyDelay(XLogReaderState *record)
 
 		WaitLatch(&XLogCtl->recoveryWakeupLatch,
 				  WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
-				  secs * 1000L + microsecs / 1000);
+				  secs * 1000L + microsecs / 1000,
+				  WAIT_TIMEOUT, WE_RECOVERY_APPLY_DELAY);
 	}
 	return true;
 }
@@ -11387,7 +11388,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
 
 						WaitLatch(&XLogCtl->recoveryWakeupLatch,
 							 WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
-								  wait_time);
+							 wait_time, WAIT_ACTIVITY, WE_RECOVERY_WAL_STREAM);
 						ResetLatch(&XLogCtl->recoveryWakeupLatch);
 						now = GetCurrentTimestamp();
 					}
@@ -11550,7 +11551,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
 					 */
 					WaitLatch(&XLogCtl->recoveryWakeupLatch,
 							  WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
-							  5000L);
+							  5000L, WAIT_ACTIVITY, WE_RECOVERY_WAL_ALL);
 					ResetLatch(&XLogCtl->recoveryWakeupLatch);
 					break;
 				}
diff --git a/src/backend/executor/nodeGather.c b/src/backend/executor/nodeGather.c
index 438d1b2..0178cd1 100644
--- a/src/backend/executor/nodeGather.c
+++ b/src/backend/executor/nodeGather.c
@@ -38,6 +38,7 @@
 #include "executor/nodeSubplan.h"
 #include "executor/tqueue.h"
 #include "miscadmin.h"
+#include "pgstat.h"
 #include "utils/memutils.h"
 #include "utils/rel.h"
 
@@ -387,7 +388,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, WAIT_IPC, WE_EXECUTE_GATHER);
 			ResetLatch(MyLatch);
 			nvisited = 0;
 		}
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index fedb02c..4f78863 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -60,6 +60,7 @@
 
 #include "libpq/libpq.h"
 #include "miscadmin.h"
+#include "pgstat.h"
 #include "storage/latch.h"
 #include "tcop/tcopprot.h"
 #include "utils/memutils.h"
@@ -419,7 +420,8 @@ aloop:
 				else
 					waitfor = WL_SOCKET_WRITEABLE;
 
-				WaitLatchOrSocket(MyLatch, waitfor, port->sock, 0);
+				WaitLatchOrSocket(MyLatch, waitfor, port->sock, 0,
+								  WAIT_CLIENT, WE_SSL_OPEN_SERVER);
 				goto aloop;
 			case SSL_ERROR_SYSCALL:
 				if (r < 0)
diff --git a/src/backend/libpq/be-secure.c b/src/backend/libpq/be-secure.c
index cdd07d5..671bffc 100644
--- a/src/backend/libpq/be-secure.c
+++ b/src/backend/libpq/be-secure.c
@@ -33,6 +33,7 @@
 
 #include "libpq/libpq.h"
 #include "miscadmin.h"
+#include "pgstat.h"
 #include "tcop/tcopprot.h"
 #include "utils/memutils.h"
 #include "storage/ipc.h"
@@ -146,7 +147,8 @@ retry:
 
 		ModifyWaitEvent(FeBeWaitSet, 0, waitfor, NULL);
 
-		WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1);
+		WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1,
+						 WAIT_CLIENT, WE_SECURE_READ);
 
 		/*
 		 * If the postmaster has died, it's not safe to continue running,
@@ -247,7 +249,8 @@ retry:
 
 		ModifyWaitEvent(FeBeWaitSet, 0, waitfor, NULL);
 
-		WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1);
+		WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1,
+						 WAIT_CLIENT, WE_SECURE_WRITE);
 
 		/* See comments in secure_read. */
 		if (event.events & WL_POSTMASTER_DEATH)
diff --git a/src/backend/libpq/pqmq.c b/src/backend/libpq/pqmq.c
index bfe66c6..8c7fff3 100644
--- a/src/backend/libpq/pqmq.c
+++ b/src/backend/libpq/pqmq.c
@@ -17,6 +17,7 @@
 #include "libpq/pqformat.h"
 #include "libpq/pqmq.h"
 #include "miscadmin.h"
+#include "pgstat.h"
 #include "tcop/tcopprot.h"
 #include "utils/builtins.h"
 
@@ -171,7 +172,8 @@ 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, WAIT_IPC,
+				  WE_MQ_PUT_MESSAGE);
 		ResetLatch(&MyProc->procLatch);
 		CHECK_FOR_INTERRUPTS();
 	}
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 1a92ca1..8558110 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),
+					   WAIT_ACTIVITY, WE_AUTOVACUUM_MAIN);
 
 		ResetLatch(MyLatch);
 
diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c
index 699c934..9bdbe68 100644
--- a/src/backend/postmaster/bgworker.c
+++ b/src/backend/postmaster/bgworker.c
@@ -16,6 +16,7 @@
 
 #include "miscadmin.h"
 #include "libpq/pqsignal.h"
+#include "pgstat.h"
 #include "postmaster/bgworker_internals.h"
 #include "postmaster/postmaster.h"
 #include "storage/barrier.h"
@@ -969,7 +970,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,
+					   WAIT_IPC, WE_BGWORKER_STARTUP);
 
 		if (rc & WL_POSTMASTER_DEATH)
 		{
@@ -1008,7 +1010,8 @@ WaitForBackgroundWorkerShutdown(BackgroundWorkerHandle *handle)
 			break;
 
 		rc = WaitLatch(&MyProc->procLatch,
-					   WL_LATCH_SET | WL_POSTMASTER_DEATH, 0);
+					   WL_LATCH_SET | WL_POSTMASTER_DEATH, 0,
+					   WAIT_IPC, WE_BGWORKER_SHUTDOWN);
 
 		if (rc & WL_POSTMASTER_DEATH)
 		{
diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c
index 1002034..67ec0ce 100644
--- a/src/backend/postmaster/bgwriter.c
+++ b/src/backend/postmaster/bgwriter.c
@@ -345,7 +345,9 @@ BackgroundWriterMain(void)
 		 */
 		rc = WaitLatch(MyLatch,
 					   WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
-					   BgWriterDelay /* ms */ );
+					   BgWriterDelay /* ms */,
+					   WAIT_ACTIVITY,
+					   WE_BGWRITER_MAIN);
 
 		/*
 		 * If no latch event and BgBufferSync says nothing's happening, extend
@@ -372,7 +374,9 @@ BackgroundWriterMain(void)
 			/* Sleep ... */
 			rc = WaitLatch(MyLatch,
 						   WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
-						   BgWriterDelay * HIBERNATE_FACTOR);
+						   BgWriterDelay * HIBERNATE_FACTOR,
+						   WAIT_ACTIVITY,
+						   WE_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 d702a48..a382157 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -556,7 +556,9 @@ 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 */,
+					   WAIT_ACTIVITY,
+					   WE_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..1fc2794 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, WAIT_ACTIVITY, WE_ARCHIVER_MAIN);
 				if (rc & WL_TIMEOUT)
 					wakened = true;
 			}
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index 96578dc..019086a 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -3155,6 +3155,18 @@ pgstat_get_wait_event_type(uint32 wait_event_info)
 		case WAIT_BUFFER_PIN:
 			event_type = "BufferPin";
 			break;
+		case WAIT_ACTIVITY:
+			event_type = "Activity";
+			break;
+		case WAIT_CLIENT:
+			event_type = "Client";
+			break;
+		case WAIT_IPC:
+			event_type = "IPC";
+			break;
+		case WAIT_TIMEOUT:
+			event_type = "Timeout";
+			break;
 		default:
 			event_type = "???";
 			break;
@@ -3196,6 +3208,13 @@ pgstat_get_wait_event(uint32 wait_event_info)
 		case WAIT_BUFFER_PIN:
 			event_name = "BufferPin";
 			break;
+		case WAIT_ACTIVITY:
+		case WAIT_CLIENT:
+		case WAIT_EXTENSION:
+		case WAIT_IPC:
+		case WAIT_TIMEOUT:
+			event_name = GetWaitEventIdentifier(eventId);
+			break;
 		default:
 			event_name = "unknown wait event";
 			break;
@@ -3684,8 +3703,7 @@ PgstatCollectorMain(int argc, char *argv[])
 #ifndef WIN32
 		wr = WaitLatchOrSocket(MyLatch,
 					 WL_LATCH_SET | WL_POSTMASTER_DEATH | WL_SOCKET_READABLE,
-							   pgStatSock,
-							   -1L);
+					 pgStatSock, -1L, WAIT_ACTIVITY, WE_PGSTAT_MAIN);
 #else
 
 		/*
@@ -3701,7 +3719,9 @@ 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 */,
+							   WAIT_ACTIVITY,
+							   WE_PGSTAT_MAIN);
 #endif
 
 		/*
diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c
index e7e488a..c937831 100644
--- a/src/backend/postmaster/syslogger.c
+++ b/src/backend/postmaster/syslogger.c
@@ -35,6 +35,7 @@
 #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"
@@ -424,7 +425,9 @@ SysLoggerMain(int argc, char *argv[])
 		rc = WaitLatchOrSocket(MyLatch,
 							   WL_LATCH_SET | WL_SOCKET_READABLE | cur_flags,
 							   syslogPipe[0],
-							   cur_timeout);
+							   cur_timeout,
+							   WAIT_ACTIVITY,
+							   WE_SYSLOGGER_MAIN);
 
 		if (rc & WL_SOCKET_READABLE)
 		{
@@ -475,7 +478,9 @@ SysLoggerMain(int argc, char *argv[])
 
 		(void) WaitLatch(MyLatch,
 						 WL_LATCH_SET | cur_flags,
-						 cur_timeout);
+						 cur_timeout,
+						 WAIT_ACTIVITY,
+						 WE_SYSLOGGER_MAIN);
 
 		EnterCriticalSection(&sysloggerSection);
 #endif   /* WIN32 */
diff --git a/src/backend/postmaster/walwriter.c b/src/backend/postmaster/walwriter.c
index 11ec56a..e798d83 100644
--- a/src/backend/postmaster/walwriter.c
+++ b/src/backend/postmaster/walwriter.c
@@ -290,7 +290,9 @@ WalWriterMain(void)
 
 		rc = WaitLatch(MyLatch,
 					   WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
-					   cur_timeout);
+					   cur_timeout,
+					   WAIT_ACTIVITY,
+					   WE_WAL_WRITER_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 da9b7a6..8e40c34 100644
--- a/src/backend/replication/basebackup.c
+++ b/src/backend/replication/basebackup.c
@@ -1286,7 +1286,9 @@ throttle(size_t increment)
 		 */
 		wait_result = WaitLatch(MyLatch,
 							 WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
-								(long) (sleep / 1000));
+								(long) (sleep / 1000),
+								WAIT_TIMEOUT,
+								WE_BASE_BACKUP_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 b442d06..09c8ce4 100644
--- a/src/backend/replication/syncrep.c
+++ b/src/backend/replication/syncrep.c
@@ -61,6 +61,7 @@
 
 #include "access/xact.h"
 #include "miscadmin.h"
+#include "pgstat.h"
 #include "replication/syncrep.h"
 #include "replication/walsender.h"
 #include "replication/walsender_private.h"
@@ -258,7 +259,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,
+				  WAIT_IPC, WE_SYNC_REP);
 	}
 
 	/*
diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c
index 413ee3a..2660016 100644
--- a/src/backend/replication/walreceiver.c
+++ b/src/backend/replication/walreceiver.c
@@ -55,6 +55,7 @@
 #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"
@@ -486,7 +487,9 @@ WalReceiverMain(void)
 								   WL_POSTMASTER_DEATH | WL_SOCKET_READABLE |
 									   WL_TIMEOUT | WL_LATCH_SET,
 									   wait_fd,
-									   NAPTIME_PER_CYCLE);
+									   NAPTIME_PER_CYCLE,
+									   WAIT_ACTIVITY,
+									   WE_WAL_RECEIVER_MAIN);
 				if (rc & WL_LATCH_SET)
 				{
 					ResetLatch(&walrcv->latch);
@@ -685,7 +688,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,
+				  WAIT_CLIENT, WE_WAL_RECEIVER_WAIT_START);
 	}
 
 	if (update_process_title)
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index c7743da..d3f66bb 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -1146,7 +1146,9 @@ WalSndWriteData(LogicalDecodingContext *ctx, XLogRecPtr lsn, TransactionId xid,
 
 		/* Sleep until something happens or we time out */
 		WaitLatchOrSocket(MyLatch, wakeEvents,
-						  MyProcPort->sock, sleeptime);
+						  MyProcPort->sock, sleeptime,
+						  WAIT_CLIENT,
+						  WE_WAL_SENDER_WRITE_DATA);
 	}
 
 	/* reactivate latch so WalSndLoop knows to continue */
@@ -1272,7 +1274,9 @@ WalSndWaitForWal(XLogRecPtr loc)
 
 		/* Sleep until something happens or we time out */
 		WaitLatchOrSocket(MyLatch, wakeEvents,
-						  MyProcPort->sock, sleeptime);
+						  MyProcPort->sock, sleeptime,
+						  WAIT_CLIENT,
+						  WE_WAL_SENDER_WAIT_WAL);
 	}
 
 	/* reactivate latch so WalSndLoop knows to continue */
@@ -1924,7 +1928,9 @@ WalSndLoop(WalSndSendDataCallback send_data)
 
 			/* Sleep until something happens or we time out */
 			WaitLatchOrSocket(MyLatch, wakeEvents,
-							  MyProcPort->sock, sleeptime);
+							  MyProcPort->sock, sleeptime,
+							  WAIT_ACTIVITY,
+							  WE_WAL_SENDER_MAIN);
 		}
 	}
 	return;
diff --git a/src/backend/storage/ipc/latch.c b/src/backend/storage/ipc/latch.c
index 9def8a1..8dcf569 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"
@@ -122,6 +123,50 @@ struct WaitEventSet
 #endif
 };
 
+/*
+ * This must match enum WaitEventIdentifier!
+ */
+const char *const WaitEventNames[] = {
+	/* Activity */
+	"ArchiverMain",
+	"AutoVacuumMain",
+	"BgWriterHibernate",
+	"BgWriterMain",
+	"CheckpointerMain",
+	"PgStatMain",
+	"RecoveryWalAll",
+	"RecoveryWalStream",
+	"SysLoggerMain",
+	"WalReceiverMain",
+	"WalSenderMain",
+	"WalWriterMain",
+	/* Client */
+	"SecureRead",
+	"SecureWrite",
+	"SSLOpenServer",
+	"WalReceiverWaitStart",
+	"WalSenderWaitForWAL",
+	"WalSenderWriteData",
+	/* Extension */
+	"Extension",
+	/* IPC */
+	"BgWorkerShutdown",
+	"BgWorkerStartup",
+	"ExecuteGather",
+	"MessageQueueInternal",
+	"MessageQueuePutMessage",
+	"MessageQueueReceive",
+	"MessageQueueSend",
+	"ParallelFinish",
+	"ProcSignal",
+	"ProcSleep",
+	"SyncRep",
+	/* Timeout */
+	"BaseBackupThrottle",
+	"PgSleep",
+	"RecoveryApplyDelay",
+};
+
 #ifndef WIN32
 /* Are we currently in WaitLatch? The signal handler would like to know. */
 static volatile sig_atomic_t waiting = false;
@@ -297,9 +342,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,
+		  uint8 classId, uint16 eventId)
 {
-	return WaitLatchOrSocket(latch, wakeEvents, PGINVALID_SOCKET, timeout);
+	return WaitLatchOrSocket(latch, wakeEvents, PGINVALID_SOCKET, timeout,
+							 classId, eventId);
 }
 
 /*
@@ -316,7 +363,7 @@ WaitLatch(volatile Latch *latch, int wakeEvents, long timeout)
  */
 int
 WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
-				  long timeout)
+				  long timeout, uint8 classId, uint16 eventId)
 {
 	int			ret = 0;
 	int			rc;
@@ -344,7 +391,7 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
 		AddWaitEventToSet(set, ev, sock, NULL, NULL);
 	}
 
-	rc = WaitEventSetWait(set, timeout, &event, 1);
+	rc = WaitEventSetWait(set, timeout, &event, 1, classId, eventId);
 
 	if (rc == 0)
 		ret |= WL_TIMEOUT;
@@ -863,7 +910,8 @@ WaitEventAdjustWin32(WaitEventSet *set, WaitEvent *event)
  */
 int
 WaitEventSetWait(WaitEventSet *set, long timeout,
-				 WaitEvent *occurred_events, int nevents)
+				 WaitEvent *occurred_events, int nevents,
+				 uint8 classId, uint16 eventId)
 {
 	int			returned_events = 0;
 	instr_time	start_time;
@@ -872,6 +920,8 @@ WaitEventSetWait(WaitEventSet *set, long timeout,
 
 	Assert(nevents > 0);
 
+	pgstat_report_wait_start((uint8) classId, (uint16) eventId);
+
 	/*
 	 * Initialize timeout if requested.  We must record the current time so
 	 * that we can determine the remaining timeout if interrupted.
@@ -960,6 +1010,8 @@ WaitEventSetWait(WaitEventSet *set, long timeout,
 	waiting = false;
 #endif
 
+	pgstat_report_wait_end();
+
 	return returned_events;
 }
 
@@ -1491,6 +1543,22 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
 }
 #endif
 
+
+/*
+ * Return an identifier for a WaitEventSet depending on an event for
+ * statistics collector.
+ */
+const char *
+GetWaitEventIdentifier(uint16 eventId)
+{
+	StaticAssertStmt(lengthof(WaitEventNames) == WE_LAST_TYPE + 1,
+					 "WaitEventNames must match WaitEventIdentifiers");
+	if (eventId > WE_LAST_TYPE)
+		return "???";
+	return WaitEventNames[eventId];
+}
+
+
 /*
  * 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 5b32782..8d8dc99 100644
--- a/src/backend/storage/ipc/shm_mq.c
+++ b/src/backend/storage/ipc/shm_mq.c
@@ -19,6 +19,7 @@
 #include "postgres.h"
 
 #include "miscadmin.h"
+#include "pgstat.h"
 #include "postmaster/bgworker.h"
 #include "storage/procsignal.h"
 #include "storage/shm_mq.h"
@@ -894,7 +895,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, WAIT_IPC, WE_MQ_SEND);
 
 			/* Reset the latch so we don't spin. */
 			ResetLatch(MyLatch);
@@ -991,7 +992,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, WAIT_IPC, WE_MQ_RECEIVE);
 
 		/* Reset the latch so we don't spin. */
 		ResetLatch(MyLatch);
@@ -1090,7 +1091,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, WAIT_IPC, WE_MQ_INTERNAL);
 
 		/* Reset the latch so we don't spin. */
 		ResetLatch(MyLatch);
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 33e7023..ca29f14 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -39,6 +39,7 @@
 #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"
@@ -1212,7 +1213,7 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
 		}
 		else
 		{
-			WaitLatch(MyLatch, WL_LATCH_SET, 0);
+			WaitLatch(MyLatch, WL_LATCH_SET, 0, WAIT_IPC, WE_PROC_SLEEP);
 			ResetLatch(MyLatch);
 			/* check for deadlocks first, as that's probably log-worthy */
 			if (got_deadlock_timeout)
@@ -1724,7 +1725,7 @@ CheckDeadLockAlert(void)
 void
 ProcWaitForSignal(void)
 {
-	WaitLatch(MyLatch, WL_LATCH_SET, 0);
+	WaitLatch(MyLatch, WL_LATCH_SET, 0, WAIT_IPC, WE_PROC_SIGNAL);
 	ResetLatch(MyLatch);
 	CHECK_FOR_INTERRUPTS();
 }
diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c
index 5e705e9..0e2ff93 100644
--- a/src/backend/utils/adt/misc.c
+++ b/src/backend/utils/adt/misc.c
@@ -30,6 +30,7 @@
 #include "funcapi.h"
 #include "miscadmin.h"
 #include "parser/scansup.h"
+#include "pgstat.h"
 #include "postmaster/syslogger.h"
 #include "rewrite/rewriteHandler.h"
 #include "storage/fd.h"
@@ -560,7 +561,9 @@ pg_sleep(PG_FUNCTION_ARGS)
 
 		(void) WaitLatch(MyLatch,
 						 WL_LATCH_SET | WL_TIMEOUT,
-						 delay_ms);
+						 delay_ms,
+						 WAIT_TIMEOUT,
+						 WE_PG_SLEEP);
 		ResetLatch(MyLatch);
 	}
 
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 0c98c59..b3f707e 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -721,8 +721,13 @@ typedef enum WaitClass
 	WAIT_LWLOCK_NAMED,
 	WAIT_LWLOCK_TRANCHE,
 	WAIT_LOCK,
-	WAIT_BUFFER_PIN
-}	WaitClass;
+	WAIT_BUFFER_PIN,
+	WAIT_ACTIVITY,
+	WAIT_CLIENT,
+	WAIT_EXTENSION,
+	WAIT_IPC,
+	WAIT_TIMEOUT
+} WaitClass;
 
 
 /* ----------
diff --git a/src/include/storage/latch.h b/src/include/storage/latch.h
index 5179ecc..8261830 100644
--- a/src/include/storage/latch.h
+++ b/src/include/storage/latch.h
@@ -135,6 +135,66 @@ typedef struct WaitEvent
 	void	   *user_data;		/* pointer provided in AddWaitEventToSet */
 } WaitEvent;
 
+/*
+ * List of WaitEventSet identifiers used when reporting activity to
+ * statistics collector. Up to 256 different WaitEventIdentifier can be
+ * handled. Those are classified by category first, and then by
+ * alphabetical order. Events are classified into sub-categories following
+ * some basic hierarchy rules:
+ * - "Activity" for main loops of processes waiting for an event.
+ * - "Client" for a socket awaited when a user is connected.
+ * - "IPC", similarly to "Client", for a socket awaited from another
+ *   server process.
+ * - "Timeout", for a timeout waiting to expire.
+ * - "Extension", to let extension modules a way to define a custom wait
+ *   point.
+ */
+typedef enum WaitEventIdentifier
+{
+	/* Activity */
+	WE_ARCHIVER_MAIN,
+	WE_AUTOVACUUM_MAIN,
+	WE_BGWRITER_HIBERNATE,
+	WE_BGWRITER_MAIN,
+	WE_CHECKPOINTER_MAIN,
+	WE_PGSTAT_MAIN,
+	WE_RECOVERY_WAL_ALL,
+	WE_RECOVERY_WAL_STREAM,
+	WE_SYSLOGGER_MAIN,
+	WE_WAL_RECEIVER_MAIN,
+	WE_WAL_SENDER_MAIN,
+	WE_WAL_WRITER_MAIN,
+	/* Client */
+	WE_SECURE_READ,
+	WE_SECURE_WRITE,
+	WE_SSL_OPEN_SERVER,
+	WE_WAL_RECEIVER_WAIT_START,
+	WE_WAL_SENDER_WAIT_WAL,
+	WE_WAL_SENDER_WRITE_DATA,
+	/* Extension */
+	WE_EXTENSION,
+	/* IPC */
+	WE_BGWORKER_SHUTDOWN,
+	WE_BGWORKER_STARTUP,
+	WE_EXECUTE_GATHER,
+	WE_MQ_INTERNAL,
+	WE_MQ_PUT_MESSAGE,
+	WE_MQ_RECEIVE,
+	WE_MQ_SEND,
+	WE_PARALLEL_FINISH,
+	WE_PROC_SIGNAL,
+	WE_PROC_SLEEP,
+	WE_SYNC_REP,
+	/* Timeout */
+	WE_BASE_BACKUP_THROTTLE,
+	WE_PG_SLEEP,
+	WE_RECOVERY_APPLY_DELAY
+} WaitEventIdentifier;
+
+#define WE_LAST_TYPE WE_RECOVERY_APPLY_DELAY
+
+extern const char *const WaitEventName[];
+
 /* forward declaration to avoid exposing latch.c implementation details */
 typedef struct WaitEventSet WaitEventSet;
 
@@ -155,10 +215,15 @@ extern int AddWaitEventToSet(WaitEventSet *set, uint32 events, pgsocket fd,
 				  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,
+				  uint8 classId, uint16 eventId);
+extern int	WaitLatch(volatile Latch *latch, int wakeEvents, long timeout,
+				  uint8 classId, uint16 eventId);
 extern int WaitLatchOrSocket(volatile Latch *latch, int wakeEvents,
-				  pgsocket sock, long timeout);
+				  pgsocket sock, long timeout, uint8 classId,
+				  uint16 eventId);
+extern const char *GetWaitEventIdentifier(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 143df4e..e7f76cd 100644
--- a/src/test/modules/test_shm_mq/setup.c
+++ b/src/test/modules/test_shm_mq/setup.c
@@ -16,6 +16,7 @@
 #include "postgres.h"
 
 #include "miscadmin.h"
+#include "pgstat.h"
 #include "postmaster/bgworker.h"
 #include "storage/procsignal.h"
 #include "storage/shm_toc.h"
@@ -279,7 +280,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, WAIT_EXTENSION, WE_EXTENSION);
 
 		/* Reset the latch so we don't spin. */
 		ResetLatch(MyLatch);
diff --git a/src/test/modules/test_shm_mq/test.c b/src/test/modules/test_shm_mq/test.c
index dd34bc7..15d3874 100644
--- a/src/test/modules/test_shm_mq/test.c
+++ b/src/test/modules/test_shm_mq/test.c
@@ -15,6 +15,7 @@
 
 #include "fmgr.h"
 #include "miscadmin.h"
+#include "pgstat.h"
 
 #include "test_shm_mq.h"
 
@@ -230,7 +231,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, WAIT_EXTENSION, WE_EXTENSION);
 			ResetLatch(MyLatch);
 			CHECK_FOR_INTERRUPTS();
 		}
diff --git a/src/test/modules/worker_spi/worker_spi.c b/src/test/modules/worker_spi/worker_spi.c
index 314e371..697dc42 100644
--- a/src/test/modules/worker_spi/worker_spi.c
+++ b/src/test/modules/worker_spi/worker_spi.c
@@ -227,7 +227,9 @@ 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,
+					   WAIT_EXTENSION,
+					   WE_EXTENSION);
 		ResetLatch(MyLatch);
 
 		/* emergency bailout if postmaster has died */
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to