From: "George Spelvin" <linux@horizon.com>
To: peterx@infradead.org
Cc: linux@horizon.com, linux-kernel@vger.kernel.org
Subject: Two other ways to do latched seqcounts
Date: 12 Apr 2015 15:36:54 -0400 [thread overview]
Message-ID: <20150412193654.1473.qmail@ns.horizon.com> (raw)
Just FYI, There are some additional ways to do this, with lower chance
of having to retry.
They increase either space or write cost, so they're not panaceas,
but do reduce the number of read retries to near-zero.
A problem with the current version is that there is only one
guaranteed-consistent copy, so a write always forces concurrent
readers to retry.
So if reading takes a while (the "extract the info I want" is slow)
and writes are frequent, you might retry a lot.
There are two ways to expand the read window.
One is to keep four copies, not two. I have a private patch to the
PPS code that does this, since the data being protected is very small:
a few timestamps. This gives three guaranteed-consistent copies, and a
reader doesn't have to retry unless there have been three writes between
the beginning and end of the sequence.
I.e.
void latch_query(struct latch_struct *latch, struct data *data)
{
unsigned seq;
do {
int idx = (seq = latch->seq) & 3;
smp_rmb();
*data = latch->data[idx]; /* Or extract the portion of interest */
smp_rmb();
} while (latch->seq - seq >= 3u);
}
The second is to update the seqlock twice per write.
While the lsbit of the seqlock is zero, *both* copies are valid, but
the one identified by the second-lsbit is more up to date and preferred.
While the lsbit of the seqlock is one, an update is in progress.
But I may read the old copy. And even if the update completes while
I'm reading, I know my copy is still consistent until the *next*
update starts.
void latch_query(struct latch_struct *latch, struct data *data)
{
unsigned seq;
do {
int idx = (seq = latch->seq) >> 1 & 1;
smp_rmb();
*data = latch->data[idx]; /* Or extract the portion of interest */
smp_rmb();
seq |= 1; /* Could OR or AND, but OR is more available than ANDN. */
} while (latch->seq - seq >= 2u);
}
One note about this version is that, although you need to update the seq variable
twice, it doesn't increase the number of smp_wmb you need. It's:
void latch_modify(struct latch_struct *latch, ...)
{
unsigned seq = latch->seq |= 1;
smp_wmb();
modify(latch->data[++seq >> 1 & 1], ...);
smp_wmb();
latch->seq = seq;
}
next reply other threads:[~2015-04-12 19:36 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-04-12 19:36 George Spelvin [this message]
[not found] <20150413073510.GC5029@twins.programming.kicks-ass.net>
2015-04-13 9:26 ` George Spelvin
2015-04-13 10:38 ` Peter Zijlstra
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150412193654.1473.qmail@ns.horizon.com \
--to=linux@horizon.com \
--cc=linux-kernel@vger.kernel.org \
--cc=peterx@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®