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
This commit is contained in:
parent
d6c08e29e7
commit
3347c982ba
|
@ -4896,9 +4896,6 @@ SubPostmasterMain(int argc, char *argv[])
|
||||||
IsPostmasterEnvironment = true;
|
IsPostmasterEnvironment = true;
|
||||||
whereToSendOutput = DestNone;
|
whereToSendOutput = DestNone;
|
||||||
|
|
||||||
/* Setup as postmaster child */
|
|
||||||
InitPostmasterChild();
|
|
||||||
|
|
||||||
/* Setup essential subsystems (to ensure elog() behaves sanely) */
|
/* Setup essential subsystems (to ensure elog() behaves sanely) */
|
||||||
InitializeGUCOptions();
|
InitializeGUCOptions();
|
||||||
|
|
||||||
|
@ -4913,6 +4910,18 @@ SubPostmasterMain(int argc, char *argv[])
|
||||||
/* Close the postmaster's sockets (as soon as we know them) */
|
/* Close the postmaster's sockets (as soon as we know them) */
|
||||||
ClosePostmasterPorts(strcmp(argv[1], "--forklog") == 0);
|
ClosePostmasterPorts(strcmp(argv[1], "--forklog") == 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start our win32 signal implementation. This has to be done after we
|
||||||
|
* read the backend variables, because we need to pick up the signal pipe
|
||||||
|
* from the parent process.
|
||||||
|
*/
|
||||||
|
#ifdef WIN32
|
||||||
|
pgwin32_signal_initialize();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Setup as postmaster child */
|
||||||
|
InitPostmasterChild();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up memory area for GSS information. Mirrors the code in ConnCreate
|
* Set up memory area for GSS information. Mirrors the code in ConnCreate
|
||||||
* for the non-exec case.
|
* for the non-exec case.
|
||||||
|
@ -4956,15 +4965,6 @@ SubPostmasterMain(int argc, char *argv[])
|
||||||
if (strcmp(argv[1], "--forkavworker") == 0)
|
if (strcmp(argv[1], "--forkavworker") == 0)
|
||||||
AutovacuumWorkerIAm();
|
AutovacuumWorkerIAm();
|
||||||
|
|
||||||
/*
|
|
||||||
* Start our win32 signal implementation. This has to be done after we
|
|
||||||
* read the backend variables, because we need to pick up the signal pipe
|
|
||||||
* from the parent process.
|
|
||||||
*/
|
|
||||||
#ifdef WIN32
|
|
||||||
pgwin32_signal_initialize();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* In EXEC_BACKEND case we will not have inherited these settings */
|
/* In EXEC_BACKEND case we will not have inherited these settings */
|
||||||
pqinitmask();
|
pqinitmask();
|
||||||
PG_SETMASK(&BlockSig);
|
PG_SETMASK(&BlockSig);
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
#include "storage/latch.h"
|
#include "storage/latch.h"
|
||||||
#include "storage/pmsignal.h"
|
#include "storage/pmsignal.h"
|
||||||
#include "storage/shmem.h"
|
#include "storage/shmem.h"
|
||||||
|
#include "utils/memutils.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Select the fd readiness primitive to use. Normally the "most modern"
|
* Select the fd readiness primitive to use. Normally the "most modern"
|
||||||
|
@ -129,6 +130,12 @@ struct WaitEventSet
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* A common WaitEventSet used to implement WatchLatch() */
|
||||||
|
static WaitEventSet *LatchWaitSet;
|
||||||
|
|
||||||
|
/* The position of the latch in LatchWaitSet. */
|
||||||
|
#define LatchWaitSetLatchPos 0
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
/* Are we currently in WaitLatch? The signal handler would like to know. */
|
/* Are we currently in WaitLatch? The signal handler would like to know. */
|
||||||
static volatile sig_atomic_t waiting = false;
|
static volatile sig_atomic_t waiting = false;
|
||||||
|
@ -242,6 +249,24 @@ InitializeLatchSupport(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
InitializeLatchWaitSet(void)
|
||||||
|
{
|
||||||
|
int latch_pos PG_USED_FOR_ASSERTS_ONLY;
|
||||||
|
|
||||||
|
Assert(LatchWaitSet == NULL);
|
||||||
|
|
||||||
|
/* Set up the WaitEventSet used by WaitLatch(). */
|
||||||
|
LatchWaitSet = CreateWaitEventSet(TopMemoryContext, 2);
|
||||||
|
latch_pos = AddWaitEventToSet(LatchWaitSet, WL_LATCH_SET, PGINVALID_SOCKET,
|
||||||
|
MyLatch, NULL);
|
||||||
|
if (IsUnderPostmaster)
|
||||||
|
AddWaitEventToSet(LatchWaitSet, WL_EXIT_ON_PM_DEATH,
|
||||||
|
PGINVALID_SOCKET, NULL, NULL);
|
||||||
|
|
||||||
|
Assert(latch_pos == LatchWaitSetLatchPos);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize a process-local latch.
|
* Initialize a process-local latch.
|
||||||
*/
|
*/
|
||||||
|
@ -365,8 +390,31 @@ int
|
||||||
WaitLatch(Latch *latch, int wakeEvents, long timeout,
|
WaitLatch(Latch *latch, int wakeEvents, long timeout,
|
||||||
uint32 wait_event_info)
|
uint32 wait_event_info)
|
||||||
{
|
{
|
||||||
return WaitLatchOrSocket(latch, wakeEvents, PGINVALID_SOCKET, timeout,
|
WaitEvent event;
|
||||||
wait_event_info);
|
|
||||||
|
/* Postmaster-managed callers must handle postmaster death somehow. */
|
||||||
|
Assert(!IsUnderPostmaster ||
|
||||||
|
(wakeEvents & WL_EXIT_ON_PM_DEATH) ||
|
||||||
|
(wakeEvents & WL_POSTMASTER_DEATH));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some callers may have a latch other than MyLatch, or no latch at all,
|
||||||
|
* or want to handle postmaster death differently. It's cheap to assign
|
||||||
|
* those, so just do it every time.
|
||||||
|
*/
|
||||||
|
if (!(wakeEvents & WL_LATCH_SET))
|
||||||
|
latch = NULL;
|
||||||
|
ModifyWaitEvent(LatchWaitSet, LatchWaitSetLatchPos, WL_LATCH_SET, latch);
|
||||||
|
LatchWaitSet->exit_on_postmaster_death =
|
||||||
|
((wakeEvents & WL_EXIT_ON_PM_DEATH) != 0);
|
||||||
|
|
||||||
|
if (WaitEventSetWait(LatchWaitSet,
|
||||||
|
(wakeEvents & WL_TIMEOUT) ? timeout : -1,
|
||||||
|
&event, 1,
|
||||||
|
wait_event_info) == 0)
|
||||||
|
return WL_TIMEOUT;
|
||||||
|
else
|
||||||
|
return event.events;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -830,7 +878,8 @@ AddWaitEventToSet(WaitEventSet *set, uint32 events, pgsocket fd, Latch *latch,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Change the event mask and, in the WL_LATCH_SET case, the latch associated
|
* Change the event mask and, in the WL_LATCH_SET case, the latch associated
|
||||||
* with the WaitEvent.
|
* with the WaitEvent. The latch may be changed to NULL to disable the latch
|
||||||
|
* temporarily, and then set back to a latch later.
|
||||||
*
|
*
|
||||||
* 'pos' is the id returned by AddWaitEventToSet.
|
* 'pos' is the id returned by AddWaitEventToSet.
|
||||||
*/
|
*/
|
||||||
|
@ -862,7 +911,6 @@ ModifyWaitEvent(WaitEventSet *set, int pos, uint32 events, Latch *latch)
|
||||||
if (event->events & WL_LATCH_SET &&
|
if (event->events & WL_LATCH_SET &&
|
||||||
events != event->events)
|
events != event->events)
|
||||||
{
|
{
|
||||||
/* we could allow to disable latch events for a while */
|
|
||||||
elog(ERROR, "cannot modify latch event");
|
elog(ERROR, "cannot modify latch event");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -120,6 +120,7 @@ InitPostmasterChild(void)
|
||||||
InitializeLatchSupport();
|
InitializeLatchSupport();
|
||||||
MyLatch = &LocalLatchData;
|
MyLatch = &LocalLatchData;
|
||||||
InitLatch(MyLatch);
|
InitLatch(MyLatch);
|
||||||
|
InitializeLatchWaitSet();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If possible, make this process a group leader, so that the postmaster
|
* If possible, make this process a group leader, so that the postmaster
|
||||||
|
@ -152,6 +153,7 @@ InitStandaloneProcess(const char *argv0)
|
||||||
InitializeLatchSupport();
|
InitializeLatchSupport();
|
||||||
MyLatch = &LocalLatchData;
|
MyLatch = &LocalLatchData;
|
||||||
InitLatch(MyLatch);
|
InitLatch(MyLatch);
|
||||||
|
InitializeLatchWaitSet();
|
||||||
|
|
||||||
/* Compute paths, no postmaster to inherit from */
|
/* Compute paths, no postmaster to inherit from */
|
||||||
if (my_exec_path[0] == '\0')
|
if (my_exec_path[0] == '\0')
|
||||||
|
|
|
@ -176,6 +176,7 @@ extern int WaitLatch(Latch *latch, int wakeEvents, long timeout,
|
||||||
uint32 wait_event_info);
|
uint32 wait_event_info);
|
||||||
extern int WaitLatchOrSocket(Latch *latch, int wakeEvents,
|
extern int WaitLatchOrSocket(Latch *latch, int wakeEvents,
|
||||||
pgsocket sock, long timeout, uint32 wait_event_info);
|
pgsocket sock, long timeout, uint32 wait_event_info);
|
||||||
|
extern void InitializeLatchWaitSet(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unix implementation uses SIGUSR1 for inter-process signaling.
|
* Unix implementation uses SIGUSR1 for inter-process signaling.
|
||||||
|
|
Loading…
Reference in New Issue