Allow condition variables to be used in interrupt code.
authorThomas Munro <tmunro@postgresql.org>
Mon, 1 Mar 2021 03:28:12 +0000 (16:28 +1300)
committerThomas Munro <tmunro@postgresql.org>
Mon, 1 Mar 2021 04:24:47 +0000 (17:24 +1300)
Adjust the condition variable sleep loop to work correctly when code
reached by its internal CHECK_FOR_INTERRUPTS() call interacts with
another condition variable.

There are no such cases currently, but a proposed patch would do this.

Discussion: https://postgr.es/m/CA+hUKGLdemy2gBm80kz20GTe6hNVwoErE8KwcJk6-U56oStjtg@mail.gmail.com

src/backend/storage/lmgr/condition_variable.c

index 0a61ff0031fefb83a6395dc525e92e3d1ee9b912..80d70c154cf7c430e2e9c6955f4622462fb96e22 100644 (file)
@@ -165,8 +165,6 @@ ConditionVariableTimedSleep(ConditionVariable *cv, long timeout,
        /* Reset latch before examining the state of the wait list. */
        ResetLatch(MyLatch);
 
-       CHECK_FOR_INTERRUPTS();
-
        /*
         * If this process has been taken out of the wait list, then we know
         * that it has been signaled by ConditionVariableSignal (or
@@ -190,6 +188,15 @@ ConditionVariableTimedSleep(ConditionVariable *cv, long timeout,
        }
        SpinLockRelease(&cv->mutex);
 
+       /*
+        * Check for interrupts, and return spuriously if that caused the
+        * current sleep target to change (meaning that interrupt handler code
+        * waited for a different condition variable).
+        */
+       CHECK_FOR_INTERRUPTS();
+       if (cv != cv_sleep_target)
+           done = true;
+
        /* We were signaled, so return */
        if (done)
            return false;