From: Peter Zijlstra <peterz@infradead.org>
To: Oleg Nesterov <oleg@redhat.com>
Cc: Paul McKenney <paulmck@linux.vnet.ibm.com>,
Mel Gorman <mgorman@suse.de>, Rik van Riel <riel@redhat.com>,
Srikar Dronamraju <srikar@linux.vnet.ibm.com>,
Ingo Molnar <mingo@kernel.org>,
Andrea Arcangeli <aarcange@redhat.com>,
Johannes Weiner <hannes@cmpxchg.org>,
Thomas Gleixner <tglx@linutronix.de>,
Steven Rostedt <rostedt@goodmis.org>,
Linus Torvalds <torvalds@linux-foundation.org>,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH 4/5] rcusync: introduce rcu_sync_struct->exclusive mode
Date: Fri, 4 Oct 2013 22:41:59 +0200 [thread overview]
Message-ID: <20131004204159.GT3081@twins.programming.kicks-ass.net> (raw)
In-Reply-To: <20131004195623.GA19436@redhat.com>
On Fri, Oct 04, 2013 at 09:56:23PM +0200, Oleg Nesterov wrote:
> Hmm. perhaps you meant that this should be done before rcu_sync_enter()
> increments ->gp_count. Perhaps this can work, but the code will be more
> complex and this way rcu_sync_exit() will always schedule the callback?
Yah, however see below.
> And again, we do want to increment ->gp_count asap to disable this cb
> if it is already pending.
Ah indeed, I forgot about that. We'd have to wait until we'd get
scheduled to increment gp_count again. However I think we can fix this
and the above problem by introduction of rcu_sync_busy() which checks
for eiter gp_count or pending waiters.
But yes, slightly more complex code :/
That would yield something like so I suppose:
void rcu_sync_enter(struct rcu_sync_struct *rss)
{
bool need_wait, need_sync;
spin_lock_irq(&rss->rss_lock);
if (rss->exclusive && rss->gp_count) {
__wait_event_locked(rss->gp_wait, rss->gp_count);
rss->gp_count++;
need_wait = need_sync = false;
} else {
need_wait = rss->gp_count++;
need_sync = rss->gp_state == GP_IDLE;
if (need_sync)
rss->gp_state = GP_PENDING;
}
spin_unlock_irq(&rss->lock);
if (need_sync) {
rss->sync();
rss->gp_state = GP_PASSED;
wake_up_all(&rss->gp_wait);
} else if (need_wait) {
wait_event(rss->gp_wait, rss->gp_state == GP_PASSED);
} else {
BUG_ON(rss->gp_state != GP_PASSED);
}
}
static bool rcu_sync_busy(struct rcu_sync_struct *rss)
{
return rss->gp_count ||
(rss->exclusive && waitqueue_active(&rss->gp_wait));
}
static void rcu_sync_func(struct rcu_head *rcu)
{
struct rcu_sync_struct *rss =
container_of(rcu, struct rcu_sync_struct, cb_head);
unsigned long flags;
BUG_ON(rss->gp_state != GP_PASSED);
BUG_ON(rss->cb_state == CB_IDLE);
spin_lock_irqsave(&rss->rss_lock, flags);
if (rcu_sync_busy(rss)) {
/*
* A new rcu_sync_begin() has happened; drop the callback.
*/
rss->cb_state = CB_IDLE;
} else if (rss->cb_state == CB_REPLAY) {
/*
* A new rcu_sync_exit() has happened; requeue the callback
* to catch a later GP.
*/
rss->cb_state = CB_PENDING;
rss->call(&rss->cb_head, rcu_sync_func);
} else {
/*
* We're at least a GP after rcu_sync_exit(); eveybody will now
* have observed the write side critical section. Let 'em rip!.
*/
rss->cb_state = CB_IDLE;
rss->gp_state = GP_IDLE;
}
spin_unlock_irqrestore(&rss->rss_lock, flags);
}
void rcu_sync_exit(struct rcu_sync_struct *rss)
{
spin_lock_irq(&rss->rss_lock);
if (!--rss->gp_count) {
if (!rcu_sync_busy(rss)) {
if (rss->cb_state == CB_IDLE) {
rss->cb_state = CB_PENDING;
rss->call(&rss->cb_head, rcu_sync_func);
} else if (rss->cb_state == CB_PENDING) {
rss->cb_state = CB_REPLAY;
}
} else {
__wake_up_locked(&rss->gp_wait, TASK_NORMAL, 1);
}
}
spin_unlock_irq(&rss->rss_lock);
}
next prev parent reply other threads:[~2013-10-04 20:42 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-10-04 18:46 [PATCH 0/5] rcusync: validations + dtor + exclusive Oleg Nesterov
2013-10-04 18:46 ` [PATCH 1/5] rcusync: introduce struct rcu_sync_ops Oleg Nesterov
2013-10-04 19:12 ` Linus Torvalds
2013-10-04 19:22 ` Oleg Nesterov
2013-10-04 19:30 ` Steven Rostedt
2013-10-04 19:38 ` Linus Torvalds
2013-10-04 19:42 ` Peter Zijlstra
2013-10-05 17:21 ` Oleg Nesterov
2013-10-05 17:17 ` Oleg Nesterov
2013-10-08 9:13 ` Peter Zijlstra
2013-10-08 15:33 ` Oleg Nesterov
2013-10-08 16:34 ` Paul E. McKenney
2013-10-04 18:46 ` [PATCH 2/5] rcusync: add the CONFIG_PROVE_RCU checks Oleg Nesterov
2013-10-04 18:46 ` [PATCH 3/5] rcusync: introduce rcu_sync_dtor() Oleg Nesterov
2013-10-04 18:46 ` [PATCH 4/5] rcusync: introduce rcu_sync_struct->exclusive mode Oleg Nesterov
2013-10-04 19:29 ` Peter Zijlstra
2013-10-04 19:56 ` Oleg Nesterov
2013-10-04 20:41 ` Peter Zijlstra [this message]
2013-10-06 13:22 ` Oleg Nesterov
2013-10-07 10:49 ` Peter Zijlstra
2013-10-04 18:46 ` [PATCH 5/5] rcusync: make rcu_sync_enter() return "bool" Oleg Nesterov
2013-10-04 19:32 ` [PATCH 0/5] rcusync: validations + dtor + exclusive Peter Zijlstra
2013-10-04 21:28 ` Paul E. McKenney
2013-10-05 17:22 ` Oleg Nesterov
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=20131004204159.GT3081@twins.programming.kicks-ass.net \
--to=peterz@infradead.org \
--cc=aarcange@redhat.com \
--cc=hannes@cmpxchg.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mgorman@suse.de \
--cc=mingo@kernel.org \
--cc=oleg@redhat.com \
--cc=paulmck@linux.vnet.ibm.com \
--cc=riel@redhat.com \
--cc=rostedt@goodmis.org \
--cc=srikar@linux.vnet.ibm.com \
--cc=tglx@linutronix.de \
--cc=torvalds@linux-foundation.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.