Re: 2.6.25.X-rtX compile errors on ARM due to cmpxchg() problems.

From: Remy Bohmer
Date: Wed Jul 16 2008 - 14:37:11 EST

Hello Steven,

A while ago I already mentioned that 2.6.25 did not compile on ARM.
(e.g. AT91SAM9261-EK)
Today I looked at it again with the latest 2.6.25 kernel with latest RT-patch.

Several errors are gone, but I still I get these warnings on every
file that is being compiled:
CC arch/arm/kernel/asm-offsets.s
In file included from include/linux/rt_lock.h:14,
from include/linux/spinlock.h:117,
from include/linux/seqlock.h:29,
from include/linux/time.h:8,
from include/linux/timex.h:57,
from include/linux/sched.h:54,
from arch/arm/kernel/asm-offsets.c:13:
include/asm/atomic.h:241:1: warning: "cmpxchg" redefined
In file included from include/asm/system.h:378,
from include/asm/bitops.h:27,
from include/linux/bitops.h:17,
from include/linux/kernel.h:15,
from include/linux/sched.h:52,
from arch/arm/kernel/asm-offsets.c:13:
include/asm-generic/cmpxchg.h:19:1: warning: this is the location of
the previous definition
and many more...

I looked at the broken-out series which patches are causing these
warnings and these are the offending patches:
* arm-fix-atomic-cmpxchg.patch
* arm-cmpxchg.patch

When these patches are removed from the Preempt-RT patchset everything
compiles again, without warnings.

But these patches are probably there for a reason, and leaving them
out could break some things. (Although I believe that these patches
are just there because they apply on 2.6.25-RT)

But, Here I need some (RT-mutex-expert) review help.

Because this ARM architecture (ARM <= V5) does not have a real
cmpxchg() assembler
instruction, and the implementation is almost the same as the generic
definition, the generic definition can be used instead.
However, The generic implementation does NOT define __HAVE_ARCH_CMPXCHG.

My questions are:
* What are the results of NOT defining __HAVE_ARCH_CMPXCHG in
kernel/rtmutex.c ?
* Does the RT-mutex still behave correctly?
* Why is this check in rtmutex.c ? Is it really needed, because there
is always a generic implementation of cmpxchg() these days?

FURTHER: The patch arm-fix-atomic-cmpxchg.patch made the
local_irq_save() a raw_local_irq_save().
Looking at the generic implementation I believe that this code should
also use the raw_* types. I attached a new patch for this to this

So, attached 3 patches:
* revert-arm-fix-atomic-cmpxchg.patch (reverts the same named patch in
preempt-RT set)
* revert-arm-cmpxchg.patch (reverts the same named patch in preempt-RT set)
* make-generic-cmpxchg-use-raw-intlock-types.patch

Can you clear some things up here? And also repair the RT-patch for
ARM and 2.6.25 ;-) (and newer)

Kind regards,

Make generic cmpxchg() use raw_local_irq_save()

The generic routines for the cmpxchg() code path should use the raw_*
types on preempt-RT.

Signed-off-by: Remy Bohmer <linux@xxxxxxxxxx>
include/asm-generic/cmpxchg-local.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

Index: linux-
--- linux- 2008-07-13 20:00:25.000000000 +0200
+++ linux- 2008-07-16 19:38:34.000000000 +0200
@@ -20,7 +20,7 @@ static inline unsigned long __cmpxchg_lo
if (size == 8 && sizeof(unsigned long) != 8)

- local_irq_save(flags);
+ raw_local_irq_save(flags);
switch (size) {
case 1: prev = *(u8 *)ptr;
if (prev == old)
@@ -41,7 +41,7 @@ static inline unsigned long __cmpxchg_lo
- local_irq_restore(flags);
+ raw_local_irq_restore(flags);
return prev;

@@ -54,11 +54,11 @@ static inline u64 __cmpxchg64_local_gene
u64 prev;
unsigned long flags;

- local_irq_save(flags);
+ raw_local_irq_save(flags);
prev = *(u64 *)ptr;
if (prev == old)
*(u64 *)ptr = new;
- local_irq_restore(flags);
+ raw_local_irq_restore(flags);
return prev;

Revert the patch named arm-cmpxchg.patch in the preempt-rt patchset

Currently the patch arm-cmpxchg.patch is part of the preempt-rt
patchset. Although it applies correctly, it introduces now a 2nd
implementation of the cmpxchg() macro, and thus a compile error.

Because this architecture does not have a real cmpxchg() assembler
instruction, and the implementation is almost the same as the generic
definition, the generic definition is now used instead.

BUT: the __HAVE_ARCH_CMPXCHG is not set any longer, because it is not
set in the generic implementation. Some review is required
for the kernel/rtmutex.c code to make sure the code still
behaves well without this flag set.

I have only compile tested this patch!
I have not confronted any hardware with this patch yet.
**** REVIEW REQUIRED on rtmutex code! ****

NOTE: Instead of applying this patch, it is even better to remove
the arm-cmpxchg.patch from the preempt-rt set because this patch
only reverts that patch.

Signed-off-by: Remy Bohmer <linux@xxxxxxxxxx>
include/asm-arm/atomic.h | 35 -----------------------------------
1 file changed, 35 deletions(-)

Index: linux-
--- linux- 2008-07-16 17:14:01.000000000 +0200
+++ linux- 2008-07-16 17:15:15.000000000 +0200
@@ -213,41 +213,6 @@ static inline void atomic_clear_mask(uns

-#ifndef CONFIG_SMP
- * Atomic compare and exchange.
- */
-#define __HAVE_ARCH_CMPXCHG 1
-extern unsigned long wrong_size_cmpxchg(volatile void *ptr);
-static inline unsigned long __cmpxchg(volatile void *ptr,
- unsigned long old,
- unsigned long new, int size)
- unsigned long flags, prev;
- volatile unsigned long *p = ptr;
- if (size == 4) {
- local_irq_save(flags);
- if ((prev = *p) == old)
- *p = new;
- local_irq_restore(flags);
- return(prev);
- } else
- return wrong_size_cmpxchg(ptr);
-#define cmpxchg(ptr,o,n) \
-({ \
- __typeof__(*(ptr)) _o_ = (o); \
- __typeof__(*(ptr)) _n_ = (n); \
- (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
- (unsigned long)_n_, sizeof(*(ptr))); \
#endif /* __LINUX_ARM_ARCH__ */

#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
Revert patch arm-fix-atomic-cmpxchg.patch in preempt-rt patchset

To be able to revert the patch arm-cmpxchg.patch this patch has to be
reverted also.
(Actually this change has been moved to the include/asm-generic/cmpxchg-local.h
through another patch)

Signed-off-by: Remy Bohmer <linux@xxxxxxxxxx>
include/asm-arm/atomic.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

Index: linux-
--- linux- 2008-07-16 17:08:42.000000000 +0200
+++ linux- 2008-07-16 17:14:01.000000000 +0200
@@ -229,10 +229,10 @@ static inline unsigned long __cmpxchg(vo
volatile unsigned long *p = ptr;

if (size == 4) {
- raw_local_irq_save(flags);
+ local_irq_save(flags);
if ((prev = *p) == old)
*p = new;
- raw_local_irq_restore(flags);
+ local_irq_restore(flags);
} else
return wrong_size_cmpxchg(ptr);