OpenMPI  0.1.1
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 (c) 2007 Sun Microsystems, Inc. All rights reserverd.
13  * $COPYRIGHT$
14  *
15  * Additional copyrights may follow
16  *
17  * $HEADER$
18  */
19 
20 #ifndef OMPI_SYS_ARCH_ATOMIC_H
21 #define OMPI_SYS_ARCH_ATOMIC_H 1
22 
23 /*
24  * On sparc v9, use casa and casxa (compare and swap) instructions.
25  */
26 
27 #define ASI_P "0x80"
28 
29 #if OPAL_WANT_SMP_LOCKS
30 #define MEMBAR(type) __asm__ __volatile__ ("membar " type : : : "memory")
31 #else
32 #define MEMBAR(type)
33 #endif
34 
35 
36 /**********************************************************************
37  *
38  * Define constants for Sparc v9 (Ultra Sparc)
39  *
40  *********************************************************************/
41 #define OPAL_HAVE_ATOMIC_MEM_BARRIER 1
42 
43 #define OPAL_HAVE_ATOMIC_CMPSET_32 1
44 
45 #define OPAL_HAVE_ATOMIC_CMPSET_64 1
46 
47 
48 /**********************************************************************
49  *
50  * Memory Barriers
51  *
52  *********************************************************************/
53 #if OMPI_GCC_INLINE_ASSEMBLY
54 
55 static inline void opal_atomic_mb(void)
56 {
57  MEMBAR("#LoadLoad | #LoadStore | #StoreStore | #StoreLoad");
58 }
59 
60 
61 static inline void opal_atomic_rmb(void)
62 {
63  MEMBAR("#LoadLoad");
64 }
65 
66 
67 static inline void opal_atomic_wmb(void)
68 {
69  MEMBAR("#StoreStore");
70 }
71 
72 #endif /* OMPI_GCC_INLINE_ASSEMBLY */
73 
74 
75 /**********************************************************************
76  *
77  * Atomic math operations
78  *
79  *********************************************************************/
80 #if OMPI_GCC_INLINE_ASSEMBLY
81 
82 static inline int opal_atomic_cmpset_32( volatile int32_t *addr,
83  int32_t oldval, int32_t newval)
84 {
85  /* casa [reg(rs1)] %asi, reg(rs2), reg(rd)
86  *
87  * if (*(reg(rs1)) == reg(rs1) )
88  * swap reg(rd), *(reg(rs1))
89  * else
90  * reg(rd) = *(reg(rs1))
91  */
92 
93  int32_t ret = newval;
94 
95  __asm__ __volatile__("casa [%1] " ASI_P ", %2, %0"
96  : "+r" (ret)
97  : "r" (addr), "r" (oldval));
98  return (ret == oldval);
99 }
100 
101 
102 static inline int opal_atomic_cmpset_acq_32( volatile int32_t *addr,
103  int32_t oldval, int32_t newval)
104 {
105  int rc;
106 
107  rc = opal_atomic_cmpset_32(addr, oldval, newval);
108  opal_atomic_rmb();
109 
110  return rc;
111 }
112 
113 
114 static inline int opal_atomic_cmpset_rel_32( volatile int32_t *addr,
115  int32_t oldval, int32_t newval)
116 {
117  opal_atomic_wmb();
118  return opal_atomic_cmpset_32(addr, oldval, newval);
119 }
120 
121 
122 #if OPAL_ASSEMBLY_ARCH == OMPI_SPARCV9_64
123 
124 static inline int opal_atomic_cmpset_64( volatile int64_t *addr,
125  int64_t oldval, int64_t newval)
126 {
127  /* casa [reg(rs1)] %asi, reg(rs2), reg(rd)
128  *
129  * if (*(reg(rs1)) == reg(rs1) )
130  * swap reg(rd), *(reg(rs1))
131  * else
132  * reg(rd) = *(reg(rs1))
133  */
134  int64_t ret = newval;
135 
136  __asm__ __volatile__("casxa [%1] " ASI_P ", %2, %0"
137  : "+r" (ret)
138  : "r" (addr), "r" (oldval));
139  return (ret == oldval);
140 }
141 
142 #else /* OPAL_ASSEMBLY_ARCH == OMPI_SPARCV9_64 */
143 
144 static inline int opal_atomic_cmpset_64( volatile int64_t *addr,
145  int64_t oldval, int64_t newval)
146 {
147  /* casa [reg(rs1)] %asi, reg(rs2), reg(rd)
148  *
149  * if (*(reg(rs1)) == reg(rs1) )
150  * swap reg(rd), *(reg(rs1))
151  * else
152  * reg(rd) = *(reg(rs1))
153  *
154  */
155  long long ret = newval;
156 
157  __asm__ __volatile__(
158  "ldx %0, %%g1 \n\t" /* g1 = ret */
159  "ldx %2, %%g2 \n\t" /* g2 = oldval */
160  "casxa [%1] " ASI_P ", %%g2, %%g1 \n\t"
161  "stx %%g1, %0 \n"
162  : "+m"(ret)
163  : "r"(addr), "m"(oldval)
164  : "%g1", "%g2"
165  );
166 
167  return (ret == oldval);
168 }
169 
170 #endif /* OPAL_ASSEMBLY_ARCH == OMPI_SPARCV9_64 */
171 
172 static inline int opal_atomic_cmpset_acq_64( volatile int64_t *addr,
173  int64_t oldval, int64_t newval)
174 {
175  int rc;
176 
177  rc = opal_atomic_cmpset_64(addr, oldval, newval);
178  opal_atomic_rmb();
179 
180  return rc;
181 }
182 
183 
184 static inline int opal_atomic_cmpset_rel_64( volatile int64_t *addr,
185  int64_t oldval, int64_t newval)
186 {
187  opal_atomic_wmb();
188  return opal_atomic_cmpset_64(addr, oldval, newval);
189 }
190 
191 #endif /* OMPI_GCC_INLINE_ASSEMBLY */
192 
193 
194 #endif /* ! OMPI_SYS_ARCH_ATOMIC_H */
void opal_atomic_rmb(void)
Read memory barrier.
void opal_atomic_mb(void)
Memory barrier.
void opal_atomic_wmb(void)
Write memory barrier.