From: Lai Jiangshan <laijs@cn.fujitsu.com>
To: paulmck@linux.vnet.ibm.com, Ingo Molnar <mingo@elte.hu>
Cc: Arnd Bergmann <arnd@arndb.de>,
LKML <linux-kernel@vger.kernel.org>,
Manfred Spraul <manfred@colorfullife.com>
Subject: [PATCH V5 1/1] rcu: introduce kfree_rcu()
Date: Fri, 18 Mar 2011 11:15:47 +0800 [thread overview]
Message-ID: <4D82CE63.4030006@cn.fujitsu.com> (raw)
In-Reply-To: <20110316040203.GB2273@linux.vnet.ibm.com>
kfree_rcu() which was original proposed by Lai 2.5 years ago is one of
the most important RCU TODO list entries, Lai and Manfred have worked on
patches for this. This V4 patch is based on the Manfred's patch and
the V1 of Lai's patch. (These two patches are almost the same
in implementation, and this patch is mainly based on the Manfred's).
Lai's V1 patch: http://lkml.org/lkml/2008/9/18/1
Manfred's patch: http://lkml.org/lkml/2009/1/2/115
RCU TODO list: http://www.kernel.org/pub/linux/kernel/people/paulmck/rcutodo.html
This new introduced API kfree_rcu() primitive kfree()s the specified memory
after a RCU grace period elapses.
It replaces many simple "call_rcu(head, simple_kfree_callback)";
These many simple_kfree_callback() instances just does
kfree(containerof(head,struct whatever_struct,rcu_member));
These simple_kfree_callback() instances are just duplicate code, we need
a generic function for them.
And kfree_rcu() is also help for unloadable modules, kfree_rcu() does not
queue any function which belong to the module, so a rcu_barrier() can
be avoid when module exit. (If we queue any other function by call_rcu(),
rcu_barrier() is still needed.)
Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com>
Signed-off-by: Manfred Spraul <manfred@colorfullife.com>
---
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 7d62909..e45ed82 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -777,4 +777,58 @@ static inline void debug_rcu_head_unqueue(struct rcu_head *head)
}
#endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */
+static __always_inline bool __is_kfree_rcu_offset(unsigned long offset)
+{
+ return offset < 4096;
+}
+
+static __always_inline
+void __kfree_rcu(struct rcu_head *head, unsigned long offset)
+{
+ typedef void (*rcu_callback)(struct rcu_head *);
+
+ BUILD_BUG_ON(!__builtin_constant_p(offset));
+
+ /* See the comments of kfree_rcu(), the "Note:" section. */
+ BUILD_BUG_ON(!__is_kfree_rcu_offset(offset));
+
+ call_rcu(head, (rcu_callback)offset);
+}
+
+extern void kfree(const void *);
+
+static inline void __rcu_reclaim(struct rcu_head *head)
+{
+ unsigned long offset = (unsigned long)head->func;
+
+ if (__is_kfree_rcu_offset(offset))
+ kfree((void *)head - offset);
+ else
+ head->func(head);
+}
+
+/**
+ * kfree_rcu() - kfree an object after a grace period.
+ * @ptr: pointer to kfree
+ * @rcu_head: the name of the struct rcu_head within the type of @ptr.
+ *
+ * Many rcu callbacks just call kfree() on the base structure. This helper
+ * function calls kfree internally. The rcu_head structure must be embedded
+ * in the to be freed structure.
+ *
+ * It is different from call_rcu(), kfree_rcu() does not require nor create
+ * any local RCU callback functions belong to its module. So the caller
+ * does not need to wait the callback to complete when the caller want to
+ * unload the module.
+ *
+ * Note: if the offset of the struct rcu_head within the type of @ptr
+ * is larger than 4096, it will trigger a BUILD_BUG_ON() compile-time
+ * error in __kfree_rcu(), the user of kfree_rcu() should rerange the
+ * fields of the type of @ptr to make the offset smaller or use call_rcu()
+ * instead or require the RCU maintainer changing the limit
+ * in this situation.
+ */
+#define kfree_rcu(ptr, rcu_head) \
+ __kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head))
+
#endif /* __LINUX_RCUPDATE_H */
diff --git a/kernel/rcutiny.c b/kernel/rcutiny.c
index 0c343b9..4d60fbc 100644
--- a/kernel/rcutiny.c
+++ b/kernel/rcutiny.c
@@ -167,7 +167,7 @@ static void rcu_process_callbacks(struct rcu_ctrlblk *rcp)
prefetch(next);
debug_rcu_head_unqueue(list);
local_bh_disable();
- list->func(list);
+ __rcu_reclaim(list);
local_bh_enable();
list = next;
RCU_TRACE(cb_count++);
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index dd4aea8..b3c1aed 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -1143,7 +1143,7 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp)
next = list->next;
prefetch(next);
debug_rcu_head_unqueue(list);
- list->func(list);
+ __rcu_reclaim(list);
list = next;
if (++count >= rdp->blimit)
break;
next prev parent reply other threads:[~2011-03-18 3:14 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-03-15 9:46 [PATCH V4 1/1] rcu: introduce kfree_rcu() Lai Jiangshan
2011-03-15 10:15 ` Arnd Bergmann
2011-03-15 11:27 ` Paul E. McKenney
2011-03-15 12:02 ` Arnd Bergmann
2011-03-15 12:19 ` Paul E. McKenney
2011-03-15 13:07 ` Arnd Bergmann
2011-03-16 2:58 ` Lai Jiangshan
2011-03-16 4:38 ` Paul E. McKenney
2011-03-16 4:02 ` Paul E. McKenney
2011-03-18 3:15 ` Lai Jiangshan [this message]
2011-03-18 8:14 ` [PATCH V5 " Arnd Bergmann
2011-03-16 2:23 ` [PATCH V4 " Lai Jiangshan
2011-03-15 11:30 ` Paul E. McKenney
2011-03-16 2:50 ` Lai Jiangshan
2011-03-16 4:29 ` Paul E. McKenney
2011-03-15 13:11 ` Eric Dumazet
2011-03-16 4:03 ` Paul E. McKenney
2011-03-17 9:28 ` Lai Jiangshan
2011-03-17 17:50 ` Paul E. McKenney
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=4D82CE63.4030006@cn.fujitsu.com \
--to=laijs@cn.fujitsu.com \
--cc=arnd@arndb.de \
--cc=linux-kernel@vger.kernel.org \
--cc=manfred@colorfullife.com \
--cc=mingo@elte.hu \
--cc=paulmck@linux.vnet.ibm.com \
/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