Skip to content

Commit 3347c98

Browse files
committed
Use a long lived WaitEventSet for WaitLatch().
Create LatchWaitSet at backend startup time, and use it to implement WaitLatch(). This avoids repeated epoll/kqueue setup and teardown system calls. Reorder SubPostmasterMain() slightly so that we restore the postmaster pipe and Windows signal emulation before we reach InitPostmasterChild(), to make this work in EXEC_BACKEND builds. Reviewed-by: Kyotaro Horiguchi <horikyota.ntt@gmail.com> Discussion: https://postgr.es/m/CA%2BhUKGJAC4Oqao%3DqforhNey20J8CiG2R%3DoBPqvfR0vOJrFysGw%40mail.gmail.com
1 parent d6c08e2 commit 3347c98

File tree

4 files changed

+67
-16
lines changed

4 files changed

+67
-16
lines changed

src/backend/postmaster/postmaster.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4896,9 +4896,6 @@ SubPostmasterMain(int argc, char *argv[])
48964896
IsPostmasterEnvironment = true;
48974897
whereToSendOutput = DestNone;
48984898

4899-
/* Setup as postmaster child */
4900-
InitPostmasterChild();
4901-
49024899
/* Setup essential subsystems (to ensure elog() behaves sanely) */
49034900
InitializeGUCOptions();
49044901

@@ -4913,6 +4910,18 @@ SubPostmasterMain(int argc, char *argv[])
49134910
/* Close the postmaster's sockets (as soon as we know them) */
49144911
ClosePostmasterPorts(strcmp(argv[1], "--forklog") == 0);
49154912

4913+
/*
4914+
* Start our win32 signal implementation. This has to be done after we
4915+
* read the backend variables, because we need to pick up the signal pipe
4916+
* from the parent process.
4917+
*/
4918+
#ifdef WIN32
4919+
pgwin32_signal_initialize();
4920+
#endif
4921+
4922+
/* Setup as postmaster child */
4923+
InitPostmasterChild();
4924+
49164925
/*
49174926
* Set up memory area for GSS information. Mirrors the code in ConnCreate
49184927
* for the non-exec case.
@@ -4956,15 +4965,6 @@ SubPostmasterMain(int argc, char *argv[])
49564965
if (strcmp(argv[1], "--forkavworker") == 0)
49574966
AutovacuumWorkerIAm();
49584967

4959-
/*
4960-
* Start our win32 signal implementation. This has to be done after we
4961-
* read the backend variables, because we need to pick up the signal pipe
4962-
* from the parent process.
4963-
*/
4964-
#ifdef WIN32
4965-
pgwin32_signal_initialize();
4966-
#endif
4967-
49684968
/* In EXEC_BACKEND case we will not have inherited these settings */
49694969
pqinitmask();
49704970
PG_SETMASK(&BlockSig);

src/backend/storage/ipc/latch.c

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
#include "storage/latch.h"
5757
#include "storage/pmsignal.h"
5858
#include "storage/shmem.h"
59+
#include "utils/memutils.h"
5960

6061
/*
6162
* Select the fd readiness primitive to use. Normally the "most modern"
@@ -129,6 +130,12 @@ struct WaitEventSet
129130
#endif
130131
};
131132

133+
/* A common WaitEventSet used to implement WatchLatch() */
134+
static WaitEventSet *LatchWaitSet;
135+
136+
/* The position of the latch in LatchWaitSet. */
137+
#define LatchWaitSetLatchPos 0
138+
132139
#ifndef WIN32
133140
/* Are we currently in WaitLatch? The signal handler would like to know. */
134141
static volatile sig_atomic_t waiting = false;
@@ -242,6 +249,24 @@ InitializeLatchSupport(void)
242249
#endif
243250
}
244251

