Skip to content

Commit 6148656

Browse files
committed
Use EVFILT_SIGNAL for kqueue latches.
Cut down on system calls and other overheads by waiting for SIGURG explicitly with kqueue instead of using a signal handler and self-pipe. Affects *BSD and macOS systems. This leaves only the poll implementation with a signal handler and the traditional self-pipe trick. Discussion: https://postgr.es/m/CA+hUKGJjxPDpzBE0a3hyUywBvaZuC89yx3jK9RFZgfv_KHU7gg@mail.gmail.com
1 parent 6a2a70a commit 6148656

File tree

1 file changed

+38
-17
lines changed

1 file changed

+38
-17
lines changed

src/backend/storage/ipc/latch.c

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
* don't need to register a signal handler or create our own self-pipe. We
1919
* assume that any system that has Linux epoll() also has Linux signalfd().
2020
*
21+
* The kqueue() implementation waits for SIGURG with EVFILT_SIGNAL.
22+
*
2123
* The Windows implementation uses Windows events that are inherited by all
2224
* postmaster child processes. There's no need for the self-pipe trick there.
2325
*
@@ -150,7 +152,7 @@ static volatile sig_atomic_t waiting = false;
150152
static int signal_fd = -1;
151153
#endif
152154

153-
#if defined(WAIT_USE_POLL) || defined(WAIT_USE_KQUEUE)
155+
#if defined(WAIT_USE_POLL)
154156
/* Read and write ends of the self-pipe */
155157
static int selfpipe_readfd = -1;
156158
static int selfpipe_writefd = -1;
@@ -189,7 +191,7 @@ static inline int WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
189191
void
190192
InitializeLatchSupport(void)
191193
{
192-
#if defined(WAIT_USE_POLL) || defined(WAIT_USE_KQUEUE)
194+
#if defined(WAIT_USE_POLL)
193195
int pipefd[2];
194196

195197
if (IsUnderPostmaster)
@@ -277,6 +279,11 @@ InitializeLatchSupport(void)
277279
elog(FATAL, "signalfd() failed");
278280
ReserveExternalFD();
279281
#endif
282+
283+
#ifdef WAIT_USE_KQUEUE
284+
/* Ignore SIGURG, because we'll receive it via kqueue. */
285+
pqsignal(SIGURG, SIG_IGN);
286+
#endif
280287
}
281288

282289
void
@@ -300,7 +307,7 @@ InitializeLatchWaitSet(void)
300307
void
301308
ShutdownLatchSupport(void)
302309
{
303-
#if defined(WAIT_USE_POLL) || defined(WAIT_USE_KQUEUE)
310+
#if defined(WAIT_USE_POLL)
304311
pqsignal(SIGURG, SIG_IGN);
305312
#endif
306313

@@ -310,7 +317,7 @@ ShutdownLatchSupport(void)
310317
LatchWaitSet = NULL;
311318
}
312319

313-
#if defined(WAIT_USE_POLL) || defined(WAIT_USE_KQUEUE)
320+
#if defined(WAIT_USE_POLL)
314321
close(selfpipe_readfd);
315322
close(selfpipe_writefd);
316323
selfpipe_readfd = -1;
@@ -335,7 +342,7 @@ InitLatch(Latch *latch)
335342
latch->owner_pid = MyProcPid;
336343
latch->is_shared = false;
337344

338-
#if defined(WAIT_USE_POLL) || defined(WAIT_USE_KQUEUE)
345+
#if defined(WAIT_USE_POLL)
339346
/* Assert InitializeLatchSupport has been called in this process */
340347
Assert(selfpipe_readfd >= 0 && selfpipe_owner_pid == MyProcPid);
341348
#elif defined(WAIT_USE_WIN32)
@@ -399,7 +406,7 @@ OwnLatch(Latch *latch)
399406
/* Sanity checks */
400407
Assert(latch->is_shared);
401408

