1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-31 22:04:40 +03:00

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:
Thomas Munro
2020-07-30 17:08:11 +12:00
parent d6c08e29e7
commit 3347c982ba
4 changed files with 67 additions and 16 deletions

View File

@ -56,6 +56,7 @@
#include "storage/latch.h"
#include "storage/pmsignal.h"
#include "storage/shmem.h"
#include "utils/memutils.h"
/*
* Select the fd readiness primitive to use. Normally the "most modern"
@ -129,6 +130,12 @@ struct WaitEventSet
#endif
};
/* A common WaitEventSet used to implement WatchLatch() */
static WaitEventSet *LatchWaitSet;
/* The position of the latch in LatchWaitSet. */
#define LatchWaitSetLatchPos 0
#ifndef WIN32
/* Are we currently in WaitLatch? The signal handler would like to know. */
static volatile sig_atomic_t waiting = false;
@ -242,6 +249,24 @@ InitializeLatchSupport(void)
#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.
*/
@ -365,8 +390,31 @@ int
WaitLatch(Latch *latch, int wakeEvents, long timeout,
uint32 wait_event_info)
{
return WaitLatchOrSocket(latch, wakeEvents, PGINVALID_SOCKET, timeout,
wait_event_info);
WaitEvent event;
/* 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
* 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.
*/
@ -862,7 +911,6 @@ ModifyWaitEvent(WaitEventSet *set, int pos, uint32 events, Latch *latch)
if (event->events & WL_LATCH_SET &&
events != event->events)
{
/* we could allow to disable latch events for a while */
elog(ERROR, "cannot modify latch event");
}