Re: dynamic shared memory and locks - Mailing list pgsql-hackers

From Kohei KaiGai
Subject Re: dynamic shared memory and locks
Date
Msg-id CADyhKSWGrrx=oyAavy066QTue6hC=B5MO1X8utm-gkorm2vJrA@mail.gmail.com
Whole thread Raw
In response to Re: dynamic shared memory and locks  (Robert Haas <robertmhaas@gmail.com>)
Responses Re: dynamic shared memory and locks
List pgsql-hackers
2014-02-08 4:52 GMT+09:00 Robert Haas <robertmhaas@gmail.com>:
> On Tue, Jan 21, 2014 at 11:37 AM, Robert Haas <robertmhaas@gmail.com> wrote:
>> One idea I just had is to improve the dsm_toc module so that it can
>> optionally set up a tranche of lwlocks for you, and provide some
>> analogues of RequestAddinLWLocks and LWLockAssign for that case.  That
>> would probably make this quite a bit simpler to use, at least for
>> people using it with dynamic shared memory.  But I think that's a
>> separate patch.
>
> I played with this a bit today and it doesn't actually seem to
> simplify things very much.  The backend that creates the DSM needs to
> do this:
>
>     lwlocks = shm_toc_allocate(toc, sizeof(LWLockPadded) * nlwlocks);
>     for (i = 0; i < nlwlocks; ++i)
>         LWLockInitialize(&lwlocks[i].lock, tranche_id);
>
> Since that's all of three lines, encapsulating it doesn't look all
> that helpful.  Then each backend needs to do something like this:
>
>     static LWLockTranche mytranche;
>     mytranche.name = "some descriptive module name";
>     mytranche.array_base = lwlocks;
>     mytranche.array_stride = sizeof(LWLockPadded);
>     LWLockRegisterTranche(tranche_id, &mytranche);
>
> That's not a lot of code either, and there's no obvious way to reduce
> it much by hooking into shm_toc.
>
> I thought maybe we needed some cleanup when the dynamic shared memory
> segment is unmapped, but looks like we really don't.  One can do
> something like LWLockRegisterTranche(tranche_id, NULL) for debugging
> clarity, but it isn't strictly needed; one can release all lwlocks
> from the tranche or assert that none are held, but that should really
> only be a problem if the user does something like
> LWLockAcquire(lock_in_the_segment); dsm_detach(seg), because error
> recovery starts by releasing *all* lwlocks.  And if the user does it
> explicitly, I'm kinda OK with that just seg faulting.  After all, the
> user could equally well have done dsm_detach(seg);
> LWLockAcquire(lock_in_the_segment) and there's no way at all to
> cross-check for that sort of mistake.
>
Does it make another problem if dsm_detach() also releases lwlocks
being allocated on the dsm segment to be released?
Lwlocks being held is tracked in the held_lwlocks[] array; its length is
usually 100. In case when dsm_detach() is called towards the segment
between addr ~ (addr + length), it seems to me an easy job to walk on
this array to find out lwlocks on the range.


> I do see one thing about the status quo that does look reasonably
> annoying: the code expects that tranche IDs are going to stay
> relatively small.  For example, consider a module foobar that uses DSM
> + LWLocks.  It won't do at all for each backend, on first use of the
> foobar module, to do LWLockNewTrancheId() and then reuse that
> tranche_id repeatedly for each new DSM - because over a system
> lifetime of months, tranche IDs could grow into the millions, causing
> LWLockTrancheArray to get really big (and eventually repalloc will
> fail).  Rather, the programmer needs to ensure that
> LWLockNewTrancheId() gets called *once per postmaster lifetime*,
> perhaps by allocating a chunk of permanent shared memory and using
> that to store the tranche_id that should be used each time an
> individual backend fires up a DSM.  Considering that one of the goals
> of dynamic shared memory is to allow modules to be loaded after
> postmaster startup and still be able to do useful stuff, that's kind
> of obnoxious.  I don't have a good idea what to do about it, though;
> making LWLockTrancheArray anything other than a flat array looks
> likely to slow down --enable-dtrace builds unacceptably.
>
Just my rough idea. Doesn't it make sense to have an offset from the
head of DSM segment that contains the lwlock, instead of the identifier
form, to indicate a cstring datum? It does not prevent to allocate it
later; after the postmaster starting up, and here is no problem if number
of dynamic lwlocks grows millions or more.
If lwlock has a "tranche_offset", not "tranche_id", all it needs to do is:
1. find out either of DSM segment or regular SHM segment that contains   the supplied lwlock.
2. Calculate mapped_address + tranche_offset; that is the local location   where cstring form is put.

Probably, it needs a common utility routine on dsm.c to find out
a particular DSM segment that contains the supplied address.
(Inverse function towards dsm_segment_address)

How about my ideas?

Thanks,
-- 
KaiGai Kohei <kaigai@kaigai.gr.jp>



pgsql-hackers by date:

Previous
From: Merlin Moncure
Date:
Subject: Re: jsonb and nested hstore
Next
From: Andres Freund
Date:
Subject: Re: jsonb and nested hstore