This is an automated email from the ASF dual-hosted git repository.

leborchuk pushed a commit to branch REL_2_STABLE
in repository https://gitbox.apache.org/repos/asf/cloudberry.git

commit 050e72fa251077b0f06b66a026dbbcdc39a97a45
Author: reshke <[email protected]>
AuthorDate: Thu Sep 24 09:57:33 2026 +0300

    Backport fixup: resolve twophase.c conflict in lwlock wait-list fix (keep 
mppSessionId init, adopt LW_WS_NOT_WAITING)
---
 src/backend/access/transam/twophase.c |  2 +-
 src/backend/storage/lmgr/lwlock.c     | 53 ++++++++++++++++++++---------------
 src/backend/storage/lmgr/proc.c       |  4 +--
 src/include/storage/lwlock.h          |  8 ++++++
 src/include/storage/proc.h            |  2 +-
 5 files changed, 42 insertions(+), 27 deletions(-)

diff --git a/src/backend/access/transam/twophase.c 
b/src/backend/access/transam/twophase.c
index 919f504ff56..e2ec5853786 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -501,7 +501,7 @@ MarkAsPreparingGuts(GlobalTransaction gxact, TransactionId 
xid, const char *gid,
        proc->tempNamespaceId = InvalidOid;
        proc->isBackgroundWorker = false;
        proc->mppSessionId = gp_session_id;
-       proc->lwWaiting = false;
+       proc->lwWaiting = LW_WS_NOT_WAITING;
        proc->lwWaitMode = 0;
        proc->waitLock = NULL;
        proc->waitProcLock = NULL;
diff --git a/src/backend/storage/lmgr/lwlock.c 
b/src/backend/storage/lmgr/lwlock.c
index f0cf60be6b5..2183fb0b387 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -995,6 +995,15 @@ LWLockWakeup(LWLock *lock)
                        wokeup_somebody = true;
                }
 
+               /*
+                * Signal that the process isn't on the wait list anymore. This 
allows
+                * LWLockDequeueSelf() to remove itself of the waitlist with a
+                * proclist_delete(), rather than having to check if it has been
+                * removed from the list.
+                */
+               Assert(waiter->lwWaiting == LW_WS_WAITING);
+               waiter->lwWaiting = LW_WS_PENDING_WAKEUP;
+
                /*
                 * Once we've woken up an exclusive lock, there's no point in 
waking
                 * up anybody else.
@@ -1052,7 +1061,7 @@ LWLockWakeup(LWLock *lock)
                 * another lock.
                 */
                pg_write_barrier();
-               waiter->lwWaiting = false;
+               waiter->lwWaiting = LW_WS_NOT_WAITING;
                PGSemaphoreUnlock(waiter->sem);
        }
 }
@@ -1073,7 +1082,7 @@ LWLockQueueSelf(LWLock *lock, LWLockMode mode)
        if (MyProc == NULL)
                elog(PANIC, "cannot wait without a PGPROC structure");
 
-       if (MyProc->lwWaiting)
+       if (MyProc->lwWaiting != LW_WS_NOT_WAITING)
                elog(PANIC, "queueing for lock while waiting on another one");
 
        LWLockWaitListLock(lock);
@@ -1081,7 +1090,7 @@ LWLockQueueSelf(LWLock *lock, LWLockMode mode)
        /* setting the flag is protected by the spinlock */
        pg_atomic_fetch_or_u32(&lock->state, LW_FLAG_HAS_WAITERS);
 
-       MyProc->lwWaiting = true;
+       MyProc->lwWaiting = LW_WS_WAITING;
        MyProc->lwWaitMode = mode;
 
        /* LW_WAIT_UNTIL_FREE waiters are always at the front of the queue */
