From: Andres Freund Date: Sat, 31 Oct 2020 00:12:09 +0000 (-0700) Subject: latch / signal perf stuff: generic X-Git-Url: http://git.postgresql.org/gitweb/review?a=commitdiff_plain;h=8e645b68febc18bb984176c69bbc6247e21a8059;p=users%2Fandresfreund%2Fpostgres.git latch / signal perf stuff: generic Author: Reviewed-By: Discussion: https://postgr.es/m/ Backpatch: --- diff --git a/src/backend/libpq/pqsignal.c b/src/backend/libpq/pqsignal.c index b43af22030..8d97b008ab 100644 --- a/src/backend/libpq/pqsignal.c +++ b/src/backend/libpq/pqsignal.c @@ -19,7 +19,8 @@ /* Global variables */ -sigset_t UnBlockSig, +sigset_t SleepSig, + UnBlockSig, BlockSig, StartupBlockSig; @@ -40,6 +41,7 @@ sigset_t UnBlockSig, void pqinitmask(void) { + sigemptyset(&SleepSig); sigemptyset(&UnBlockSig); /* First set all signals, then clear some. */ @@ -94,6 +96,8 @@ pqinitmask(void) #ifdef SIGALRM sigdelset(&StartupBlockSig, SIGALRM); #endif + + sigaddset(&UnBlockSig, SIGURG); } /* diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 47e60ca561..211859f77d 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -464,7 +464,9 @@ AutoVacLauncherMain(int argc, char *argv[]) pqsignal(SIGPIPE, SIG_IGN); pqsignal(SIGUSR1, procsignal_sigusr1_handler); + pqsignal(SIGUSR1, procsignal_sigusr1_handler); pqsignal(SIGUSR2, avl_sigusr2_handler); + pqsignal(SIGURG, latch_sigurg_handler); pqsignal(SIGFPE, FloatExceptionHandler); pqsignal(SIGCHLD, SIG_DFL); @@ -1543,6 +1545,7 @@ AutoVacWorkerMain(int argc, char *argv[]) pqsignal(SIGPIPE, SIG_IGN); pqsignal(SIGUSR1, procsignal_sigusr1_handler); pqsignal(SIGUSR2, SIG_IGN); + pqsignal(SIGURG, latch_sigurg_handler); pqsignal(SIGFPE, FloatExceptionHandler); pqsignal(SIGCHLD, SIG_DFL); diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index dd3dad3de3..c0282e882c 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -330,6 +330,7 @@ BackgroundWorkerStateChange(bool allow_new_workers) pg_memory_barrier(); slot->pid = 0; slot->in_use = false; + /* FIXME: shouldn't this use SetLatch() or something */ if (notify_pid != 0) kill(notify_pid, SIGUSR1); @@ -779,6 +780,7 @@ StartBackgroundWorker(void) */ pqsignal(SIGINT, StatementCancelHandler); pqsignal(SIGUSR1, procsignal_sigusr1_handler); + pqsignal(SIGURG, latch_sigurg_handler); pqsignal(SIGFPE, FloatExceptionHandler); /* XXX Any other handlers needed here? */ @@ -787,6 +789,7 @@ StartBackgroundWorker(void) { pqsignal(SIGINT, SIG_IGN); pqsignal(SIGUSR1, bgworker_sigusr1_handler); + pqsignal(SIGURG, latch_sigurg_handler); pqsignal(SIGFPE, SIG_IGN); } pqsignal(SIGTERM, bgworker_die); diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c index 715d5195bb..66864a42df 100644 --- a/src/backend/postmaster/bgwriter.c +++ b/src/backend/postmaster/bgwriter.c @@ -109,6 +109,7 @@ BackgroundWriterMain(void) pqsignal(SIGPIPE, SIG_IGN); pqsignal(SIGUSR1, procsignal_sigusr1_handler); pqsignal(SIGUSR2, SIG_IGN); + pqsignal(SIGURG, latch_sigurg_handler); /* * Reset some signals that are accepted by postmaster but not here diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 524fc4f112..e208b5878d 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -203,6 +203,7 @@ CheckpointerMain(void) pqsignal(SIGPIPE, SIG_IGN); pqsignal(SIGUSR1, procsignal_sigusr1_handler); pqsignal(SIGUSR2, SignalHandlerForShutdownRequest); + pqsignal(SIGURG, latch_sigurg_handler); /* * Reset some signals that are accepted by postmaster but not here diff --git a/src/backend/postmaster/startup.c b/src/backend/postmaster/startup.c index f781fdc6fc..1fce630b47 100644 --- a/src/backend/postmaster/startup.c +++ b/src/backend/postmaster/startup.c @@ -180,6 +180,7 @@ StartupProcessMain(void) pqsignal(SIGPIPE, SIG_IGN); pqsignal(SIGUSR1, procsignal_sigusr1_handler); pqsignal(SIGUSR2, StartupProcTriggerHandler); + pqsignal(SIGURG, latch_sigurg_handler); /* * Reset some signals that are accepted by postmaster but not here diff --git a/src/backend/postmaster/walwriter.c b/src/backend/postmaster/walwriter.c index 5f36796fcd..92ed7519a2 100644 --- a/src/backend/postmaster/walwriter.c +++ b/src/backend/postmaster/walwriter.c @@ -107,6 +107,7 @@ WalWriterMain(void) pqsignal(SIGPIPE, SIG_IGN); pqsignal(SIGUSR1, procsignal_sigusr1_handler); pqsignal(SIGUSR2, SIG_IGN); /* not used */ + pqsignal(SIGURG, latch_sigurg_handler); /* * Reset some signals that are accepted by postmaster but not here diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c index 723f513d8b..751c2d38cf 100644 --- a/src/backend/replication/walreceiver.c +++ b/src/backend/replication/walreceiver.c @@ -264,6 +264,7 @@ WalReceiverMain(void) pqsignal(SIGPIPE, SIG_IGN); pqsignal(SIGUSR1, procsignal_sigusr1_handler); pqsignal(SIGUSR2, SIG_IGN); + pqsignal(SIGURG, latch_sigurg_handler); /* Reset some signals that are accepted by postmaster but not here */ pqsignal(SIGCHLD, SIG_DFL); diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index fe0d368a35..dfdea4f4c4 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -3054,6 +3054,7 @@ WalSndSignals(void) pqsignal(SIGUSR1, procsignal_sigusr1_handler); pqsignal(SIGUSR2, WalSndLastCycleHandler); /* request a last cycle and * shutdown */ + pqsignal(SIGURG, latch_sigurg_handler); /* Reset some signals that are accepted by postmaster but not here */ pqsignal(SIGCHLD, SIG_DFL); diff --git a/src/backend/storage/ipc/latch.c b/src/backend/storage/ipc/latch.c index f2d005eea0..1d9a375078 100644 --- a/src/backend/storage/ipc/latch.c +++ b/src/backend/storage/ipc/latch.c @@ -46,6 +46,7 @@ #include #endif +#include "libpq/pqsignal.h" #include "miscadmin.h" #include "pgstat.h" #include "port/atomics.h" @@ -274,6 +275,7 @@ void InitLatch(Latch *latch) { latch->is_set = false; + latch->maybe_sleeping = false; latch->owner_pid = MyProcPid; latch->is_shared = false; @@ -321,6 +323,7 @@ InitSharedLatch(Latch *latch) #endif latch->is_set = false; + latch->maybe_sleeping = false; latch->owner_pid = 0; latch->is_shared = true; } @@ -523,6 +526,11 @@ SetLatch(Latch *latch) latch->is_set = true; + pg_memory_barrier(); + + if (!latch->maybe_sleeping) + return; + #ifndef WIN32 /* @@ -556,7 +564,7 @@ SetLatch(Latch *latch) sendSelfPipeByte(); } else - kill(owner_pid, SIGUSR1); + kill(owner_pid, SIGURG); #else /* @@ -589,6 +597,7 @@ ResetLatch(Latch *latch) { /* Only the owner should reset the latch */ Assert(latch->owner_pid == MyProcPid); + Assert(latch->maybe_sleeping == false); latch->is_set = false; @@ -1289,6 +1298,14 @@ WaitEventSetWait(WaitEventSet *set, long timeout, * ordering, so that we cannot miss seeing is_set if a notification * has already been queued. */ + if (set->latch && !set->latch->is_set) + { + /* about to sleep on a latch */ + set->latch->maybe_sleeping = true; + pg_memory_barrier(); + /* and recheck */ + } + if (set->latch && set->latch->is_set) { occurred_events->fd = PGINVALID_SOCKET; @@ -1299,6 +1316,9 @@ WaitEventSetWait(WaitEventSet *set, long timeout, occurred_events++; returned_events++; + /* could have been set above */ + set->latch->maybe_sleeping = false; + break; } @@ -1310,6 +1330,12 @@ WaitEventSetWait(WaitEventSet *set, long timeout, rc = WaitEventSetWaitBlock(set, cur_timeout, occurred_events, nevents); + if (set->latch) + { + Assert(set->latch->maybe_sleeping); + set->latch->maybe_sleeping = false; + } + if (rc == -1) break; /* timeout occurred */ else @@ -1355,8 +1381,8 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout, struct epoll_event *cur_epoll_event; /* Sleep */ - rc = epoll_wait(set->epoll_fd, set->epoll_ret_events, - nevents, cur_timeout); + rc = epoll_pwait(set->epoll_fd, set->epoll_ret_events, + nevents, cur_timeout, &SleepSig); /* Check return code */ if (rc < 0) @@ -1399,6 +1425,8 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout, if (cur_event->events == WL_LATCH_SET && cur_epoll_event->events & (EPOLLIN | EPOLLERR | EPOLLHUP)) { + Assert(set->latch); + /* There's data in the self-pipe, clear it. */ drainSelfPipe(); @@ -1946,6 +1974,14 @@ latch_sigusr1_handler(void) if (waiting) sendSelfPipeByte(); } + +void +latch_sigurg_handler(SIGNAL_ARGS) +{ + if (waiting) + sendSelfPipeByte(); +} + #endif /* !WIN32 */ /* Send one byte to the self-pipe, to wake up WaitLatch */ diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 583efaecff..876abf1b51 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -587,7 +587,7 @@ procsignal_sigusr1_handler(SIGNAL_ARGS) SetLatch(MyLatch); - latch_sigusr1_handler(); + //latch_sigusr1_handler(); errno = save_errno; } diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 28055680aa..fdb9eab73a 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -3924,6 +3924,7 @@ PostgresMain(int argc, char *argv[], pqsignal(SIGPIPE, SIG_IGN); pqsignal(SIGUSR1, procsignal_sigusr1_handler); pqsignal(SIGUSR2, SIG_IGN); + pqsignal(SIGURG, latch_sigurg_handler); pqsignal(SIGFPE, FloatExceptionHandler); /* diff --git a/src/include/libpq/pqsignal.h b/src/include/libpq/pqsignal.h index 1161b13874..ee41e9732c 100644 --- a/src/include/libpq/pqsignal.h +++ b/src/include/libpq/pqsignal.h @@ -30,7 +30,8 @@ extern int pqsigsetmask(int mask); #define sigdelset(set, signum) (*(set) &= ~(sigmask(signum))) #endif /* WIN32 */ -extern sigset_t UnBlockSig, +extern sigset_t SleepSig, + UnBlockSig, BlockSig, StartupBlockSig; diff --git a/src/include/storage/latch.h b/src/include/storage/latch.h index 1468f30a8e..f13e399c08 100644 --- a/src/include/storage/latch.h +++ b/src/include/storage/latch.h @@ -110,6 +110,7 @@ typedef struct Latch { sig_atomic_t is_set; + sig_atomic_t maybe_sleeping; bool is_shared; int owner_pid; #ifdef WIN32 @@ -184,8 +185,10 @@ extern void InitializeLatchWaitSet(void); */ #ifndef WIN32 extern void latch_sigusr1_handler(void); +extern void latch_sigurg_handler(SIGNAL_ARGS); #else #define latch_sigusr1_handler() ((void) 0) +static inline void latch_sigurg_handler(SIGNAL_ARGS) {} #endif #endif /* LATCH_H */