On 06/30/2015 10:09 PM, Andres Freund wrote:
On 2015-06-30 21:08:53 +0300, Heikki Linnakangas wrote:
                        /*
                         * XXX: We can significantly optimize this on platforms 
with 64bit
                         * atomics.
                         */
                        value = *valptr;
                        if (value != oldval)
                        {
                                result = false;
                                mustwait = false;
                                *newval = value;
                        }
                        else
                                mustwait = true;
                        SpinLockRelease(&lock->mutex);
                }
                else
                        mustwait = false;

                if (!mustwait)
                        break;                          /* the lock was free or 
value didn't match */

                /*
                 * Add myself to wait queue. Note that this is racy, somebody 
else
                 * could wakeup before we're finished queuing. NB: We're using 
nearly
                 * the same twice-in-a-row lock acquisition protocol as
                 * LWLockAcquire(). Check its comments for details.
                 */
                LWLockQueueSelf(lock, LW_WAIT_UNTIL_FREE, false);

After the spinlock is released above, but before the LWLockQueueSelf() call,
it's possible that another backend comes in, acquires the lock, changes the
variable's value, and releases the lock again. In 9.4, the spinlock was not
released until the process was queued.

Hm. Right. A recheck of the value after the queuing should be sufficient
to fix? That's how we deal with the exact same scenarios for the normal
lock state, so that shouldn't be very hard to add.

Yeah. It's probably more efficient to not release the spinlock between checking the value and LWLockQueueSelf() though.

Looking at LWLockAcquireWithVar(), it's also no longer holding the spinlock
while it updates the Var. That's not cool either :-(.

Hm. I'd somehow assumed holding the lwlock ought to be sufficient, but
it really isn't. This var stuff isn't fitting all that well into the
lwlock code.

I'll take a stab at fixing this tomorrow. I take the blame for not documenting the semantics of LWLockAcquireWithVar() and friends well enough...

- Heikki



--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to