Re: [patch] Real-Time Preemption, -RT-2.6.12-rc1-V0.7.41-07

Paul E. McKenney
2005-03-24T06:45:48Z

On Wed, Mar 23, 2005 at 10:03:41AM +0100, Ingo Molnar wrote:
>
> * Peter Zijlstra <peter@programming.kicks-ass.net> wrote:
>
> > > i think the 'migrate read-count' method is not adequate either, because
> > > all callbacks queued within an RCU read section must be called after the
> > > lock has been dropped - while with the migration method CPU#1 would be
> > > free to process callbacks queued in the RCU read section still active on
> > > CPU#2.
> >
> > how about keeping the rcu callback list in process context and only
> > splice it to a global (per cpu) list on rcu_read_unlock?
>
> hm, that would indeed solve this problem. It would also solve the grace
> period problem: all callbacks in the global (per-CPU) list are
> immediately processable. Paul?

If I understand the proposal, it would break in the following situation
(lifted from earlier email):

rcu_read_lock();
list_for_each_entry_rcu(p, head, list) {
if (unlikely(p->status == DELETE_ME)) {
spin_lock(&p->mutex);
if (likely(p->status == DELETE_ME)) {
p->status = DELETED;
list_rcu(&p->list);
call_rcu(&p->rcu, sublist_finalize_rcu);
}
spin_unlock(&p->mutex);
}
}
rcu_read_unlock();

Here, sublist_finalize_rcu() just finds the front of the block and
kfree()s it.

Here is the scenario:

CPU 1 CPU 2

task 1 does rcu_read lock

task 2 does rcu_read_lock

task 1 sees DELETE_ME

task 2 sees DELETE_ME

task 1 acquires the lock

task 2 blocks/spins on lock

task 1 does call_rcu

task 1 releases lock

task 1 does rcu_read_unlock()

task 2 acquires lock

RCU puts the callback on global list

RCU invokes callback, kfree()!!!

task 2 now sees garbage!!!

Callbacks cannot be invoked until all RCU read-side critical sections
that were in process at the time of the rcu_callback() have all
completed.

Thanx, Paul