Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cmpxchg.h
Go to the documentation of this file.
1 /* MN10300 Atomic xchg/cmpxchg operations
2  *
3  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4  * Written by David Howells ([email protected])
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public Licence
8  * as published by the Free Software Foundation; either version
9  * 2 of the Licence, or (at your option) any later version.
10  */
11 #ifndef _ASM_CMPXCHG_H
12 #define _ASM_CMPXCHG_H
13 
14 #include <asm/irqflags.h>
15 
16 #ifdef CONFIG_SMP
17 #ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
18 static inline
19 unsigned long __xchg(volatile unsigned long *m, unsigned long val)
20 {
21  unsigned long status;
22  unsigned long oldval;
23 
24  asm volatile(
25  "1: mov %4,(_AAR,%3) \n"
26  " mov (_ADR,%3),%1 \n"
27  " mov %5,(_ADR,%3) \n"
28  " mov (_ADR,%3),%0 \n" /* flush */
29  " mov (_ASR,%3),%0 \n"
30  " or %0,%0 \n"
31  " bne 1b \n"
32  : "=&r"(status), "=&r"(oldval), "=m"(*m)
33  : "a"(ATOMIC_OPS_BASE_ADDR), "r"(m), "r"(val)
34  : "memory", "cc");
35 
36  return oldval;
37 }
38 
39 static inline unsigned long __cmpxchg(volatile unsigned long *m,
40  unsigned long old, unsigned long new)
41 {
42  unsigned long status;
43  unsigned long oldval;
44 
45  asm volatile(
46  "1: mov %4,(_AAR,%3) \n"
47  " mov (_ADR,%3),%1 \n"
48  " cmp %5,%1 \n"
49  " bne 2f \n"
50  " mov %6,(_ADR,%3) \n"
51  "2: mov (_ADR,%3),%0 \n" /* flush */
52  " mov (_ASR,%3),%0 \n"
53  " or %0,%0 \n"
54  " bne 1b \n"
55  : "=&r"(status), "=&r"(oldval), "=m"(*m)
56  : "a"(ATOMIC_OPS_BASE_ADDR), "r"(m),
57  "r"(old), "r"(new)
58  : "memory", "cc");
59 
60  return oldval;
61 }
62 #else /* CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT */
63 #error "No SMP atomic operation support!"
64 #endif /* CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT */
65 
66 #else /* CONFIG_SMP */
67 
68 /*
69  * Emulate xchg for non-SMP MN10300
70  */
71 struct __xchg_dummy { unsigned long a[100]; };
72 #define __xg(x) ((struct __xchg_dummy *)(x))
73 
74 static inline
75 unsigned long __xchg(volatile unsigned long *m, unsigned long val)
76 {
77  unsigned long oldval;
78  unsigned long flags;
79 
80  flags = arch_local_cli_save();
81  oldval = *m;
82  *m = val;
84  return oldval;
85 }
86 
87 /*
88  * Emulate cmpxchg for non-SMP MN10300
89  */
90 static inline unsigned long __cmpxchg(volatile unsigned long *m,
91  unsigned long old, unsigned long new)
92 {
93  unsigned long oldval;
94  unsigned long flags;
95 
96  flags = arch_local_cli_save();
97  oldval = *m;
98  if (oldval == old)
99  *m = new;
100  arch_local_irq_restore(flags);
101  return oldval;
102 }
103 
104 #endif /* CONFIG_SMP */
105 
106 #define xchg(ptr, v) \
107  ((__typeof__(*(ptr))) __xchg((unsigned long *)(ptr), \
108  (unsigned long)(v)))
109 
110 #define cmpxchg(ptr, o, n) \
111  ((__typeof__(*(ptr))) __cmpxchg((unsigned long *)(ptr), \
112  (unsigned long)(o), \
113  (unsigned long)(n)))
114 
115 #endif /* _ASM_CMPXCHG_H */