Fix use of inline in IMD
[alexxy/gromacs.git] / src / gromacs / legacyheaders / thread_mpi / atomic / gcc_ppc.h
1 /*
2    This source code file is part of thread_mpi.
3    Written by Sander Pronk, Erik Lindahl, and possibly others.
4
5    Copyright (c) 2009, Sander Pronk, Erik Lindahl.
6    All rights reserved.
7
8    Redistribution and use in source and binary forms, with or without
9    modification, are permitted provided that the following conditions are met:
10    1) Redistributions of source code must retain the above copyright
11    notice, this list of conditions and the following disclaimer.
12    2) Redistributions in binary form must reproduce the above copyright
13    notice, this list of conditions and the following disclaimer in the
14    documentation and/or other materials provided with the distribution.
15    3) Neither the name of the copyright holders nor the
16    names of its contributors may be used to endorse or promote products
17    derived from this software without specific prior written permission.
18
19    THIS SOFTWARE IS PROVIDED BY US ''AS IS'' AND ANY
20    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22    DISCLAIMED. IN NO EVENT SHALL WE BE LIABLE FOR ANY
23    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30    If you want to redistribute modifications, please consider that
31    scientific software is very special. Version control is crucial -
32    bugs must be traceable. We will be happy to consider code for
33    inclusion in the official distribution, but derived work should not
34    be called official thread_mpi. Details are found in the README & COPYING
35    files.
36  */
37
38
39 /* NOTE:
40
41  ***************************************************************************
42    this file is not used any more. gcc intrinsics take care of the atomics
43  ***************************************************************************
44
45  */
46
47 #error included gcc_ppc.h. This file is outdated
48
49
50
51 typedef struct tMPI_Atomic
52 {
53     volatile int value;   /*!< Volatile, to avoid compiler aliasing */
54 }
55 tMPI_Atomic_t;
56
57 typedef struct tMPI_Atomic_ptr
58 {
59     void* volatile* value;   /*!< Volatile, to avoid compiler aliasing */
60 }
61 tMPI_Atomic_ptr_t;
62
63
64 typedef struct tMPI_Spinlock
65 {
66     volatile unsigned int lock;   /*!< Volatile, to avoid compiler aliasing */
67 }
68 tMPI_Spinlock_t;
69 #define TMPI_ATOMIC_HAVE_NATIVE_SPINLOCK
70
71
72 #define TMPI_SPINLOCK_INITIALIZER   { 0 }
73
74 #define tMPI_Atomic_get(a)        ((a)->value)
75 #define tMPI_Atomic_set(a, i)     (((a)->value) = (i))
76
77 #define tMPI_Atomic_ptr_get(a)    (void*)((a)->value)
78 #define tMPI_Atomic_ptr_set(a, i)  (((a)->value) = (void*)(i))
79
80
81 #if (TMPI_GCC_VERSION >= 40100)
82
83 #include "gcc_intrinsics.h"
84
85 #else
86
87 /* Compiler-dependent stuff: GCC memory barrier */
88 #define tMPI_Atomic_memory_barrier() __asm__ __volatile__("isync" : : : "memory")
89
90
91
92 #define TMPI_ATOMIC_HAVE_NATIVE_SWAP
93 static inline int tMPI_Atomic_swap(tMPI_Atomic_t *a, int b)
94 {
95     int ret;
96
97     __asm__ __volatile__ ("1:    lwarx   %0,0,%2 \n"
98                           "\tstwcx.  %3,0,%2 \n"
99                           "\tbne-    1b\n"
100                           : "=&r" (ret), "=m" (a->value)
101                           : "r" (&(a->value)), "r" (b)
102                           : "cc", "memory");
103
104     return ret;
105 }
106
107 static inline void* tMPI_Atomic_ptr_swap(tMPI_Atomic_ptr_t *a, void *b)
108 {
109     int ret;
110
111 #if (!defined(__PPC64__)) && (!defined(__ppc64))
112     __asm__ __volatile__ ("1:    lwarx   %0,0,%2 \n"
113                           "\tstwcx.  %3,0,%2 \n"
114                           "\tbne-    1b\n"
115                           : "=&r" (ret), "=m" (a->value)
116                           : "r" (&(a->value)), "r" (b)
117                           : "cc", "memory");
118 #else
119     __asm__ __volatile__ ("1:    ldarx   %0,0,%2 \n"
120                           "\tstdcx.  %3,0,%2 \n"
121                           "\tbne-    1b\n"
122                           : "=&r" (ret), "=m" (a->value)
123                           : "r" (&(a->value)), "r" (b)
124                           : "cc", "memory");
125 #endif
126
127     return ret;
128 }
129
130
131
132 static inline int tMPI_Atomic_cas(tMPI_Atomic_t *a, int oldval, int newval)
133 {
134     int prev;
135
136     __asm__ __volatile__ ("1:    lwarx   %0,0,%2 \n"
137                           "\tcmpw    0,%0,%3 \n"
138                           "\tbne     2f \n"
139                           "\tstwcx.  %4,0,%2 \n"
140                           "bne-    1b\n"
141                           "\tsync\n"
142                           "2:\n"
143                           : "=&r" (prev), "=m" (a->value)
144                           : "r" (&a->value), "r" (oldval), "r" (newval),
145                           "m" (a->value)
146                           : "cc", "memory");
147
148     return prev == oldval;
149 }
150
151
152 static inline int tMPI_Atomic_ptr_cas(tMPI_Atomic_ptr_t *a, void *oldval,
153                                       void *newval)
154 {
155     void *prev;
156
157 #if (!defined(__PPC64__)) && (!defined(__ppc64))
158     __asm__ __volatile__ ("1:    lwarx   %0,0,%2 \n"
159                           "\tcmpw    0,%0,%3 \n"
160                           "\tbne     2f \n"
161                           "\tstwcx.  %4,0,%2 \n"
162                           "bne-    1b\n"
163                           "\tsync\n"
164                           "2:\n"
165                           : "=&r" (prev), "=m" (a->value)
166                           : "r" (&a->value), "r" (oldval), "r" (newval),
167                           "m" (a->value)
168                           : "cc", "memory");
169 #else
170     __asm__ __volatile__ ("1:    ldarx   %0,0,%2 \n"
171                           "\tcmpd    0,%0,%3 \n"
172                           "\tbne     2f \n"
173                           "\tstdcx.  %4,0,%2 \n"
174                           "bne-    1b\n"
175                           "\tsync\n"
176                           "2:\n"
177                           : "=&r" (prev), "=m" (a->value)
178                           : "r" (&a->value), "r" (oldval), "r" (newval),
179                           "m" (a->value)
180                           : "cc", "memory");
181 #endif
182     return prev == oldval;
183 }
184
185 #define TMPI_ATOMIC_HAVE_NATIVE_ADD_RETURN
186 static inline int tMPI_Atomic_add_return(tMPI_Atomic_t *a, int i)
187 {
188     int t;
189
190     __asm__ __volatile__("1:     lwarx   %0,0,%2\n"
191                          "\tadd     %0,%1,%0\n"
192                          "\tstwcx.  %0,0,%2 \n"
193                          "\tbne-    1b\n"
194                          "\tisync\n"
195                          : "=&r" (t)
196                          : "r" (i), "r" (&a->value)
197                          : "cc", "memory");
198     return t;
199 }
200
201
202
203 #define TMPI_ATOMIC_HAVE_NATIVE_FETCH_ADD
204 static inline int tMPI_Atomic_fetch_add(tMPI_Atomic_t *a, int i)
205 {
206     int t;
207
208     __asm__ __volatile__("\teieio\n"
209                          "1:     lwarx   %0,0,%2\n"
210                          "\tadd     %0,%1,%0\n"
211                          "\tstwcx.  %0,0,%2 \n"
212                          "\tbne-    1b\n"
213                          "\tisync\n"
214                          : "=&r" (t)
215                          : "r" (i), "r" (&a->value)
216                          : "cc", "memory");
217
218     return (t - i);
219 }
220
221
222 #endif
223
224
225 static inline void tMPI_Spinlock_init(tMPI_Spinlock_t *x)
226 {
227     x->lock = 0;
228 }
229
230
231
232 static inline void tMPI_Spinlock_lock(tMPI_Spinlock_t *x)
233 {
234     unsigned int tmp;
235
236     __asm__ __volatile__("\tb      1f\n"
237                          "2:      lwzx    %0,0,%1\n"
238                          "\tcmpwi   0,%0,0\n"
239                          "\tbne+    2b\n"
240                          "1:      lwarx   %0,0,%1\n"
241                          "\tcmpwi   0,%0,0\n"
242                          "\tbne-    2b\n"
243                          "\tstwcx.  %2,0,%1\n"
244                          "bne-    2b\n"
245                          "\tisync\n"
246                          : "=&r" (tmp)
247                          : "r" (&x->lock), "r" (1)
248                          : "cr0", "memory");
249 }
250
251
252 static inline int tMPI_Spinlock_trylock(tMPI_Spinlock_t *x)
253 {
254     unsigned int           old, t;
255     unsigned int           mask = 1;
256     volatile unsigned int *p    = &x->lock;
257
258     __asm__ __volatile__("\teieio\n"
259                          "1:      lwarx   %0,0,%4 \n"
260                          "\tor      %1,%0,%3 \n"
261                          "\tstwcx.  %1,0,%4 \n"
262                          "\tbne     1b\n"
263                          "\tsync\n"
264                          : "=&r" (old), "=&r" (t), "=m" (*p)
265                          : "r" (mask), "r" (p), "m" (*p)
266                          : "cc", "memory");
267
268     return (old & mask);
269 }
270
271
272 static inline void tMPI_Spinlock_unlock(tMPI_Spinlock_t *x)
273 {
274     __asm__ __volatile__("\teieio\n" : : : "memory");
275     x->lock = 0;
276 }
277
278
279 static inline int tMPI_Spinlock_islocked(const tMPI_Spinlock_t *x)
280 {
281     return ( x->lock != 0);
282 }
283
284
285 static inline void tMPI_Spinlock_wait(tMPI_Spinlock_t *x)
286 {
287     do
288     {
289         tMPI_Atomic_memory_barrier();
290     }
291     while (tMPI_Spinlock_islocked(x));
292 }