From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752341AbbGKXhi (ORCPT ); Sat, 11 Jul 2015 19:37:38 -0400 Received: from mx1.redhat.com ([209.132.183.28]:49385 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752300AbbGKXhg (ORCPT ); Sat, 11 Jul 2015 19:37:36 -0400 Date: Sun, 12 Jul 2015 01:35:58 +0200 From: Oleg Nesterov To: Linus Torvalds , Paul McKenney , Peter Zijlstra Cc: Daniel Wagner , Davidlohr Bueso , Ingo Molnar , Tejun Heo , linux-kernel@vger.kernel.org Subject: [PATCH 4/7] rcusync: Introduce rcu_sync_dtor() Message-ID: <20150711233558.GA860@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20150711233535.GA829@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add the new rcu_sync_ops->wait() method and the new helper, rcu_sync_dtor(). It is needed if you are going to, say, kfree(rcu_sync_object). It simply calls ops->wait() to "flush" the potentially pending rcu callback. Reviewed-by: Paul E. McKenney Signed-off-by: Oleg Nesterov Signed-off-by: Peter Zijlstra (Intel) --- include/linux/rcusync.h | 1 + kernel/rcu/sync.c | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 0 deletions(-) diff --git a/include/linux/rcusync.h b/include/linux/rcusync.h index a51e5c7..0135838 100644 --- a/include/linux/rcusync.h +++ b/include/linux/rcusync.h @@ -31,6 +31,7 @@ static inline bool rcu_sync_is_idle(struct rcu_sync_struct *rss) extern void rcu_sync_init(struct rcu_sync_struct *, enum rcu_sync_type); extern void rcu_sync_enter(struct rcu_sync_struct *); extern void rcu_sync_exit(struct rcu_sync_struct *); +extern void rcu_sync_dtor(struct rcu_sync_struct *); #define __RCU_SYNC_INITIALIZER(name, type) { \ .gp_state = 0, \ diff --git a/kernel/rcu/sync.c b/kernel/rcu/sync.c index 32cdbb8..8835ad1 100644 --- a/kernel/rcu/sync.c +++ b/kernel/rcu/sync.c @@ -10,6 +10,7 @@ static const struct { void (*sync)(void); void (*call)(struct rcu_head *, void (*)(struct rcu_head *)); + void (*wait)(void); #ifdef CONFIG_PROVE_RCU int (*held)(void); #endif @@ -17,16 +18,19 @@ static const struct { [RCU_SYNC] = { .sync = synchronize_rcu, .call = call_rcu, + .wait = rcu_barrier, __INIT_HELD(rcu_read_lock_held) }, [RCU_SCHED_SYNC] = { .sync = synchronize_sched, .call = call_rcu_sched, + .wait = rcu_barrier_sched, __INIT_HELD(rcu_read_lock_sched_held) }, [RCU_BH_SYNC] = { .sync = synchronize_rcu_bh, .call = call_rcu_bh, + .wait = rcu_barrier_bh, __INIT_HELD(rcu_read_lock_bh_held) }, }; @@ -128,3 +132,21 @@ void rcu_sync_exit(struct rcu_sync_struct *rss) } spin_unlock_irq(&rss->rss_lock); } + +void rcu_sync_dtor(struct rcu_sync_struct *rss) +{ + int cb_state; + + BUG_ON(rss->gp_count); + + spin_lock_irq(&rss->rss_lock); + if (rss->cb_state == CB_REPLAY) + rss->cb_state = CB_PENDING; + cb_state = rss->cb_state; + spin_unlock_irq(&rss->rss_lock); + + if (cb_state != CB_IDLE) { + gp_ops[rss->gp_type].wait(); + BUG_ON(rss->cb_state != CB_IDLE); + } +} -- 1.5.5.1