diff options
author | Thomas Munro <tmunro@postgresql.org> | 2021-03-01 12:28:43 +1300 |
---|---|---|
committer | Thomas Munro <tmunro@postgresql.org> | 2021-03-01 14:20:04 +1300 |
commit | 6148656a0be1c6245fbcfcbbeb87541f1b173162 (patch) | |
tree | dc1f6132f8f21ea2c7c234930cc1ea0fa17253dc /src | |
parent | 6a2a70a02018d6362f9841cc2f499cc45405e86b (diff) | |
download | postgresql-6148656a0be1c6245fbcfcbbeb87541f1b173162.tar.gz postgresql-6148656a0be1c6245fbcfcbbeb87541f1b173162.zip |
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
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/storage/ipc/latch.c | 55 |
1 files changed, 38 insertions, 17 deletions
diff --git a/src/backend/storage/ipc/latch.c b/src/backend/storage/ipc/latch.c index ea6d9948abe..43a5fded103 100644 --- a/src/backend/storage/ipc/latch.c +++ b/src/backend/storage/ipc/latch.c @@ -18,6 +18,8 @@ * don't need to register a signal handler or create our own self-pipe. We * assume that any system that has Linux epoll() also has Linux signalfd(). * + * The kqueue() implementation waits for SIGURG with EVFILT_SIGNAL. + * * The Windows implementation uses Windows events that are inherited by all * postmaster child processes. There's no need for the self-pipe trick there. * @@ -150,7 +152,7 @@ static volatile sig_atomic_t waiting = false; static int signal_fd = -1; #endif -#if defined(WAIT_USE_POLL) || defined(WAIT_USE_KQUEUE) +#if defined(WAIT_USE_POLL) /* Read and write ends of the self-pipe */ static int selfpipe_readfd = -1; static int selfpipe_writefd = -1; @@ -189,7 +191,7 @@ static inline int WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout, void InitializeLatchSupport(void) { -#if defined(WAIT_USE_POLL) || defined(WAIT_USE_KQUEUE) +#if defined(WAIT_USE_POLL) int pipefd[2]; if (IsUnderPostmaster) @@ -277,6 +279,11 @@ InitializeLatchSupport(void) elog(FATAL, "signalfd() failed"); ReserveExternalFD(); #endif + +#ifdef WAIT_USE_KQUEUE + /* Ignore SIGURG, because we'll receive it via kqueue. */ + pqsignal(SIGURG, SIG_IGN); +#endif } void @@ -300,7 +307,7 @@ InitializeLatchWaitSet(void) void ShutdownLatchSupport(void) { -#if defined(WAIT_USE_POLL) || defined(WAIT_USE_KQUEUE) +#if defined(WAIT_USE_POLL) pqsignal(SIGURG, SIG_IGN); #endif @@ -310,7 +317,7 @@ ShutdownLatchSupport(void) LatchWaitSet = NULL; } -#if defined(WAIT_USE_POLL) || defined(WAIT_USE_KQUEUE) +#if defined(WAIT_USE_POLL) close(selfpipe_readfd); close(selfpipe_writefd); selfpipe_readfd = -1; @@ -335,7 +342,7 @@ InitLatch(Latch *latch) latch->owner_pid = MyProcPid; latch->is_shared = false; -#if defined(WAIT_USE_POLL) || defined(WAIT_USE_KQUEUE) +#if defined(WAIT_USE_POLL) /* Assert InitializeLatchSupport has been called in this process */ Assert(selfpipe_readfd >= 0 && selfpipe_owner_pid == MyProcPid); #elif defined(WAIT_USE_WIN32) @@ -399,7 +406,7 @@ OwnLatch(Latch *latch) /* Sanity checks */ Assert(latch->is_shared); -#if defined(WAIT_USE_POLL) || defined(WAIT_USE_KQUEUE) +#if defined(WAIT_USE_POLL) /* Assert InitializeLatchSupport has been called in this process */ Assert(selfpipe_readfd >= 0 && selfpipe_owner_pid == MyProcPid); #endif @@ -611,7 +618,7 @@ SetLatch(Latch *latch) return; else if (owner_pid == MyProcPid) { -#if defined(WAIT_USE_POLL) || defined(WAIT_USE_KQUEUE) +#if defined(WAIT_USE_POLL) if (waiting) sendSelfPipeByte(); #else @@ -898,14 +905,16 @@ AddWaitEventToSet(WaitEventSet *set, uint32 events, pgsocket fd, Latch *latch, { set->latch = latch; set->latch_pos = event->pos; -#if defined(WAIT_USE_POLL) || defined(WAIT_USE_KQUEUE) +#if defined(WAIT_USE_POLL) event->fd = selfpipe_readfd; #elif defined(WAIT_USE_EPOLL) event->fd = signal_fd; #else event->fd = PGINVALID_SOCKET; +#ifdef WAIT_USE_EPOLL return event->pos; #endif +#endif } else if (events == WL_POSTMASTER_DEATH) { @@ -1125,6 +1134,18 @@ WaitEventAdjustKqueueAddPostmaster(struct kevent *k_ev, WaitEvent *event) AccessWaitEvent(k_ev) = event; } +static inline void +WaitEventAdjustKqueueAddLatch(struct kevent *k_ev, WaitEvent *event) +{ + /* For now latch can only be added, not removed. */ + k_ev->ident = SIGURG; + k_ev->filter = EVFILT_SIGNAL; + k_ev->flags = EV_ADD; + k_ev->fflags = 0; + k_ev->data = 0; + AccessWaitEvent(k_ev) = event; +} + /* * old_events is the previous event mask, used to compute what has changed. */ @@ -1156,6 +1177,11 @@ WaitEventAdjustKqueue(WaitEventSet *set, WaitEvent *event, int old_events) */ WaitEventAdjustKqueueAddPostmaster(&k_ev[count++], event); } + else if (event->events == WL_LATCH_SET) + { + /* We detect latch wakeup using a signal event. */ + WaitEventAdjustKqueueAddLatch(&k_ev[count++], event); + } else { /* @@ -1163,11 +1189,9 @@ WaitEventAdjustKqueue(WaitEventSet *set, WaitEvent *event, int old_events) * old event mask to the new event mask, since kevent treats readable * and writable as separate events. */ - if (old_events == WL_LATCH_SET || - (old_events & WL_SOCKET_READABLE)) + if (old_events & WL_SOCKET_READABLE) old_filt_read = true; - if (event->events == WL_LATCH_SET || - (event->events & WL_SOCKET_READABLE)) + if (event->events & WL_SOCKET_READABLE) new_filt_read = true; if (old_events & WL_SOCKET_WRITEABLE) old_filt_write = true; @@ -1620,11 +1644,8 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout, occurred_events->events = 0; if (cur_event->events == WL_LATCH_SET && - cur_kqueue_event->filter == EVFILT_READ) + cur_kqueue_event->filter == EVFILT_SIGNAL) { - /* There's data in the self-pipe, clear it. */ - drain(); - if (set->latch && set->latch->is_set) { occurred_events->fd = PGINVALID_SOCKET; @@ -1999,7 +2020,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout, } #endif -#if defined(WAIT_USE_POLL) || defined(WAIT_USE_KQUEUE) +#if defined(WAIT_USE_POLL) /* * SetLatch uses SIGURG to wake up the process waiting on the latch. |