Re: FlexLocks - Mailing list pgsql-hackers

From Robert Haas
Subject Re: FlexLocks
Date
Msg-id CA+TgmoaE5MSkt-Ey4oKwLTVYHw5-pV1muAimrF_x4=foh6e=mQ@mail.gmail.com
Whole thread Raw
In response to Re: FlexLocks  ("Kevin Grittner" <Kevin.Grittner@wicourts.gov>)
Responses Re: FlexLocks
List pgsql-hackers
On Wed, Nov 23, 2011 at 7:18 PM, Kevin Grittner
<Kevin.Grittner@wicourts.gov> wrote:
> Why is it OK to drop these lines from the else condition in
> ProcArrayEndTransaction()?:
>
>        /* must be cleared with xid/xmin: */
>        proc->vacuumFlags &= ~PROC_VACUUM_STATE_MASK;

It's probably not.  Oops.

I believe the attached patch versions address your comments regarding
the flexlock patch as well; it is also rebased over the PGXACT patch,
which has since been committed.

> The extraWaits code still looks like black magic to me, so unless
> someone can point me in the right direction to really understand
> that, I can't address whether it's OK.

I don't think I've changed the behavior, so it should be fine.  The
idea is that something like this can happen:

1. Backend #1 does some action which will eventually cause some other
process to send it a wakeup (like adding itself to the wait-queue for
a heavyweight lock).
2. Before actually going to sleep, backend #1 tries to acquire an
LWLock.  The LWLock is not immediately available, so it sleeps on its
process semaphore.
3. Backend #2 sees the shared memory state created in step one and
decides sends a wakeup to backend #1 (for example, because the lock is
now available).
4. Backend #1 receives the wakeup.  It duly reacquires the spinlock
protecting the LWLock, sees that the LWLock is not available, releases
the spinlock, and goes back to sleep.
5. Backend #3 now releases the LWLock that backend #1 is trying to
acquire and, as backend #1 is first in line, it sends backend #1 a
wakeup.
6. Backend #1 now wakes up again, reacquires the spinlock, gets the
lwlock, releases the spinlock, does some stuff, and releases the
lwlock.
7. Backend #1, having now finished what it needed to do while holding
the lwlock, is ready to go to sleep and wait for the event that it
queued up for back in step #1.  However, the wakeup for that event
*has already arrived* and was consumed by the LWLock machinery.  So
when backend #1 goes to sleep, it's waiting for a wakeup that will
never arrive, because it already did arrive, and got eaten.

The solution is the "extraWaits" thing; in step #6, we remember that
we received an extra, useless wakeup in step #4 that we threw away.
To make up for having thrown away a wakeup someone else sent us in
step #3, we send ourselves a wakeup in step #6.  That way, when we go
to sleep in step #7, we wake up immediately, just as we should.

> The need to modify flexlock_internals.h and flexlock.c seems to me to
> indicate a lack of desirable modularity here.  The lower level object
> type shouldn't need to know about each and every implementation of a
> higher level type which uses it, particularly not compiled in like
> that.  It would be really nice if each of the higher level types
> "registered" with flexlock at runtime, so that the areas modified at
> the flexlock level in this patch file could be generic.  Among other
> things, this could allow extensions to use specialized types, which
> seems possibly useful.  Does that (or some other technique to address
> the concern) seem feasible?

Possibly; let me think about that.  I haven't addressed that in this version.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Attachment

pgsql-hackers by date:

Previous
From: Jesper Krogh
Date:
Subject: Accounting for toast in query planner. (gin/gist indexes).
Next
From: Robert Haas
Date:
Subject: Re: WIP: index support for regexp search