@@ -1109,8 +1118,7 @@ LWLockQueueSelf(LWLock *lock, LWLockMode mode)
 static void
 LWLockDequeueSelf(LWLock *lock)
 {
-       bool            found = false;
-       proclist_mutable_iter iter;
+       bool            on_waitlist;
 
 #ifdef LWLOCK_STATS
        lwlock_stats *lwstats;
@@ -1123,18 +1131,13 @@ LWLockDequeueSelf(LWLock *lock)
        LWLockWaitListLock(lock);
 
        /*
-        * Can't just remove ourselves from the list, but we need to iterate 
over
-        * all entries as somebody else could have dequeued us.
+        * Remove ourselves from the waitlist, unless we've already been
+        * removed. The removal happens with the wait list lock held, so there's
+        * no race in this check.
         */
-       proclist_foreach_modify(iter, &lock->waiters, lwWaitLink)
-       {
-               if (iter.cur == MyProc->pgprocno)
-               {
-                       found = true;
-                       proclist_delete(&lock->waiters, iter.cur, lwWaitLink);
-                       break;
-               }
-       }
+       on_waitlist = MyProc->lwWaiting == LW_WS_WAITING;
+       if (on_waitlist)
+               proclist_delete(&lock->waiters, MyProc->pgprocno, lwWaitLink);
 
        if (proclist_is_empty(&lock->waiters) &&
                (pg_atomic_read_u32(&lock->state) & LW_FLAG_HAS_WAITERS) != 0)
@@ -1146,8 +1149,8 @@ LWLockDequeueSelf(LWLock *lock)
        LWLockWaitListUnlock(lock);
 
        /* clear waiting state again, nice for debugging */
-       if (found)
-               MyProc->lwWaiting = false;
+       if (on_waitlist)
+               MyProc->lwWaiting = LW_WS_NOT_WAITING;
        else
        {
                int                     extraWaits = 0;
@@ -1171,7 +1174,7 @@ LWLockDequeueSelf(LWLock *lock)
                for (;;)
                {
                        PGSemaphoreLock(MyProc->sem);
-                       if (!MyProc->lwWaiting)
+                       if (MyProc->lwWaiting == LW_WS_NOT_WAITING)
                                break;
                        extraWaits++;
                }
@@ -1322,7 +1325,7 @@ LWLockAcquire(LWLock *lock, LWLockMode mode)
                for (;;)
                {
                        PGSemaphoreLock(proc->sem);
-                       if (!proc->lwWaiting)
+                       if (proc->lwWaiting == LW_WS_NOT_WAITING)
                                break;
                        extraWaits++;
                }
@@ -1487,7 +1490,7 @@ LWLockAcquireOrWait(LWLock *lock, LWLockMode mode)
                        for (;;)
                        {
                                PGSemaphoreLock(proc->sem);
-                               if (!proc->lwWaiting)
+                               if (proc->lwWaiting == LW_WS_NOT_WAITING)
                                        break;
                                extraWaits++;
                        }
@@ -1703,7 +1706,7 @@ LWLockWaitForVar(LWLock *lock, uint64 *valptr, uint64 
oldval, uint64 *newval)
                for (;;)
                {
                        PGSemaphoreLock(proc->sem);
-                       if (!proc->lwWaiting)
+                       if (proc->lwWaiting == LW_WS_NOT_WAITING)
                                break;
                        extraWaits++;
                }
@@ -1781,6 +1784,10 @@ LWLockUpdateVar(LWLock *lock, uint64 *valptr, uint64 val)
 
                proclist_delete(&lock->waiters, iter.cur, lwWaitLink);
                proclist_push_tail(&wakeup, iter.cur, lwWaitLink);
+
+               /* see LWLockWakeup() */
+               Assert(waiter->lwWaiting == LW_WS_WAITING);
+               waiter->lwWaiting = LW_WS_PENDING_WAKEUP;
        }
 
        /* We are done updating shared state of the lock itself. */
@@ -1796,7 +1803,7 @@ LWLockUpdateVar(LWLock *lock, uint64 *valptr, uint64 val)
                proclist_delete(&wakeup, iter.cur, lwWaitLink);
                /* check comment in LWLockWakeup() about this barrier */
                pg_write_barrier();
-               waiter->lwWaiting = false;
+               waiter->lwWaiting = LW_WS_NOT_WAITING;
                PGSemaphoreUnlock(waiter->sem);
        }
 }
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 59789af12c5..5e89b20ecc5 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -481,7 +481,7 @@ InitProcess(void)
        /* NB -- autovac launcher intentionally does not set IS_AUTOVACUUM */
        if (IsAutoVacuumWorkerProcess())
                MyProc->statusFlags |= PROC_IS_AUTOVACUUM;
-       MyProc->lwWaiting = false;
+       MyProc->lwWaiting = LW_WS_NOT_WAITING;
        MyProc->lwWaitMode = 0;
        MyProc->waitLock = NULL;
        MyProc->waitProcLock = NULL;
@@ -746,7 +746,7 @@ InitAuxiliaryProcess(void)
        MyProc->delayChkpt = false;
        MyProc->delayChkptEnd = false;
        MyProc->statusFlags = 0;
-       MyProc->lwWaiting = false;
+       MyProc->lwWaiting = LW_WS_NOT_WAITING;
        MyProc->lwWaitMode = 0;
        MyProc->waitLock = NULL;
        MyProc->waitProcLock = NULL;
diff --git a/src/include/storage/lwlock.h b/src/include/storage/lwlock.h
index eaffe82d7c9..49bcc580708 100644
--- a/src/include/storage/lwlock.h
+++ b/src/include/storage/lwlock.h
@@ -23,6 +23,14 @@
 
 struct PGPROC;
 
+/* what state of the wait process is a backend in */
+typedef enum LWLockWaitState
+{
+       LW_WS_NOT_WAITING, /* not currently waiting / woken up */
+       LW_WS_WAITING, /* currently waiting */
+       LW_WS_PENDING_WAKEUP /* removed from waitlist, but not yet signalled */
+} LWLockWaitState;
+
 /*
  * Code outside of lwlock.c should not manipulate the contents of this
  * structure directly, but we have to declare it here to allow LWLocks to be
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index 9a675c03293..ede942ca508 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -201,7 +201,7 @@ struct PGPROC
        bool            recoveryConflictPending;
 
        /* Info about LWLock the process is currently waiting for, if any. */
-       bool            lwWaiting;              /* true if waiting for an LW 
lock */
+       uint8           lwWaiting;              /* see LWLockWaitState */
        uint8           lwWaitMode;             /* lwlock mode being waited for 
*/
        proclist_node lwWaitLink;       /* position in LW lock wait list */
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to