Lockless uidinfo.
Pawel Jakub Dawidek
pjd at FreeBSD.org
Tue Aug 21 23:37:00 PDT 2007
On Tue, Aug 21, 2007 at 05:53:34PM -0400, John Baldwin wrote:
> On Tuesday 21 August 2007 03:19:02 pm Pawel Jakub Dawidek wrote:
> > > Memory barriers on another CPU don't mean anything about the CPU thread 2
> is
> > > on. Memory barriers do not flush caches on other CPUs, etc. Normally
> when
> > > objects are refcounted in a table, the table holds a reference on the
> object,
> > > but that doesn't seem to be the case here. [...]
> >
> > But the memory barrier from 'mtx_lock(&uihashtbl_mtx)' above
> > 'if (uip->ui_ref > 0)' would do the trick and I can safely avoid using
> > atomic read in this if statement, right?
>
> Yes, though that may be rather non-obvious to other people, or to yourself 6
> months down the road. You should probably document it.
Agreed, I added a comment that should explain it.
> > > I wouldn't use a more complex algo in uifree() unless the simple one is
> shown
> > > to perform badly. Needless complexity is a hindrance to future
> maintenance.
> >
> > Of coure we could do that, but I was trying really hard to remove
> > contention in the common case. Before we used UIDINFO_LOCK() in the
> > common case, now you suggesting using global lock here, and I'd really,
> > really prefer using one atomic only.
>
> *sigh* You ignored my last sentence. You need to think about other people
> who come and read this later or yourself 12 months from now when you've paged
> out all the uidinfo stuff from your head.
>
> Hmm, what happens if you get this:
>
> thread A
> --------
>
> refcount_release() - drops to 0
>
> preempted
>
> thread B
> --------
> uihold() - refcount goes to 1
> ...
> uifree() - refcount goes to 0
> removes object from table and frees it
>
> resumes
>
> mtx_lock(&uihashtbl);
>
> sees refcount of 0 so tries to destroy object again
>
> *BOOM* (corruption, panic, etc.)
Grr, good catch.
> This is the race that the current code handles by taking a reference
> on the uid while it drops the uidinfo lock to acquire the table lock.
>
> Probably you need to not drop the last reference unless you hold the
> uihashtbl_mtx, which means not using refcount_release() and manually use an
> atomic_cmpset_int() if the refcount is > 1 to drop a ref to optimize the
> common case:
>
> old = uip->ui_refs;
> if (old > 1) {
> if (atomic_cmpset_int(&uip->ui_refs, old, old - 1))
> return;
> }
>
> mtx_lock(&uihashtbl_mtx);
> if (refcount_release(&uip->ui_refs)) {
> /* remove from table and free */
> }
> mtx_unlock(&uihashtbl_mtx);
How about we relookup it after acquiring the uihashtbl_mtx lock?
Something like this (comments removed):
uid_t uid;
uid = uip->ui_uid;
if (!refcount_release(&uip->ui_ref))
return;
mtx_lock(&uihashtbl_mtx);
uip = uilookup(uid);
if (uip != NULL && uip->ui_ref == 0) {
LIST_REMOVE(uip, ui_hash);
mtx_unlock(&uihashtbl_mtx);
FREE(uip, M_UIDINFO);
return;
}
mtx_unlock(&uihashtbl_mtx);
I updated the patch at:
http://people.freebsd.org/~pjd/patches/uidinfo_waitfree.patch
--
Pawel Jakub Dawidek http://www.wheel.pl
pjd at FreeBSD.org http://www.FreeBSD.org
FreeBSD committer Am I Evil? Yes, I Am!
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 187 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-arch/attachments/20070822/33a0e30f/attachment.pgp
More information about the freebsd-arch
mailing list