Re: pg_atomic_compare_exchange_*() and memory barriers

Поиск
Список
Период
Сортировка
От Andres Freund
Тема Re: pg_atomic_compare_exchange_*() and memory barriers
Дата
Msg-id aw3hirtizbn42fkl57bjeafzws3b2bvhknimbxyoi23i43sajb@i65p2ubb6zte
обсуждение исходный текст
Ответ на Re: pg_atomic_compare_exchange_*() and memory barriers  (Alexander Korotkov <aekorotkov@gmail.com>)
Ответы Re: pg_atomic_compare_exchange_*() and memory barriers
Список pgsql-hackers
Hi,

On 2025-03-07 19:15:23 +0200, Alexander Korotkov wrote:
> On Fri, Mar 7, 2025 at 7:07 PM Andres Freund <andres@anarazel.de> wrote:
> > What is the access pattern and the observed problems with it that made you
> > look at the disassembly?
> 
> Check this code.
> 
> l1:     pg_atomic_write_u64(&XLogCtl->xlblocks[nextidx], NewPageEndPtr);

>         /*
>          * Try to advance XLogCtl->InitializedUpTo.
>          *
>          * If the CAS operation failed, then some of previous pages are not
>          * initialized yet, and this backend gives up.
>          *
>          * Since initializer of next page might give up on advancing of
>          * InitializedUpTo, this backend have to attempt advancing until it
>          * find page "in the past" or concurrent backend succeeded at
>          * advancing.  When we finish advancing XLogCtl->InitializedUpTo, we
>          * notify all the waiters with XLogCtl->InitializedUpToCondVar.
>          */
> l2:     while (pg_atomic_compare_exchange_u64(&XLogCtl->InitializedUpTo,
> &NewPageBeginPtr, NewPageEndPtr))
>         {
>             NewPageBeginPtr = NewPageEndPtr;
>             NewPageEndPtr = NewPageBeginPtr + XLOG_BLCKSZ;
>             nextidx = XLogRecPtrToBufIdx(NewPageBeginPtr);
> 
> l3:         if (pg_atomic_read_u64(&XLogCtl->xlblocks[nextidx]) !=
> NewPageEndPtr)
>             {
>                 /*
>                  * Page at nextidx wasn't initialized yet, so we cann't move
>                  * InitializedUpto further. It will be moved by backend
> which
>                  * will initialize nextidx.
>                  */
> 
> ConditionVariableBroadcast(&XLogCtl->InitializedUpToCondVar);
>                 break;
>             }
>         }
> 
> Consider the following execution order with process 1 (p1) and process 2
> (p2).

On 2025-03-07 19:24:39 +0200, Alexander Korotkov wrote:
> Sorry, I messed this up.
> The correct sequence is following.
> 
> 1. p1 executes l1
> 2. p1 executes l2 with failure
> 3. p2 executes l2 with success
> 4. p2 execute l3, but doesn't see the results of step 1, because 3
> didn't provide enough of memory barrier

Did you mean because 2) didn't provide enough of a memory barrier? Because 3)
does, right?

You could get in exactly same the situation if the p1 is scheduled out by the
OS after step 1, no?

Greetings,

Andres Freund



В списке pgsql-hackers по дате отправления: