Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 20 Jun 2014 03:04:24 +0200
From:      Mateusz Guzik <mjguzik@gmail.com>
To:        Adrian Chadd <adrian@freebsd.org>
Cc:        Robert Watson <rwatson@freebsd.org>, "freebsd-arch@freebsd.org" <freebsd-arch@freebsd.org>
Subject:   Re: capability races (was: Re: Seeing ENOTCAPABLE from write FDs in kqueue?)
Message-ID:  <20140620010424.GA5830@dft-labs.eu>
In-Reply-To: <20140618203314.GB7157@dft-labs.eu>
References:  <CAJ-VmonJaqg=WV0eTxknOQr51E5qdhDU=MdoCywz-hwZ57jj6w@mail.gmail.com> <20140608220000.GA5030@dft-labs.eu> <20140608230059.GB5030@dft-labs.eu> <20140618203314.GB7157@dft-labs.eu>

next in thread | previous in thread | raw e-mail | index | archive | help
Good news.

While previous approached were giving ~16% worse performance in my
microbenchmarks I found a way to make up for this (needs verification
for correctness).

fget_unlocked does:
        /*
         * Avoid reads reordering and then a first access to the
         * fdp->fd_ofiles table which could result in OOB operation.
         */
        if (fd < 0 || fd >= atomic_load_acq_int(&fdp->fd_nfiles))
                return (EBADF);

Turns out replacing this read with mere "fdp->fd_nfiles" gives ~10%
performance increase over regular kernel and almost brings kernel with
sequence counters to the level of regular kernel.

So how to get rid of the need for atomic_load_acq_int?

Currently struct filedesc contains file table and its size. File table
pointer update is one operation, size update is another. Thus the need
for memory barriers.

Now let's consider the following structure:
struct fdtable {
	int f_size;
	struct filedesc f_files[0];
};

Pointer to this strucure in struct filedesc can be replaced atomically,
and from what I'm told the only synchronization needed is data dependency
barrier (which in case of amd64 means there is no need to do anything).

In short, we can get ~10% better performance and then sacrifice the gain
(and some more) to have capability races fixed and be slightly slower
than now.

Thoughts?

The patch is a total hack so I'm not attaching it, but as far as
performance goes you can just move fd_nfiles to be next to fd_ofiles and
remove atomic_load_acq_int in fget_unlocked.

fdgrowtable will need to have a write barrier before the pointer is
atomically replaced.

-- 
Mateusz Guzik <mjguzik gmail.com>



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20140620010424.GA5830>