OpenMPI 0.1.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

atomic.h
1 /*
2 * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
3 * University Research and Technology
4 * Corporation. All rights reserved.
5 * Copyright (c) 2004-2005 The University of Tennessee and The University
6 * of Tennessee Research Foundation. All rights
7 * reserved.
8 * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
9 * University of Stuttgart. All rights reserved.
10 * Copyright (c) 2004-2005 The Regents of the University of California.
11 * All rights reserved.
12 * $COPYRIGHT$
13 *
14 * Additional copyrights may follow
15 *
16 * $HEADER$
17 */
18
19 #ifndef OMPI_SYS_ARCH_ATOMIC_H
20 #define OMPI_SYS_ARCH_ATOMIC_H 1
21
22
23 #if OPAL_WANT_SMP_LOCKS
24
25 /* BWB - FIX ME! */
26 #ifdef __linux__
27 #define MB() __asm__ __volatile__(".set mips2; sync; .set mips0": : :"memory")
28 #define RMB() __asm__ __volatile__(".set mips2; sync; .set mips0": : :"memory")
29 #define WMB() __asm__ __volatile__(".set mips2; sync; .set mips0": : :"memory")
30 #define SMP_SYNC ".set mips2; sync; .set mips0"
31 #else
32 #define MB() __asm__ __volatile__("sync": : :"memory")
33 #define RMB() __asm__ __volatile__("sync": : :"memory")
34 #define WMB() __asm__ __volatile__("sync": : :"memory")
35 #define SMP_SYNC "sync"
36 #endif
37
38 #else
39
40 #define MB()
41 #define RMB()
42 #define WMB()
43 #define SMP_SYNC ""
44
45 #endif
46
47
48 /**********************************************************************
49 *
50 * Define constants for MIPS
51 *
52 *********************************************************************/
53 #define OPAL_HAVE_ATOMIC_MEM_BARRIER 1
54
55 #define OPAL_HAVE_ATOMIC_CMPSET_32 1
56
57 #ifdef __mips64
58 #define OPAL_HAVE_ATOMIC_CMPSET_64 1
59 #endif
60
61 /**********************************************************************
62 *
63 * Memory Barriers
64 *
65 *********************************************************************/
66 #if OMPI_GCC_INLINE_ASSEMBLY
67
68 static inline
69 void opal_atomic_mb(void)
70 {
71 MB();
72 }
73
74
75 static inline
76 void opal_atomic_rmb(void)
77 {
78 RMB();
79 }
80
81
82 static inline
83 void opal_atomic_wmb(void)
84 {
85 WMB();
86 }
87
88 #endif
89
90 /**********************************************************************
91 *
92 * Atomic math operations
93 *
94 *********************************************************************/
95 #if OMPI_GCC_INLINE_ASSEMBLY
96
97 static inline int opal_atomic_cmpset_32(volatile int32_t *addr,
98 int32_t oldval, int32_t newval)
99 {
100 int32_t ret;
101
102 __asm__ __volatile__ (".set noreorder \n"
103 ".set noat \n"
104 "1: \n"
105 #ifdef __linux__
106 ".set mips2 \n\t"
107 #endif
108 "ll %0, %2 \n" /* load *addr into ret */
109 "bne %0, %z3, 2f \n" /* done if oldval != ret */
110 "or $1, %z4, 0 \n" /* tmp = newval (delay slot) */
111 "sc $1, %2 \n" /* store tmp in *addr */
112 #ifdef __linux__
113 ".set mips0 \n\t"
114 #endif
115 /* note: ret will be 0 if failed, 1 if succeeded */
116 "beqz $1, 1b \n" /* if 0 jump back to 1b */
117 "nop \n" /* fill delay slots */
118 "2: \n"
119 ".set reorder \n"
120 : "=&r"(ret), "=m"(*addr)
121 : "m"(*addr), "r"(oldval), "r"(newval)
122 : "cc", "memory");
123 return (ret == oldval);
124 }
125
126
127 /* these two functions aren't inlined in the non-gcc case because then
128 there would be two function calls (since neither cmpset_32 nor
129 atomic_?mb can be inlined). Instead, we "inline" them by hand in
130 the assembly, meaning there is one function call overhead instead
131 of two */
132 static inline int opal_atomic_cmpset_acq_32(volatile int32_t *addr,
133 int32_t oldval, int32_t newval)
134 {
135 int rc;
136
137 rc = opal_atomic_cmpset_32(addr, oldval, newval);
138 opal_atomic_rmb();
139
140 return rc;
141 }
142
143
144 static inline int opal_atomic_cmpset_rel_32(volatile int32_t *addr,
145 int32_t oldval, int32_t newval)
146 {
147 opal_atomic_wmb();
148 return opal_atomic_cmpset_32(addr, oldval, newval);
149 }
150
151 #ifdef OPAL_HAVE_ATOMIC_CMPSET_64
152 static inline int opal_atomic_cmpset_64(volatile int64_t *addr,
153 int64_t oldval, int64_t newval)
154 {
155 int64_t ret;
156
157 __asm__ __volatile__ (".set noreorder \n"
158 ".set noat \n"
159 "1: \n\t"
160 "lld %0, %2 \n\t" /* load *addr into ret */
161 "bne %0, %z3, 2f \n\t" /* done if oldval != ret */
162 "or $1, %4, 0 \n\t" /* tmp = newval (delay slot) */
163 "scd $1, %2 \n\t" /* store tmp in *addr */
164 /* note: ret will be 0 if failed, 1 if succeeded */
165 "beqz $1, 1b \n\t" /* if 0 jump back to 1b */
166 "nop \n\t" /* fill delay slot */
167 "2: \n\t"
168 ".set reorder \n"
169 : "=&r" (ret), "=m" (*addr)
170 : "m" (*addr), "r" (oldval), "r" (newval)
171 : "cc", "memory");
172
173 return (ret == oldval);
174 }
175
176
177 /* these two functions aren't inlined in the non-gcc case because then
178 there would be two function calls (since neither cmpset_64 nor
179 atomic_?mb can be inlined). Instead, we "inline" them by hand in
180 the assembly, meaning there is one function call overhead instead
181 of two */
182 static inline int opal_atomic_cmpset_acq_64(volatile int64_t *addr,
183 int64_t oldval, int64_t newval)
184 {
185 int rc;
186
187 rc = opal_atomic_cmpset_64(addr, oldval, newval);
188 opal_atomic_rmb();
189
190 return rc;
191 }
192
193
194 static inline int opal_atomic_cmpset_rel_64(volatile int64_t *addr,
195 int64_t oldval, int64_t newval)
196 {
197 opal_atomic_wmb();
198 return opal_atomic_cmpset_64(addr, oldval, newval);
199 }
200 #endif /* OPAL_HAVE_ATOMIC_CMPSET_64 */
201
202 #endif /* OMPI_GCC_INLINE_ASSEMBLY */
203
204 #endif /* ! OMPI_SYS_ARCH_ATOMIC_H */
opal_atomic_rmb
void opal_atomic_rmb(void)
Read memory barrier.
opal_atomic_mb
void opal_atomic_mb(void)
Memory barrier.
opal_atomic_wmb
void opal_atomic_wmb(void)
Write memory barrier.