v5-0002-Add-support-for-lower-priority-latches.patch
text/x-patch
Filename: v5-0002-Add-support-for-lower-priority-latches.patch
Type: text/x-patch
Part: 1
Patch
Format: format-patch
Series: patch v5-0002
Subject: Add support for lower priority latches.
| File | + | − |
|---|---|---|
| src/backend/storage/ipc/latch.c | 42 | 13 |
| src/include/storage/latch.h | 1 | 0 |
From 05cc76fbbd4fd6bd7b154c4ab732df4e755117d1 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Mon, 13 Dec 2021 14:31:18 +1300
Subject: [PATCH v5 2/3] Add support for lower priority latches.
Normally, latch events that can be detected by reading shared memory are
reported immediately, without entering the kernel to poll for any other
conditions that might also be reportable.
Add a new variant of WL_LATCH_SET called WL_LATCH_SET_LOPRIO that
disables this high priority treatment, so that you can ask for all events
that are currently pending, even if a latch would normally hide any
others.
Discussion: https://postgr.es/m/77def86b27e41f0efcba411460e929ae%40postgrespro.ru
---
src/backend/storage/ipc/latch.c | 55 +++++++++++++++++++++++++--------
src/include/storage/latch.h | 1 +
2 files changed, 43 insertions(+), 13 deletions(-)
diff --git a/src/backend/storage/ipc/latch.c b/src/backend/storage/ipc/latch.c
index 54e928c564..8850ef740d 100644
--- a/src/backend/storage/ipc/latch.c
+++ b/src/backend/storage/ipc/latch.c
@@ -102,9 +102,13 @@ struct WaitEventSet
* said latch, and latch_pos the offset in the ->events array. This is
* useful because we check the state of the latch before performing doing
* syscalls related to waiting.
+ *
+ * WL_LATCH_SET_LOPRIO is converted to WL_LATCH_SET and latch_loprio is
+ * set.
*/
Latch *latch;
int latch_pos;
+ bool latch_loprio;
/*
* WL_EXIT_ON_PM_DEATH is converted to WL_POSTMASTER_DEATH, but this flag
@@ -833,6 +837,7 @@ FreeWaitEventSet(WaitEventSet *set)
/* ---
* Add an event to the set. Possible events are:
* - WL_LATCH_SET: Wait for the latch to be set
+ * - WL_LATCH_SET_LOPRIO: Wait for the latch to be set, lower priority
* - WL_POSTMASTER_DEATH: Wait for postmaster to die
* - WL_SOCKET_READABLE: Wait for socket to become readable,
* can be combined in one event with other WL_SOCKET_* events
@@ -868,6 +873,12 @@ AddWaitEventToSet(WaitEventSet *set, uint32 events, pgsocket fd, Latch *latch,
/* not enough space */
Assert(set->nevents < set->nevents_space);
+ if (events == WL_LATCH_SET_LOPRIO)
+ {
+ events = WL_LATCH_SET;
+ set->latch_loprio = true;
+ }
+
if (events == WL_EXIT_ON_PM_DEATH)
{
events = WL_POSTMASTER_DEATH;
@@ -1354,9 +1365,8 @@ WaitEventSetWait(WaitEventSet *set, long timeout,
int rc;
/*
- * Check if the latch is set already. If so, leave the loop
- * immediately, avoid blocking again. We don't attempt to report any
- * other events that might also be satisfied.
+ * Check if the latch is set already first. We may be able to exit the
+ * loop and avoid a system call.
*
* If someone sets the latch between this and the
* WaitEventSetWaitBlock() below, the setter will write a byte to the
@@ -1401,7 +1411,28 @@ WaitEventSetWait(WaitEventSet *set, long timeout,
/* could have been set above */
set->latch->maybe_sleeping = false;
- break;
+ if (!set->latch_loprio || returned_events == nevents)
+ {
+ /*
+ * Latch events normally have higher priority than other
+ * events: we report them immediately, rather than entering the
+ * kernel to look for more events that might be pending.
+ */
+ break;
+ }
+ else
+ {
+ /*
+ * The caller opted for lower priority latches, and there is
+ * space to poll for more events. Set timeout to zero, because
+ * we already have an event to report to the caller.
+ * WaitEventSetWaitBlock() won't double-report the latch,
+ * because we cleared latch->maybe_sleeping.
+ */
+ Assert(returned_events == 1);
+ Assert(nevents > 1);
+ cur_timeout = 0;
+ }
}
/*
@@ -1410,18 +1441,16 @@ WaitEventSetWait(WaitEventSet *set, long timeout,
* to retry, everything >= 1 is the number of returned events.
*/
rc = WaitEventSetWaitBlock(set, cur_timeout,
- occurred_events, nevents);
+ occurred_events,
+ nevents - returned_events);
if (set->latch)
- {
- Assert(set->latch->maybe_sleeping);
set->latch->maybe_sleeping = false;
- }
if (rc == -1)
break; /* timeout occurred */
else
- returned_events = rc;
+ returned_events += rc;
/* If we're not done, update cur_timeout for next iteration */
if (returned_events == 0 && timeout >= 0)
@@ -1509,7 +1538,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
/* Drain the signalfd. */
drain();
- if (set->latch && set->latch->is_set)
+ if (set->latch && set->latch->maybe_sleeping && set->latch->is_set)
{
occurred_events->fd = PGINVALID_SOCKET;
occurred_events->events = WL_LATCH_SET;
@@ -1667,7 +1696,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
if (cur_event->events == WL_LATCH_SET &&
cur_kqueue_event->filter == EVFILT_SIGNAL)
{
- if (set->latch && set->latch->is_set)
+ if (set->latch && set->latch->maybe_sleeping && set->latch->is_set)
{
occurred_events->fd = PGINVALID_SOCKET;
occurred_events->events = WL_LATCH_SET;
@@ -1792,7 +1821,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
/* There's data in the self-pipe, clear it. */
drain();
- if (set->latch && set->latch->is_set)
+ if (set->latch && set->latch->maybe_sleeping && set->latch->is_set)
{
occurred_events->fd = PGINVALID_SOCKET;
occurred_events->events = WL_LATCH_SET;
@@ -1974,7 +2003,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
if (!ResetEvent(set->handles[cur_event->pos + 1]))
elog(ERROR, "ResetEvent failed: error code %lu", GetLastError());
- if (set->latch && set->latch->is_set)
+ if (set->latch && set->latch->maybe_sleeping && set->latch->is_set)
{
occurred_events->fd = PGINVALID_SOCKET;
occurred_events->events = WL_LATCH_SET;
diff --git a/src/include/storage/latch.h b/src/include/storage/latch.h
index d78ff0bede..4da655d052 100644
--- a/src/include/storage/latch.h
+++ b/src/include/storage/latch.h
@@ -139,6 +139,7 @@ typedef struct Latch
WL_SOCKET_WRITEABLE | \
WL_SOCKET_CONNECTED | \
WL_SOCKET_CLOSED)
+#define WL_LATCH_SET_LOPRIO (1 << 8)
typedef struct WaitEvent
{
--
2.33.1