]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Optimize latches to send fewer signals.
authorThomas Munro <tmunro@postgresql.org>
Sun, 28 Feb 2021 22:51:15 +0000 (11:51 +1300)
committerThomas Munro <tmunro@postgresql.org>
Sun, 28 Feb 2021 23:44:12 +0000 (12:44 +1300)
Don't send signals to processes that aren't sleeping.

Author: Andres Freund <andres@anarazel.de>
Discussion: https://postgr.es/m/CA+hUKGJjxPDpzBE0a3hyUywBvaZuC89yx3jK9RFZgfv_KHU7gg@mail.gmail.com

src/backend/storage/ipc/latch.c
src/include/storage/latch.h

index 79b9627831fcadd07d6d0a4378a7f12988bc24aa..eacf8d51ea0833462966b151f46f099630e10ba2 100644 (file)
@@ -274,6 +274,7 @@ void
 InitLatch(Latch *latch)
 {
        latch->is_set = false;
+       latch->maybe_sleeping = false;
        latch->owner_pid = MyProcPid;
        latch->is_shared = false;
 
@@ -321,6 +322,7 @@ InitSharedLatch(Latch *latch)
 #endif
 
        latch->is_set = false;
+       latch->maybe_sleeping = false;
        latch->owner_pid = 0;
        latch->is_shared = true;
 }
@@ -523,6 +525,10 @@ SetLatch(Latch *latch)
 
        latch->is_set = true;
 
+       pg_memory_barrier();
+       if (!latch->maybe_sleeping)
+               return;
+
 #ifndef WIN32
 
        /*
@@ -589,6 +595,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;
 
@@ -1270,6 +1277,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;
@@ -1280,6 +1295,9 @@ WaitEventSetWait(WaitEventSet *set, long timeout,
                        occurred_events++;
                        returned_events++;
 
+                       /* could have been set above */
+                       set->latch->maybe_sleeping = false;
+
                        break;
                }
 
@@ -1291,6 +1309,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
index 1468f30a8e00e50ed9bfa8983d6a40ffc8ca6fec..393591be03c098103e6bc0ede4061e05dc7066b0 100644 (file)
 typedef struct Latch
 {
        sig_atomic_t is_set;
+       sig_atomic_t maybe_sleeping;
        bool            is_shared;
        int                     owner_pid;
 #ifdef WIN32