From: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
To: akpm@linux-foundation.org, linux-kernel@vger.kernel.org
Cc: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>,
clameter@sgi.com, mingo@redhat.com
Subject: [patch 01/23] Fall back on interrupt disable in cmpxchg8b on 80386 and 80486
Date: Mon, 20 Aug 2007 16:15:20 -0400 [thread overview]
Message-ID: <20070820201822.597720007@polymtl.ca> (raw)
In-Reply-To: 20070820201519.512791382@polymtl.ca
[-- Attachment #1: i386-cmpxchg64-80386-80486-fallback.patch --]
[-- Type: text/plain, Size: 7517 bytes --]
Actually, on 386, cmpxchg and cmpxchg_local fall back on
cmpxchg_386_u8/16/32: it disables interruptions around non atomic
updates to mimic the cmpxchg behavior.
The comment:
/* Poor man's cmpxchg for 386. Unsuitable for SMP */
already present in cmpxchg_386_u32 tells much about how this cmpxchg
implementation should not be used in a SMP context. However, the cmpxchg_local
can perfectly use this fallback, since it only needs to be atomic wrt the local
cpu.
This patch adds a cmpxchg_486_u64 and uses it as a fallback for cmpxchg64
and cmpxchg64_local on 80386 and 80486.
Q:
but why is it called cmpxchg_486 when the other functions are called
A:
Because the standard cmpxchg is missing only on 386, but cmpxchg8b is
missing both on 386 and 486.
Citing Intel's Instruction set reference:
cmpxchg:
This instruction is not supported on Intel processors earlier than the
Intel486 processors.
cmpxchg8b:
This instruction encoding is not supported on Intel processors earlier
than the Pentium processors.
Q:
What's the reason to have cmpxchg64_local on 32 bit architectures?
Without that need all this would just be a few simple defines.
A:
cmpxchg64_local on 32 bits architectures takes unsigned long long
parameters, but cmpxchg_local only takes longs. Since we have cmpxchg8b
to execute a 8 byte cmpxchg atomically on pentium and +, it makes sense
to provide a flavor of cmpxchg and cmpxchg_local using this instruction.
Also, for 32 bits architectures lacking the 64 bits atomic cmpxchg, it
makes sense _not_ to define cmpxchg64 while cmpxchg could still be
available.
Moreover, the fallback for cmpxchg8b on i386 for 386 and 486 is a
different case than cmpxchg (which is only required for 386). Using
different code makes this easier.
However, cmpxchg64_local will be emulated by disabling interrupts on all
architectures where it is not supported atomically.
Therefore, we *could* turn cmpxchg64_local into a cmpxchg_local, but it
would make the 386/486 fallbacks ugly, make its design different from
cmpxchg/cmpxchg64 (which really depends on atomic operations and cannot
be emulated) and require the __cmpxchg_local to be expressed as a macro
rather than an inline function so the parameters would not be fixed to
unsigned long long in every case.
So I think cmpxchg64_local makes sense there, but I am open to
suggestions.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
CC: clameter@sgi.com
CC: mingo@redhat.com
---
arch/i386/kernel/cpu/intel.c | 17 +++++++
include/asm-i386/cmpxchg.h | 100 +++++++++++++++++++++++++++++--------------
2 files changed, 85 insertions(+), 32 deletions(-)
Index: linux-2.6-lttng/arch/i386/kernel/cpu/intel.c
===================================================================
--- linux-2.6-lttng.orig/arch/i386/kernel/cpu/intel.c 2007-08-07 11:00:43.000000000 -0400
+++ linux-2.6-lttng/arch/i386/kernel/cpu/intel.c 2007-08-07 11:11:07.000000000 -0400
@@ -329,5 +329,22 @@ unsigned long cmpxchg_386_u32(volatile v
EXPORT_SYMBOL(cmpxchg_386_u32);
#endif
+#ifndef CONFIG_X86_CMPXCHG64
+unsigned long long cmpxchg_486_u64(volatile void *ptr, u64 old, u64 new)
+{
+ u64 prev;
+ unsigned long flags;
+
+ /* Poor man's cmpxchg8b for 386 and 486. Unsuitable for SMP */
+ local_irq_save(flags);
+ prev = *(u64 *)ptr;
+ if (prev == old)
+ *(u64 *)ptr = new;
+ local_irq_restore(flags);
+ return prev;
+}
+EXPORT_SYMBOL(cmpxchg_486_u64);
+#endif
+
// arch_initcall(intel_cpu_init);
Index: linux-2.6-lttng/include/asm-i386/cmpxchg.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-i386/cmpxchg.h 2007-08-07 11:01:17.000000000 -0400
+++ linux-2.6-lttng/include/asm-i386/cmpxchg.h 2007-08-07 11:16:42.000000000 -0400
@@ -116,6 +116,15 @@ static inline unsigned long __xchg(unsig
(unsigned long)(n),sizeof(*(ptr))))
#endif
+#ifdef CONFIG_X86_CMPXCHG64
+#define cmpxchg64(ptr,o,n)\
+ ((__typeof__(*(ptr)))__cmpxchg64((ptr),(unsigned long long)(o),\
+ (unsigned long long)(n)))
+#define cmpxchg64_local(ptr,o,n)\
+ ((__typeof__(*(ptr)))__cmpxchg64_local((ptr),(unsigned long long)(o),\
+ (unsigned long long)(n)))
+#endif
+
static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
unsigned long new, int size)
{
@@ -203,6 +212,34 @@ static inline unsigned long __cmpxchg_lo
return old;
}
+static inline unsigned long long __cmpxchg64(volatile void *ptr,
+ unsigned long long old, unsigned long long new)
+{
+ unsigned long long prev;
+ __asm__ __volatile__(LOCK_PREFIX "cmpxchg8b %3"
+ : "=A"(prev)
+ : "b"((unsigned long)new),
+ "c"((unsigned long)(new >> 32)),
+ "m"(*__xg(ptr)),
+ "0"(old)
+ : "memory");
+ return prev;
+}
+
+static inline unsigned long long __cmpxchg64_local(volatile void *ptr,
+ unsigned long long old, unsigned long long new)
+{
+ unsigned long long prev;
+ __asm__ __volatile__("cmpxchg8b %3"
+ : "=A"(prev)
+ : "b"((unsigned long)new),
+ "c"((unsigned long)(new >> 32)),
+ "m"(*__xg(ptr)),
+ "0"(old)
+ : "memory");
+ return prev;
+}
+
#ifndef CONFIG_X86_CMPXCHG
/*
* Building a kernel capable running on 80386. It may be necessary to
@@ -252,38 +289,37 @@ static inline unsigned long cmpxchg_386(
})
#endif
-static inline unsigned long long __cmpxchg64(volatile void *ptr, unsigned long long old,
- unsigned long long new)
-{
- unsigned long long prev;
- __asm__ __volatile__(LOCK_PREFIX "cmpxchg8b %3"
- : "=A"(prev)
- : "b"((unsigned long)new),
- "c"((unsigned long)(new >> 32)),
- "m"(*__xg(ptr)),
- "0"(old)
- : "memory");
- return prev;
-}
+#ifndef CONFIG_X86_CMPXCHG64
+/*
+ * Building a kernel capable running on 80386 and 80486. It may be necessary
+ * to simulate the cmpxchg8b on the 80386 and 80486 CPU.
+ */
+
+extern unsigned long long cmpxchg_486_u64(volatile void *, u64, u64);
+
+#define cmpxchg64(ptr,o,n) \
+({ \
+ __typeof__(*(ptr)) __ret; \
+ if (likely(boot_cpu_data.x86 > 4)) \
+ __ret = __cmpxchg64((ptr), (unsigned long long)(o), \
+ (unsigned long long)(n)); \
+ else \
+ __ret = cmpxchg_486_u64((ptr), (unsigned long long)(o), \
+ (unsigned long long)(n)); \
+ __ret; \
+})
+#define cmpxchg64_local(ptr,o,n) \
+({ \
+ __typeof__(*(ptr)) __ret; \
+ if (likely(boot_cpu_data.x86 > 4)) \
+ __ret = __cmpxchg64_local((ptr), (unsigned long long)(o), \
+ (unsigned long long)(n)); \
+ else \
+ __ret = cmpxchg_486_u64((ptr), (unsigned long long)(o), \
+ (unsigned long long)(n)); \
+ __ret; \
+})
-static inline unsigned long long __cmpxchg64_local(volatile void *ptr,
- unsigned long long old, unsigned long long new)
-{
- unsigned long long prev;
- __asm__ __volatile__("cmpxchg8b %3"
- : "=A"(prev)
- : "b"((unsigned long)new),
- "c"((unsigned long)(new >> 32)),
- "m"(*__xg(ptr)),
- "0"(old)
- : "memory");
- return prev;
-}
+#endif
-#define cmpxchg64(ptr,o,n)\
- ((__typeof__(*(ptr)))__cmpxchg64((ptr),(unsigned long long)(o),\
- (unsigned long long)(n)))
-#define cmpxchg64_local(ptr,o,n)\
- ((__typeof__(*(ptr)))__cmpxchg64_local((ptr),(unsigned long long)(o),\
- (unsigned long long)(n)))
#endif
--
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
next prev parent reply other threads:[~2007-08-20 20:21 UTC|newest]
Thread overview: 118+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-08-20 20:15 [patch 00/23] cmpxchg_local and cmpxchg64_local implementation Mathieu Desnoyers
2007-08-20 20:15 ` Mathieu Desnoyers [this message]
2007-08-20 20:32 ` [patch 01/23] Fall back on interrupt disable in cmpxchg8b on 80386 and 80486 Christoph Lameter
2007-08-20 20:41 ` Mathieu Desnoyers
2007-08-20 20:46 ` Christoph Lameter
2007-08-20 21:29 ` Mathieu Desnoyers
2007-08-20 21:49 ` Christoph Lameter
2007-08-20 21:54 ` Mathieu Desnoyers
2007-08-20 22:07 ` Christoph Lameter
2007-08-20 22:29 ` Mathieu Desnoyers
2007-08-21 17:38 ` [PATCH] SLUB Use cmpxchg() everywhere Mathieu Desnoyers
2007-08-21 17:38 ` [PATCH] SLUB use cmpxchg_local Mathieu Desnoyers
2007-08-21 17:44 ` Mathieu Desnoyers
2007-08-21 21:10 ` Christoph Lameter
2007-08-21 23:21 ` Mathieu Desnoyers
2007-08-21 23:35 ` Christoph Lameter
2007-08-21 23:38 ` Christoph Lameter
2007-08-21 20:41 ` Mathieu Desnoyers
2007-08-21 21:36 ` Christoph Lameter
2007-08-21 21:08 ` Christoph Lameter
2007-08-21 23:12 ` Mathieu Desnoyers
2007-08-21 23:17 ` Christoph Lameter
2007-08-21 23:39 ` Mathieu Desnoyers
2007-08-21 23:41 ` Christoph Lameter
2007-08-21 23:47 ` Mathieu Desnoyers
2007-08-21 23:51 ` Christoph Lameter
2007-08-22 0:03 ` Mathieu Desnoyers
2007-08-22 0:11 ` Christoph Lameter
2007-08-22 0:26 ` Mathieu Desnoyers
2007-08-22 0:34 ` Christoph Lameter
2007-08-22 1:18 ` Mathieu Desnoyers
2007-08-22 15:00 ` [PATCH] define have_arch_cmpxchg() Mathieu Desnoyers
2007-08-22 18:50 ` Christoph Lameter
2007-08-22 15:02 ` [PATCH] SLUB: use have_arch_cmpxchg() Mathieu Desnoyers
2007-08-22 16:24 ` Pekka Enberg
2007-08-27 14:56 ` Mathieu Desnoyers
2007-08-27 19:43 ` Christoph Lameter
2007-08-27 20:25 ` Mathieu Desnoyers
2007-08-22 1:28 ` [PATCH] SLUB use cmpxchg_local Andi Kleen
2007-08-22 0:38 ` Mathieu Desnoyers
2007-08-22 1:06 ` Christoph Lameter
2007-08-22 1:12 ` Mathieu Desnoyers
2007-08-22 9:39 ` Andi Kleen
2007-08-22 13:45 ` Mathieu Desnoyers
2007-08-22 13:46 ` Andi Kleen
2007-08-22 18:54 ` Christoph Lameter
2007-08-22 19:25 ` Christoph Lameter
2007-08-22 20:09 ` Mathieu Desnoyers
2007-08-22 20:19 ` Christoph Lameter
2007-08-22 20:29 ` Mathieu Desnoyers
2007-08-22 20:33 ` Christoph Lameter
2007-08-22 20:38 ` Christoph Lameter
2007-08-21 23:14 ` Christoph Lameter
2007-08-21 23:23 ` Mathieu Desnoyers
2007-08-21 23:50 ` Mathieu Desnoyers
2007-08-27 6:52 ` Peter Zijlstra
2007-08-27 19:39 ` Christoph Lameter
2007-08-27 20:22 ` Mathieu Desnoyers
2007-08-27 20:26 ` Christoph Lameter
2007-08-27 20:39 ` Mathieu Desnoyers
2007-08-27 21:04 ` Christoph Lameter
2007-08-27 21:10 ` Mathieu Desnoyers
2007-08-27 21:23 ` Christoph Lameter
2007-08-27 21:38 ` Mathieu Desnoyers
2007-08-27 22:12 ` Christoph Lameter
2007-08-27 22:27 ` Mathieu Desnoyers
2007-08-27 22:29 ` Christoph Lameter
2007-08-28 1:26 ` Christoph Lameter
2007-08-28 12:07 ` Mathieu Desnoyers
2007-08-28 19:42 ` Christoph Lameter
2007-09-04 20:02 ` Mathieu Desnoyers
2007-09-04 20:03 ` [PATCH] local_t protection (critical section) Mathieu Desnoyers
2007-09-04 20:04 ` [PATCH] slub - Use local_t protection Mathieu Desnoyers
2007-09-04 20:45 ` Christoph Lameter
2007-09-05 13:03 ` Mathieu Desnoyers
2007-09-05 13:04 ` [PATCH] local_t protection (critical section) Mathieu Desnoyers
2007-09-12 22:33 ` Christoph Lameter
2007-09-12 23:00 ` Mathieu Desnoyers
2007-09-05 13:06 ` [PATCH] slub - Use local_t protection Mathieu Desnoyers
2007-09-12 22:28 ` Christoph Lameter
2007-08-27 22:15 ` [PATCH] SLUB use cmpxchg_local Christoph Lameter
2007-08-28 7:12 ` Peter Zijlstra
2007-08-28 19:36 ` Christoph Lameter
2007-08-28 19:46 ` Peter Zijlstra
2007-08-20 20:15 ` [patch 02/23] Add cmpxchg_local to asm-generic for per cpu atomic operations Mathieu Desnoyers
2007-08-20 20:15 ` [patch 03/23] Add cmpxchg_local to arm Mathieu Desnoyers
2007-08-20 20:15 ` [patch 04/23] Add cmpxchg_local to avr32 Mathieu Desnoyers
2007-08-20 20:15 ` [patch 05/23] Add cmpxchg_local to blackfin, replace __cmpxchg by generic cmpxchg Mathieu Desnoyers
2007-08-20 20:15 ` [patch 06/23] Add cmpxchg_local to cris Mathieu Desnoyers
2007-08-20 20:15 ` [patch 07/23] Add cmpxchg_local to frv Mathieu Desnoyers
2007-08-20 20:15 ` [patch 08/23] Add cmpxchg_local to h8300 Mathieu Desnoyers
2007-08-20 20:15 ` [patch 09/23] Add cmpxchg_local, cmpxchg64 and cmpxchg64_local to ia64 Mathieu Desnoyers
2007-08-20 20:15 ` [patch 10/23] New cmpxchg_local (optimized for UP case) for m32r Mathieu Desnoyers
2007-08-21 9:36 ` Hirokazu Takata
2007-08-20 20:15 ` [patch 11/23] Fix m32r __xchg Mathieu Desnoyers
2007-08-21 9:39 ` Hirokazu Takata
2007-08-20 20:15 ` [patch 12/23] local_t m32r use architecture specific cmpxchg_local Mathieu Desnoyers
2007-08-21 9:34 ` Hirokazu Takata
2007-08-21 14:01 ` Mathieu Desnoyers
2007-08-20 20:15 ` [patch 13/23] Add cmpxchg_local to m86k Mathieu Desnoyers
2007-08-20 20:15 ` [patch 14/23] Add cmpxchg_local to m68knommu Mathieu Desnoyers
2007-08-20 20:15 ` [patch 15/23] Add cmpxchg_local to parisc Mathieu Desnoyers
2007-08-20 20:15 ` [patch 16/23] Add cmpxchg_local to ppc Mathieu Desnoyers
2007-08-20 20:15 ` [patch 17/23] Add cmpxchg_local to s390 Mathieu Desnoyers
2007-08-20 20:15 ` [patch 18/23] Add cmpxchg_local to sh, use generic cmpxchg() instead of cmpxchg_u32 Mathieu Desnoyers
2007-08-20 20:15 ` [patch 19/23] Add cmpxchg_local to sh64 Mathieu Desnoyers
2007-08-20 20:15 ` [patch 20/23] Add cmpxchg_local to sparc, move __cmpxchg to system.h Mathieu Desnoyers
2007-08-20 20:15 ` [patch 21/23] Add cmpxchg_local to sparc64 Mathieu Desnoyers
2007-08-20 23:34 ` Julian Calaby
2007-08-20 23:36 ` Christoph Lameter
2007-08-20 23:42 ` Julian Calaby
2007-08-20 23:43 ` [patch 21/23] Add cmpxchg_local to sparc64 (update) Mathieu Desnoyers
2007-08-20 20:15 ` [patch 22/23] Add cmpxchg_local to v850 Mathieu Desnoyers
2007-08-20 20:15 ` [patch 23/23] Add cmpxchg_local to xtensa Mathieu Desnoyers
2007-08-20 20:29 ` [patch 00/23] cmpxchg_local and cmpxchg64_local implementation Mathieu Desnoyers
-- strict thread matches above, loose matches on Subject: below --
2007-08-12 14:54 [patch 00/23] Atomic operations updates: add cmpxchg_local Mathieu Desnoyers
2007-08-12 14:54 ` [patch 01/23] Fall back on interrupt disable in cmpxchg8b on 80386 and 80486 Mathieu Desnoyers
2007-08-12 15:51 ` Jan Engelhardt
2007-08-12 16:23 ` Mathieu Desnoyers
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=20070820201822.597720007@polymtl.ca \
--to=mathieu.desnoyers@polymtl.ca \
--cc=akpm@linux-foundation.org \
--cc=clameter@sgi.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.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