402-
#if defined(WAIT_USE_POLL) || defined(WAIT_USE_KQUEUE)
409+
#if defined(WAIT_USE_POLL)
403410
/* Assert InitializeLatchSupport has been called in this process */
404411
Assert(selfpipe_readfd >= 0 && selfpipe_owner_pid == MyProcPid);
405412
#endif
@@ -611,7 +618,7 @@ SetLatch(Latch *latch)
611618
return;
612619
else if (owner_pid == MyProcPid)
613620
{
614-
#if defined(WAIT_USE_POLL) || defined(WAIT_USE_KQUEUE)
621+
#if defined(WAIT_USE_POLL)
615622
if (waiting)
616623
sendSelfPipeByte();
617624
#else
@@ -898,13 +905,15 @@ AddWaitEventToSet(WaitEventSet *set, uint32 events, pgsocket fd, Latch *latch,
898905
{
899906
set->latch = latch;
900907
set->latch_pos = event->pos;
901-
#if defined(WAIT_USE_POLL) || defined(WAIT_USE_KQUEUE)
908+
#if defined(WAIT_USE_POLL)
902909
event->fd = selfpipe_readfd;
903910
#elif defined(WAIT_USE_EPOLL)
904911
event->fd = signal_fd;
905912
#else
906913
event->fd = PGINVALID_SOCKET;
914+
#ifdef WAIT_USE_EPOLL
907915
return event->pos;
916+
#endif
908917
#endif
909918
}
910919
else if (events == WL_POSTMASTER_DEATH)
@@ -1125,6 +1134,18 @@ WaitEventAdjustKqueueAddPostmaster(struct kevent *k_ev, WaitEvent *event)
11251134
AccessWaitEvent(k_ev) = event;
11261135
}
11271136

1137+
static inline void
1138+
WaitEventAdjustKqueueAddLatch(struct kevent *k_ev, WaitEvent *event)
1139+
{
1140+
/* For now latch can only be added, not removed. */
1141+
k_ev->ident = SIGURG;
1142+
k_ev->filter = EVFILT_SIGNAL;
1143+
k_ev->flags = EV_ADD;
1144+
k_ev->fflags = 0;
1145+
k_ev->data = 0;
1146+
AccessWaitEvent(k_ev) = event;
1147+
}
1148+
11281149
/*
11291150
* old_events is the previous event mask, used to compute what has changed.
11301151
*/
@@ -1156,18 +1177,21 @@ WaitEventAdjustKqueue(WaitEventSet *set, WaitEvent *event, int old_events)
11561177
*/
11571178
WaitEventAdjustKqueueAddPostmaster(&k_ev[count++], event);
11581179
}
1180+
else if (event->events == WL_LATCH_SET)
1181+
{
1182+
/* We detect latch wakeup using a signal event. */
1183+
WaitEventAdjustKqueueAddLatch(&k_ev[count++], event);
1184+
}
11591185
else
11601186
{
11611187
/*
11621188
* We need to compute the adds and deletes required to get from the
11631189
* old event mask to the new event mask, since kevent treats readable
11641190
* and writable as separate events.
11651191
*/
1166-
if (old_events == WL_LATCH_SET ||
1167-
(old_events & WL_SOCKET_READABLE))
1192+
if (old_events & WL_SOCKET_READABLE)
11681193
old_filt_read = true;
1169-
if (event->events == WL_LATCH_SET ||
1170-
(event->events & WL_SOCKET_READABLE))
1194+
if (event->events & WL_SOCKET_READABLE)
11711195
new_filt_read = true;
11721196
if (old_events & WL_SOCKET_WRITEABLE)
11731197
old_filt_write = true;
@@ -1620,11 +1644,8 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
16201644
occurred_events->events = 0;
16211645

16221646
if (cur_event->events == WL_LATCH_SET &&
1623-
cur_kqueue_event->filter == EVFILT_READ)
1647+
cur_kqueue_event->filter == EVFILT_SIGNAL)
16241648
{
1625-
/* There's data in the self-pipe, clear it. */
1626-
drain();
1627-
16281649
if (set->latch && set->latch->is_set)
16291650
{
16301651
occurred_events->fd = PGINVALID_SOCKET;
@@ -1999,7 +2020,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
19992020
}
20002021
#endif
20012022

2002-
#if defined(WAIT_USE_POLL) || defined(WAIT_USE_KQUEUE)
2023+
#if defined(WAIT_USE_POLL)
20032024

20042025
/*
20052026
* SetLatch uses SIGURG to wake up the process waiting on the latch.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy