From: Christoph Lameter <cl@linux.com>
To: Tejun Heo <tj@kernel.org>
Cc: akpm@linux-foundation.org
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: linux-kernel@vger.kernel.org
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Subject: [cpuops cmpxchg double V2 1/4] Generic support for this_cpu_cmpxchg_double
Date: Thu, 06 Jan 2011 14:45:14 -0600 [thread overview]
Message-ID: <20110106204525.222395863@linux.com> (raw)
In-Reply-To: 20110106204513.669098445@linux.com
[-- Attachment #1: cpuops_double_generic --]
[-- Type: text/plain, Size: 6856 bytes --]
Introduce this_cpu_cmpxchg_double. this_cpu_cmpxchg_double() allows the
comparision between two consecutive words and replaces them if there is
a match.
bool this_cpu_cmpxchg_double(pcp1, pcp2,
old_word1, old_word2, new_word1, new_word2)
this_cpu_cmpxchg_double does not return the old value (difficult since
there are two words) but a boolean indicating if the operation was
successful.
The first percpu variable must be double word aligned!
Signed-off-by: Christoph Lameter <cl@linux.com>
---
include/linux/percpu.h | 130 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 130 insertions(+)
Index: linux-2.6/include/linux/percpu.h
===================================================================
--- linux-2.6.orig/include/linux/percpu.h 2011-01-05 15:00:46.000000000 -0600
+++ linux-2.6/include/linux/percpu.h 2011-01-06 13:19:43.000000000 -0600
@@ -259,6 +259,29 @@ extern void __bad_size_call_parameter(vo
pscr2_ret__; \
})
+/*
+ * Special handling for cmpxchg_double. cmpxchg_double is passed two
+ * percpu variables. The first has to be aligned to a double word
+ * boundary and the second has to follow directly thereafter.
+ */
+#define __pcpu_double_call_return_int(stem, pcp1, pcp2, ...) \
+({ \
+ int ret__; \
+ __verify_pcpu_ptr(&pcp1); \
+ VM_BUG_ON((unsigned long)(&pcp1) % (2 * sizeof(pcp1))); \
+ VM_BUG_ON((unsigned long)(&pcp2) != (unsigned long)(&pcp1) + sizeof(pcp1));\
+ VM_BUG_ON(sizeof(pcp1) != sizeof(pcp2)); \
+ switch(sizeof(pcp1)) { \
+ case 1: ret__ = stem##1(pcp1, pcp2, __VA_ARGS__);break; \
+ case 2: ret__ = stem##2(pcp1, pcp2, __VA_ARGS__);break; \
+ case 4: ret__ = stem##4(pcp1, pcp2, __VA_ARGS__);break; \
+ case 8: ret__ = stem##8(pcp1, pcp2, __VA_ARGS__);break; \
+ default: \
+ __bad_size_call_parameter();break; \
+ } \
+ ret__; \
+})
+
#define __pcpu_size_call(stem, variable, ...) \
do { \
__verify_pcpu_ptr(&(variable)); \
@@ -422,6 +445,80 @@ do { \
__this_cpu_cmpxchg_, pcp, oval, nval)
#endif
+/*
+ * cmpxchg_double replaces two adjacent scalars at once. The first two
+ * parameters are per cpu variables which have to be of the same size.
+ * A truth value is returned to indicate success or
+ * failure (since a double register result is difficult to handle).
+ * There is very limited hardware support for these operations. So only certain
+ * sizes may work.
+ */
+#define __this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2) \
+({ \
+ int __ret = 0; \
+ if (__this_cpu_read(pcp1) == (oval1) && \
+ __this_cpu_read(pcp2) == (oval2)) { \
+ __this_cpu_write(pcp1, (nval1)); \
+ __this_cpu_write(pcp2, (nval2)); \
+ __ret = 1; \
+ } \
+ (__ret); \
+})
+
+#ifndef __this_cpu_cmpxchg_double
+# ifndef __this_cpu_cmpxchg_double_1
+# define __this_cpu_cmpxchg_double_1(pcp1, pcp2, oval1, oval2, nval1, nval2) \
+ __this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+# endif
+# ifndef __this_cpu_cmpxchg_double_2
+# define __this_cpu_cmpxchg_double_2(pcp1, pcp2, oval1, oval2, nval1, nval2) \
+ __this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+# endif
+# ifndef __this_cpu_cmpxchg_double_4
+# define __this_cpu_cmpxchg_double_4(pcp1, pcp2, oval1, oval2, nval1, nval2) \
+ __this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+# endif
+# ifndef __this_cpu_cmpxchg_double_8
+# define __this_cpu_cmpxchg_double_8(pcp1, pcp2, oval1, oval2, nval1, nval2) \
+ __this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+# endif
+# define __this_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2) \
+ __pcpu_double_call_return_int(__this_cpu_cmpxchg_double_, (pcp1), (pcp2) \
+ oval1, oval2, nval1, nval2)
+#endif
+
+#define _this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2) \
+({ \
+ int ret__; \
+ preempt_disable(); \
+ ret__ = __this_cpu_generic_cmpxchg_double(pcp1, pcp2, \
+ oval1, oval2, nval1, nval2); \
+ preempt_enable(); \
+ ret__; \
+})
+
+#ifndef this_cpu_cmpxchg_double
+# ifndef this_cpu_cmpxchg_double_1
+# define this_cpu_cmpxchg_double_1(pcp1, pcp2, oval1, oval2, nval1, nval2) \
+ _this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+# endif
+# ifndef this_cpu_cmpxchg_double_2
+# define this_cpu_cmpxchg_double_2(pcp1, pcp2, oval1, oval2, nval1, nval2) \
+ _this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+# endif
+# ifndef this_cpu_cmpxchg_double_4
+# define this_cpu_cmpxchg_double_4(pcp1, pcp2, oval1, oval2, nval1, nval2) \
+ _this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+# endif
+# ifndef this_cpu_cmpxchg_double_8
+# define this_cpu_cmpxchg_double_8(pcp1, pcp2, oval1, oval2, nval1, nval2) \
+ _this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+# endif
+# define this_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2) \
+ __pcpu_double_call_return_int(this_cpu_cmpxchg_double_, (pcp1), (pcp2), \
+ oval1, oval2, nval1, nval2)
+#endif
+
#define _this_cpu_generic_to_op(pcp, val, op) \
do { \
preempt_disable(); \
@@ -825,4 +922,37 @@ do { \
# define irqsafe_cpu_cmpxchg(pcp, oval, nval) __pcpu_size_call_return2(irqsafe_cpu_cmpxchg_, (pcp), oval, nval)
#endif
+#define irqsafe_generic_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2) \
+({ \
+ int ret__; \
+ unsigned long flags; \
+ local_irq_save(flags); \
+ ret__ = __this_cpu_generic_cmpxchg_double(pcp1, pcp2, \
+ oval1, oval2, nval1, nval2); \
+ local_irq_restore(flags); \
+ ret__; \
+})
+
+#ifndef irqsafe_cpu_cmpxchg_double
+# ifndef irqsafe_cpu_cmpxchg_double_1
+# define irqsafe_cpu_cmpxchg_double_1(pcp1, pcp2, oval1, oval2, nval1, nval2) \
+ irqsafe_generic_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+# endif
+# ifndef irqsafe_cpu_cmpxchg_double_2
+# define irqsafe_cpu_cmpxchg_double_2(pcp1, pcp2, oval1, oval2, nval1, nval2) \
+ irqsafe_generic_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+# endif
+# ifndef irqsafe_cpu_cmpxchg_double_4
+# define irqsafe_cpu_cmpxchg_double_4(pcp1, pcp2, oval1, oval2, nval1, nval2) \
+ irqsafe_generic_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+# endif
+# ifndef irqsafe_cpu_cmpxchg_double_8
+# define irqsafe_cpu_cmpxchg_double_8(pcp1, pcp2, oval1, oval2, nval1, nval2) \
+ irqsafe_generic_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+# endif
+# define irqsafe_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2) \
+ __pcpu_double_call_return_int(irqsafe_cpu_cmpxchg_double_, (pcp1), (pcp2), \
+ oval1, oval2, nval1, nval2)
+#endif
+
#endif /* __LINUX_PERCPU_H */
next prev parent reply other threads:[~2011-01-06 20:45 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-01-06 20:45 [cpuops cmpxchg double V2 0/4] this_cpu_cmpxchg_double support Christoph Lameter
2011-01-06 20:45 ` Christoph Lameter [this message]
2011-01-06 21:08 ` [cpuops cmpxchg double V2 1/4] Generic support for this_cpu_cmpxchg_double Mathieu Desnoyers
2011-01-06 21:43 ` Christoph Lameter
2011-01-06 22:05 ` H. Peter Anvin
2011-01-07 15:15 ` Christoph Lameter
2011-01-07 18:04 ` Mathieu Desnoyers
2011-01-07 18:41 ` Christoph Lameter
2011-01-08 17:24 ` Tejun Heo
2011-01-09 8:33 ` Pekka Enberg
2011-01-21 7:31 ` Pekka Enberg
2011-01-21 9:26 ` Tejun Heo
2011-01-21 15:31 ` H. Peter Anvin
2011-01-21 15:48 ` Tejun Heo
2011-01-21 16:30 ` H. Peter Anvin
2011-01-21 16:34 ` Tejun Heo
2011-01-21 16:54 ` Mathieu Desnoyers
2011-01-21 17:07 ` Christoph Lameter
2011-01-21 17:50 ` Mathieu Desnoyers
2011-01-21 18:06 ` Christoph Lameter
2011-01-21 18:37 ` Mathieu Desnoyers
2011-01-21 17:08 ` Tejun Heo
2011-01-21 17:13 ` H. Peter Anvin
2011-01-21 17:19 ` Tejun Heo
2011-01-24 6:01 ` H. Peter Anvin
2011-02-25 13:09 ` Pekka Enberg
2011-02-25 13:19 ` Tejun Heo
2011-02-25 16:26 ` Christoph Lameter
2011-02-25 16:37 ` Tejun Heo
2011-02-25 16:43 ` Christoph Lameter
2011-02-25 16:38 ` Eric Dumazet
2011-02-25 16:45 ` Christoph Lameter
2011-01-21 17:24 ` Christoph Lameter
2011-01-21 17:42 ` Mathieu Desnoyers
2011-01-21 17:50 ` Christoph Lameter
2011-01-21 18:10 ` Mathieu Desnoyers
2011-01-21 18:42 ` Christoph Lameter
2011-01-21 18:31 ` H. Peter Anvin
2011-01-21 18:46 ` Christoph Lameter
2011-01-21 19:32 ` Mathieu Desnoyers
2011-01-23 18:00 ` H. Peter Anvin
2011-01-06 20:45 ` [cpuops cmpxchg double V2 2/4] x86: this_cpu_cmpxchg_double() support Christoph Lameter
2011-01-06 20:45 ` [cpuops cmpxchg double V2 3/4] slub: Get rid of slab_free_hook_irq() Christoph Lameter
2011-01-06 20:45 ` [cpuops cmpxchg double V2 4/4] Lockless (and preemptless) fastpaths for slub Christoph Lameter
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=20110106204525.222395863@linux.com \
--to=cl@linux.com \
--cc=akpm@linux-foundation.org \
--cc=tj@kernel.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.