]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/atomic.h
Inital import
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / libc / sysdeps / linux / sh / bits / atomic.h
1 /* Atomic operations used inside libc.  Linux/SH version.
2    Copyright (C) 2003 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <stdint.h>
21
22
23 typedef int8_t atomic8_t;
24 typedef uint8_t uatomic8_t;
25 typedef int_fast8_t atomic_fast8_t;
26 typedef uint_fast8_t uatomic_fast8_t;
27
28 typedef int16_t atomic16_t;
29 typedef uint16_t uatomic16_t;
30 typedef int_fast16_t atomic_fast16_t;
31 typedef uint_fast16_t uatomic_fast16_t;
32
33 typedef int32_t atomic32_t;
34 typedef uint32_t uatomic32_t;
35 typedef int_fast32_t atomic_fast32_t;
36 typedef uint_fast32_t uatomic_fast32_t;
37
38 typedef int64_t atomic64_t;
39 typedef uint64_t uatomic64_t;
40 typedef int_fast64_t atomic_fast64_t;
41 typedef uint_fast64_t uatomic_fast64_t;
42
43 typedef intptr_t atomicptr_t;
44 typedef uintptr_t uatomicptr_t;
45 typedef intmax_t atomic_max_t;
46 typedef uintmax_t uatomic_max_t;
47
48 /* SH kernel has implemented a gUSA ("g" User Space Atomicity) support
49    for the user space atomicity. The atomicity macros use this scheme.
50
51   Reference:
52     Niibe Yutaka, "gUSA: Simple and Efficient User Space Atomicity
53     Emulation with Little Kernel Modification", Linux Conference 2002,
54     Japan. http://lc.linux.or.jp/lc2002/papers/niibe0919h.pdf (in
55     Japanese).
56
57     B.N. Bershad, D. Redell, and J. Ellis, "Fast Mutual Exclusion for
58     Uniprocessors",  Proceedings of the Fifth Architectural Support for
59     Programming Languages and Operating Systems (ASPLOS), pp. 223-233,
60     October 1992. http://www.cs.washington.edu/homes/bershad/Papers/Rcs.ps
61
62   SuperH ABI:
63       r15:    -(size of atomic instruction sequence) < 0
64       r0:     end point
65       r1:     saved stack pointer
66 */
67
68 #define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \
69   ({ __typeof (*(mem)) __result; \
70      __asm__ __volatile__ ("\
71         .align 2\n\
72         mova 1f,r0\n\
73         nop\n\
74         mov r15,r1\n\
75         mov #-8,r15\n\
76      0: mov.b @%1,%0\n\
77         cmp/eq %0,%3\n\
78         bf 1f\n\
79         mov.b %2,@%1\n\
80      1: mov r1,r15"\
81         : "=&r" (__result) : "r" (mem), "r" (newval), "r" (oldval) \
82         : "r0", "r1", "t", "memory"); \
83      __result; })
84
85 #define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \
86   ({ __typeof (*(mem)) __result; \
87      __asm__ __volatile__ ("\
88         .align 2\n\
89         mova 1f,r0\n\
90         nop\n\
91         mov r15,r1\n\
92         mov #-8,r15\n\
93      0: mov.w @%1,%0\n\
94         cmp/eq %0,%3\n\
95         bf 1f\n\
96         mov.w %2,@%1\n\
97      1: mov r1,r15"\
98         : "=&r" (__result) : "r" (mem), "r" (newval), "r" (oldval) \
99         : "r0", "r1", "t", "memory"); \
100      __result; })
101
102 #define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \
103   ({ __typeof (*(mem)) __result; \
104      __asm__ __volatile__ ("\
105         .align 2\n\
106         mova 1f,r0\n\
107         nop\n\
108         mov r15,r1\n\
109         mov #-8,r15\n\
110      0: mov.l @%1,%0\n\
111         cmp/eq %0,%3\n\
112         bf 1f\n\
113         mov.l %2,@%1\n\
114      1: mov r1,r15"\
115         : "=&r" (__result) : "r" (mem), "r" (newval), "r" (oldval) \
116         : "r0", "r1", "t", "memory"); \
117      __result; })
118
119 /* XXX We do not really need 64-bit compare-and-exchange.  At least
120    not in the moment.  Using it would mean causing portability
121    problems since not many other 32-bit architectures have support for
122    such an operation.  So don't define any code for now.  */
123
124 # define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
125   (abort (), (__typeof (*mem)) 0)
126
127 #define atomic_exchange_and_add(mem, value) \
128   ({ __typeof (*(mem)) __result, __tmp, __value = (value); \
129      if (sizeof (*(mem)) == 1) \
130        __asm__ __volatile__ ("\
131           .align 2\n\
132           mova 1f,r0\n\
133           mov r15,r1\n\
134           mov #-6,r15\n\
135        0: mov.b @%2,%0\n\
136           add %0,%1\n\
137           mov.b %1,@%2\n\
138        1: mov r1,r15"\
139         : "=&r" (__result), "=&r" (__tmp) : "r" (mem), "1" (__value) \
140         : "r0", "r1", "memory"); \
141      else if (sizeof (*(mem)) == 2) \
142        __asm__ __volatile__ ("\
143           .align 2\n\
144           mova 1f,r0\n\
145           mov r15,r1\n\
146           mov #-6,r15\n\
147        0: mov.w @%2,%0\n\
148           add %0,%1\n\
149           mov.w %1,@%2\n\
150        1: mov r1,r15"\
151         : "=&r" (__result), "=&r" (__tmp) : "r" (mem), "1" (__value) \
152         : "r0", "r1", "memory"); \
153      else if (sizeof (*(mem)) == 4) \
154        __asm__ __volatile__ ("\
155           .align 2\n\
156           mova 1f,r0\n\
157           mov r15,r1\n\
158           mov #-6,r15\n\
159        0: mov.l @%2,%0\n\
160           add %0,%1\n\
161           mov.l %1,@%2\n\
162        1: mov r1,r15"\
163         : "=&r" (__result), "=&r" (__tmp) : "r" (mem), "1" (__value) \
164         : "r0", "r1", "memory"); \
165      else \
166        { \
167          __typeof (mem) memp = (mem); \
168          do \
169            __result = *memp; \
170          while (__arch_compare_and_exchange_val_64_acq \
171                  (memp, __result + __value, __result) == __result); \
172          (void) __value; \
173        } \
174      __result; })
175
176 #define atomic_add(mem, value) \
177   (void) ({ __typeof (*(mem)) __tmp, __value = (value); \
178             if (sizeof (*(mem)) == 1) \
179               __asm__ __volatile__ ("\
180                 .align 2\n\
181                 mova 1f,r0\n\
182                 mov r15,r1\n\
183                 mov #-6,r15\n\
184              0: mov.b @%1,r2\n\
185                 add r2,%0\n\
186                 mov.b %0,@%1\n\
187              1: mov r1,r15"\
188                 : "=&r" (__tmp) : "r" (mem), "0" (__value) \
189                 : "r0", "r1", "r2", "memory"); \
190             else if (sizeof (*(mem)) == 2) \
191               __asm__ __volatile__ ("\
192                 .align 2\n\
193                 mova 1f,r0\n\
194                 mov r15,r1\n\
195                 mov #-6,r15\n\
196              0: mov.w @%1,r2\n\
197                 add r2,%0\n\
198                 mov.w %0,@%1\n\
199              1: mov r1,r15"\
200                 : "=&r" (__tmp) : "r" (mem), "0" (__value) \
201                 : "r0", "r1", "r2", "memory"); \
202             else if (sizeof (*(mem)) == 4) \
203               __asm__ __volatile__ ("\
204                 .align 2\n\
205                 mova 1f,r0\n\
206                 mov r15,r1\n\
207                 mov #-6,r15\n\
208              0: mov.l @%1,r2\n\
209                 add r2,%0\n\
210                 mov.l %0,@%1\n\
211              1: mov r1,r15"\
212                 : "=&r" (__tmp) : "r" (mem), "0" (__value) \
213                 : "r0", "r1", "r2", "memory"); \
214             else \
215               { \
216                 __typeof (*(mem)) oldval; \
217                 __typeof (mem) memp = (mem); \
218                 do \
219                   oldval = *memp; \
220                 while (__arch_compare_and_exchange_val_64_acq \
221                         (memp, oldval + __value, oldval) == oldval); \
222                 (void) __value; \
223               } \
224             })
225
226 #define atomic_add_negative(mem, value) \
227   ({ unsigned char __result; \
228      __typeof (*(mem)) __tmp, __value = (value); \
229      if (sizeof (*(mem)) == 1) \
230        __asm__ __volatile__ ("\
231           .align 2\n\
232           mova 1f,r0\n\
233           mov r15,r1\n\
234           mov #-6,r15\n\
235        0: mov.b @%2,r2\n\
236           add r2,%1\n\
237           mov.b %1,@%2\n\
238        1: mov r1,r15\n\
239           shal %1\n\
240           movt %0"\
241         : "=r" (__result), "=&r" (__tmp) : "r" (mem), "1" (__value) \
242         : "r0", "r1", "r2", "t", "memory"); \
243      else if (sizeof (*(mem)) == 2) \
244        __asm__ __volatile__ ("\
245           .align 2\n\
246           mova 1f,r0\n\
247           mov r15,r1\n\
248           mov #-6,r15\n\
249        0: mov.w @%2,r2\n\
250           add r2,%1\n\
251           mov.w %1,@%2\n\
252        1: mov r1,r15\n\
253           shal %1\n\
254           movt %0"\
255         : "=r" (__result), "=&r" (__tmp) : "r" (mem), "1" (__value) \
256         : "r0", "r1", "r2", "t", "memory"); \
257      else if (sizeof (*(mem)) == 4) \
258        __asm__ __volatile__ ("\
259           .align 2\n\
260           mova 1f,r0\n\
261           mov r15,r1\n\
262           mov #-6,r15\n\
263        0: mov.l @%2,r2\n\
264           add r2,%1\n\
265           mov.l %1,@%2\n\
266        1: mov r1,r15\n\
267           shal %1\n\
268           movt %0"\
269         : "=r" (__result), "=&r" (__tmp) : "r" (mem), "1" (__value) \
270         : "r0", "r1", "r2", "t", "memory"); \
271      else \
272        abort (); \
273      __result; })
274
275 #define atomic_add_zero(mem, value) \
276   ({ unsigned char __result; \
277      __typeof (*(mem)) __tmp, __value = (value); \
278      if (sizeof (*(mem)) == 1) \
279        __asm__ __volatile__ ("\
280           .align 2\n\
281           mova 1f,r0\n\
282           mov r15,r1\n\
283           mov #-6,r15\n\
284        0: mov.b @%2,r2\n\
285           add r2,%1\n\
286           mov.b %1,@%2\n\
287        1: mov r1,r15\n\
288           tst %1,%1\n\
289           movt %0"\
290         : "=r" (__result), "=&r" (__tmp) : "r" (mem), "1" (__value) \
291         : "r0", "r1", "r2", "t", "memory"); \
292      else if (sizeof (*(mem)) == 2) \
293        __asm__ __volatile__ ("\
294           .align 2\n\
295           mova 1f,r0\n\
296           mov r15,r1\n\
297           mov #-6,r15\n\
298        0: mov.w @%2,r2\n\
299           add r2,%1\n\
300           mov.w %1,@%2\n\
301        1: mov r1,r15\n\
302           tst %1,%1\n\
303           movt %0"\
304         : "=r" (__result), "=&r" (__tmp) : "r" (mem), "1" (__value) \
305         : "r0", "r1", "r2", "t", "memory"); \
306      else if (sizeof (*(mem)) == 4) \
307        __asm__ __volatile__ ("\
308           .align 2\n\
309           mova 1f,r0\n\
310           mov r15,r1\n\
311           mov #-6,r15\n\
312        0: mov.l @%2,r2\n\
313           add r2,%1\n\
314           mov.l %1,@%2\n\
315        1: mov r1,r15\n\
316           tst %1,%1\n\
317           movt %0"\
318         : "=r" (__result), "=&r" (__tmp) : "r" (mem), "1" (__value) \
319         : "r0", "r1", "r2", "t", "memory"); \
320      else \
321        abort (); \
322      __result; })
323
324 #define atomic_increment_and_test(mem) atomic_add_zero((mem), 1)
325 #define atomic_decrement_and_test(mem) atomic_add_zero((mem), -1)
326
327 #define atomic_bit_set(mem, bit) \
328   (void) ({ unsigned int __mask = 1 << (bit); \
329             if (sizeof (*(mem)) == 1) \
330               __asm__ __volatile__ ("\
331                 .align 2\n\
332                 mova 1f,r0\n\
333                 mov r15,r1\n\
334                 mov #-6,r15\n\
335              0: mov.b @%0,r2\n\
336                 or %1,r2\n\
337                 mov.b r2,@%0\n\
338              1: mov r1,r15"\
339                 : : "r" (mem), "r" (__mask) \
340                 : "r0", "r1", "r2", "memory"); \
341             else if (sizeof (*(mem)) == 2) \
342               __asm__ __volatile__ ("\
343                 .align 2\n\
344                 mova 1f,r0\n\
345                 mov r15,r1\n\
346                 mov #-6,r15\n\
347              0: mov.w @%0,r2\n\
348                 or %1,r2\n\
349                 mov.w r2,@%0\n\
350              1: mov r1,r15"\
351                 : : "r" (mem), "r" (__mask) \
352                 : "r0", "r1", "r2", "memory"); \
353             else if (sizeof (*(mem)) == 4) \
354               __asm__ __volatile__ ("\
355                 .align 2\n\
356                 mova 1f,r0\n\
357                 mov r15,r1\n\
358                 mov #-6,r15\n\
359              0: mov.l @%0,r2\n\
360                 or %1,r2\n\
361                 mov.l r2,@%0\n\
362              1: mov r1,r15"\
363                 : : "r" (mem), "r" (__mask) \
364                 : "r0", "r1", "r2", "memory"); \
365             else \
366               abort (); \
367             })
368
369 #define atomic_bit_test_set(mem, bit) \
370   ({ unsigned int __mask = 1 << (bit); \
371      unsigned int __result = __mask; \
372      if (sizeof (*(mem)) == 1) \
373        __asm__ __volatile__ ("\
374           .align 2\n\
375           mova 1f,r0\n\
376           nop\n\
377           mov r15,r1\n\
378           mov #-8,r15\n\
379        0: mov.b @%2,r2\n\
380           or r2,%1\n\
381           and r2,%0\n\
382           mov.b %1,@%2\n\
383        1: mov r1,r15"\
384         : "=&r" (__result), "=&r" (__mask) \
385         : "r" (mem), "0" (__result), "1" (__mask) \
386         : "r0", "r1", "r2", "memory"); \
387      else if (sizeof (*(mem)) == 2) \
388        __asm__ __volatile__ ("\
389           .align 2\n\
390           mova 1f,r0\n\
391           nop\n\
392           mov r15,r1\n\
393           mov #-8,r15\n\
394        0: mov.w @%2,r2\n\
395           or r2,%1\n\
396           and r2,%0\n\
397           mov.w %1,@%2\n\
398        1: mov r1,r15"\
399         : "=&r" (__result), "=&r" (__mask) \
400         : "r" (mem), "0" (__result), "1" (__mask) \
401         : "r0", "r1", "r2", "memory"); \
402      else if (sizeof (*(mem)) == 4) \
403        __asm__ __volatile__ ("\
404           .align 2\n\
405           mova 1f,r0\n\
406           nop\n\
407           mov r15,r1\n\
408           mov #-8,r15\n\
409        0: mov.l @%2,r2\n\
410           or r2,%1\n\
411           and r2,%0\n\
412           mov.l %1,@%2\n\
413        1: mov r1,r15"\
414         : "=&r" (__result), "=&r" (__mask) \
415         : "r" (mem), "0" (__result), "1" (__mask) \
416         : "r0", "r1", "r2", "memory"); \
417      else \
418        abort (); \
419      __result; })