252+
void
253+
InitializeLatchWaitSet(void)
254+
{
255+
int latch_pos PG_USED_FOR_ASSERTS_ONLY;
256+
257+
Assert(LatchWaitSet == NULL);
258+
259+
/* Set up the WaitEventSet used by WaitLatch(). */
260+
LatchWaitSet = CreateWaitEventSet(TopMemoryContext, 2);
261+
latch_pos = AddWaitEventToSet(LatchWaitSet, WL_LATCH_SET, PGINVALID_SOCKET,
262+
MyLatch, NULL);
263+
if (IsUnderPostmaster)
264+
AddWaitEventToSet(LatchWaitSet, WL_EXIT_ON_PM_DEATH,
265+
PGINVALID_SOCKET, NULL, NULL);
266+
267+
Assert(latch_pos == LatchWaitSetLatchPos);
268+
}
269+
245270
/*
246271
* Initialize a process-local latch.
247272
*/
@@ -365,8 +390,31 @@ int
365390
WaitLatch(Latch *latch, int wakeEvents, long timeout,
366391
uint32 wait_event_info)
367392
{
368-
return WaitLatchOrSocket(latch, wakeEvents, PGINVALID_SOCKET, timeout,
369-
wait_event_info);
393+
WaitEvent event;
394+
395+
/* Postmaster-managed callers must handle postmaster death somehow. */
396+
Assert(!IsUnderPostmaster ||
397+
(wakeEvents & WL_EXIT_ON_PM_DEATH) ||
398+
(wakeEvents & WL_POSTMASTER_DEATH));
399+
400+
/*
401+
* Some callers may have a latch other than MyLatch, or no latch at all,
402+
* or want to handle postmaster death differently. It's cheap to assign
403+
* those, so just do it every time.
404+
*/
405+
if (!(wakeEvents & WL_LATCH_SET))
406+
latch = NULL;
407+
ModifyWaitEvent(LatchWaitSet, LatchWaitSetLatchPos, WL_LATCH_SET, latch);
408+
LatchWaitSet->exit_on_postmaster_death =
409+
((wakeEvents & WL_EXIT_ON_PM_DEATH) != 0);
410+
411+
if (WaitEventSetWait(LatchWaitSet,
412+
(wakeEvents & WL_TIMEOUT) ? timeout : -1,
413+
&event, 1,
414+
wait_event_info) == 0)
415+
return WL_TIMEOUT;
416+
else
417+
return event.events;
370418
}
371419

372420
/*
@@ -830,7 +878,8 @@ AddWaitEventToSet(WaitEventSet *set, uint32 events, pgsocket fd, Latch *latch,
830878

831879
/*
832880
* Change the event mask and, in the WL_LATCH_SET case, the latch associated
833-
* with the WaitEvent.
881+
* with the WaitEvent. The latch may be changed to NULL to disable the latch
882+
* temporarily, and then set back to a latch later.
834883
*
835884
* 'pos' is the id returned by AddWaitEventToSet.
836885
*/
@@ -862,7 +911,6 @@ ModifyWaitEvent(WaitEventSet *set, int pos, uint32 events, Latch *latch)
862911
if (event->events & WL_LATCH_SET &&
863912
events != event->events)
864913
{
865-
/* we could allow to disable latch events for a while */
866914
elog(ERROR, "cannot modify latch event");
867915
}
868916

src/backend/utils/init/miscinit.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ InitPostmasterChild(void)
120120
InitializeLatchSupport();
121121
MyLatch = &LocalLatchData;
122122
InitLatch(MyLatch);
123+
InitializeLatchWaitSet();
123124

124125
/*
125126
* If possible, make this process a group leader, so that the postmaster
@@ -152,6 +153,7 @@ InitStandaloneProcess(const char *argv0)
152153
InitializeLatchSupport();
153154
MyLatch = &LocalLatchData;
154155
InitLatch(MyLatch);
156+
InitializeLatchWaitSet();
155157

156158
/* Compute paths, no postmaster to inherit from */
157159
if (my_exec_path[0] == '\0')

src/include/storage/latch.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ extern int WaitLatch(Latch *latch, int wakeEvents, long timeout,
176176
uint32 wait_event_info);
177177
extern int WaitLatchOrSocket(Latch *latch, int wakeEvents,
178178
pgsocket sock, long timeout, uint32 wait_event_info);
179+
extern void InitializeLatchWaitSet(void);
179180

180181
/*
181182
* Unix implementation uses SIGUSR1 for inter-process signaling.

0 commit comments

Comments
 (0)