source: svn/trunk/newcon3bcm2_21bu/toolchain/mips-linux-uclibc/include/bits/atomic.h

Last change on this file was 2, checked in by jglee, 11 years ago

first commit

  • Property svn:executable set to *
File size: 10.4 KB
Line 
1/* Low-level functions for atomic operations. Mips version.
2   Copyright (C) 2005 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#ifndef _MIPS_BITS_ATOMIC_H
21#define _MIPS_BITS_ATOMIC_H 1
22
23#include <inttypes.h>
24#include <sgidefs.h>
25
26typedef int32_t atomic32_t;
27typedef uint32_t uatomic32_t;
28typedef int_fast32_t atomic_fast32_t;
29typedef uint_fast32_t uatomic_fast32_t;
30
31typedef int64_t atomic64_t;
32typedef uint64_t uatomic64_t;
33typedef int_fast64_t atomic_fast64_t;
34typedef uint_fast64_t uatomic_fast64_t;
35
36typedef intptr_t atomicptr_t;
37typedef uintptr_t uatomicptr_t;
38typedef intmax_t atomic_max_t;
39typedef uintmax_t uatomic_max_t;
40
41#if _MIPS_SIM == _ABIO32
42#define MIPS_PUSH_MIPS2 ".set   mips2\n\t"
43#else
44#define MIPS_PUSH_MIPS2
45#endif
46
47/* See the comments in <sys/asm.h> about the use of the sync instruction.  */
48#ifndef MIPS_SYNC
49# define MIPS_SYNC      sync
50#endif
51
52#define MIPS_SYNC_STR_2(X) #X
53#define MIPS_SYNC_STR_1(X) MIPS_SYNC_STR_2(X)
54#define MIPS_SYNC_STR MIPS_SYNC_STR_1(MIPS_SYNC)
55
56/* Compare and exchange.  For all of the "xxx" routines, we expect a
57   "__prev" and a "__cmp" variable to be provided by the enclosing scope,
58   in which values are returned.  */
59
60#define __arch_compare_and_exchange_xxx_8_int(mem, newval, oldval, rel, acq) \
61  (abort (), __prev = __cmp = 0)
62
63#define __arch_compare_and_exchange_xxx_16_int(mem, newval, oldval, rel, acq) \
64  (abort (), __prev = __cmp = 0)
65
66#define __arch_compare_and_exchange_xxx_32_int(mem, newval, oldval, rel, acq) \
67     __asm__ __volatile__ (                                                   \
68     ".set      push\n\t"                                                     \
69     MIPS_PUSH_MIPS2                                                          \
70     rel        "\n"                                                          \
71     "1:\t"                                                                   \
72     "ll        %0,%4\n\t"                                                    \
73     "move      %1,$0\n\t"                                                    \
74     "bne       %0,%2,2f\n\t"                                                 \
75     "move      %1,%3\n\t"                                                    \
76     "sc        %1,%4\n\t"                                                    \
77     "beqz      %1,1b\n"                                                      \
78     acq        "\n\t"                                                        \
79     ".set      pop\n"                                                        \
80     "2:\n\t"                                                                 \
81              : "=&r" (__prev), "=&r" (__cmp)                                 \
82              : "r" (oldval), "r" (newval), "m" (*mem)                        \
83              : "memory")
84
85#if _MIPS_SIM == _ABIO32
86/* We can't do an atomic 64-bit operation in O32.  */
87#define __arch_compare_and_exchange_xxx_64_int(mem, newval, oldval, rel, acq) \
88  (abort (), __prev = __cmp = 0)
89#else
90#define __arch_compare_and_exchange_xxx_64_int(mem, newval, oldval, rel, acq) \
91     __asm__ __volatile__ ("\n"                                               \
92     ".set      push\n\t"                                                     \
93     MIPS_PUSH_MIPS2                                                          \
94     rel        "\n"                                                          \
95     "1:\t"                                                                   \
96     "lld       %0,%4\n\t"                                                    \
97     "move      %1,$0\n\t"                                                    \
98     "bne       %0,%2,2f\n\t"                                                 \
99     "move      %1,%3\n\t"                                                    \
100     "scd       %1,%4\n\t"                                                    \
101     "beqz      %1,1b\n"                                                      \
102     acq        "\n\t"                                                        \
103     ".set      pop\n"                                                        \
104     "2:\n\t"                                                                 \
105              : "=&r" (__prev), "=&r" (__cmp)                                 \
106              : "r" (oldval), "r" (newval), "m" (*mem)                        \
107              : "memory")
108#endif
109
110/* For all "bool" routines, we return FALSE if exchange succesful.  */
111
112#define __arch_compare_and_exchange_bool_8_int(mem, new, old, rel, acq) \
113({ typeof (*mem) __prev; int __cmp;                                     \
114   __arch_compare_and_exchange_xxx_8_int(mem, new, old, rel, acq);      \
115   !__cmp; })
116
117#define __arch_compare_and_exchange_bool_16_int(mem, new, old, rel, acq) \
118({ typeof (*mem) __prev; int __cmp;                                     \
119   __arch_compare_and_exchange_xxx_16_int(mem, new, old, rel, acq);     \
120   !__cmp; })
121
122#define __arch_compare_and_exchange_bool_32_int(mem, new, old, rel, acq) \
123({ typeof (*mem) __prev; int __cmp;                                     \
124   __arch_compare_and_exchange_xxx_32_int(mem, new, old, rel, acq);     \
125   !__cmp; })
126
127#define __arch_compare_and_exchange_bool_64_int(mem, new, old, rel, acq) \
128({ typeof (*mem) __prev; int __cmp;                                     \
129   __arch_compare_and_exchange_xxx_64_int(mem, new, old, rel, acq);     \
130   !__cmp; })
131
132/* For all "val" routines, return the old value whether exchange
133   successful or not.  */
134
135#define __arch_compare_and_exchange_val_8_int(mem, new, old, rel, acq)  \
136({ typeof (*mem) __prev; int __cmp;                                     \
137   __arch_compare_and_exchange_xxx_8_int(mem, new, old, rel, acq);      \
138   (typeof (*mem))__prev; })
139
140#define __arch_compare_and_exchange_val_16_int(mem, new, old, rel, acq) \
141({ typeof (*mem) __prev; int __cmp;                                     \
142   __arch_compare_and_exchange_xxx_16_int(mem, new, old, rel, acq);     \
143   (typeof (*mem))__prev; })
144
145#define __arch_compare_and_exchange_val_32_int(mem, new, old, rel, acq) \
146({ typeof (*mem) __prev; int __cmp;                                     \
147   __arch_compare_and_exchange_xxx_32_int(mem, new, old, rel, acq);     \
148   (typeof (*mem))__prev; })
149
150#define __arch_compare_and_exchange_val_64_int(mem, new, old, rel, acq) \
151({ typeof (*mem) __prev; int __cmp;                                     \
152   __arch_compare_and_exchange_xxx_64_int(mem, new, old, rel, acq);     \
153   (typeof (*mem))__prev; })
154
155/* Compare and exchange with "acquire" semantics, ie barrier after.  */
156
157#define atomic_compare_and_exchange_bool_acq(mem, new, old)     \
158  __atomic_bool_bysize (__arch_compare_and_exchange_bool, int,  \
159                        mem, new, old, "", MIPS_SYNC_STR)
160
161#define atomic_compare_and_exchange_val_acq(mem, new, old)      \
162  __atomic_val_bysize (__arch_compare_and_exchange_val, int,    \
163                       mem, new, old, "", MIPS_SYNC_STR)
164
165/* Compare and exchange with "release" semantics, ie barrier before.  */
166
167#define atomic_compare_and_exchange_bool_rel(mem, new, old)     \
168  __atomic_bool_bysize (__arch_compare_and_exchange_bool, int,  \
169                        mem, new, old, MIPS_SYNC_STR, "")
170
171#define atomic_compare_and_exchange_val_rel(mem, new, old)      \
172  __atomic_val_bysize (__arch_compare_and_exchange_val, int,    \
173                       mem, new, old, MIPS_SYNC_STR, "")
174
175
176
177/* Atomic exchange (without compare).  */
178
179#define __arch_exchange_xxx_8_int(mem, newval, rel, acq) \
180  (abort (), 0)
181
182#define __arch_exchange_xxx_16_int(mem, newval, rel, acq) \
183  (abort (), 0)
184
185#define __arch_exchange_xxx_32_int(mem, newval, rel, acq) \
186({ typeof (*mem) __prev; int __cmp;                                           \
187     __asm__ __volatile__ ("\n"                                               \
188     ".set      push\n\t"                                                     \
189     MIPS_PUSH_MIPS2                                                          \
190     rel        "\n"                                                          \
191     "1:\t"                                                                   \
192     "ll        %0,%3\n\t"                                                    \
193     "move      %1,%2\n\t"                                                    \
194     "sc        %1,%3\n\t"                                                    \
195     "beqz      %1,1b\n"                                                      \
196     acq        "\n\t"                                                        \
197     ".set      pop\n"                                                        \
198     "2:\n\t"                                                                 \
199              : "=&r" (__prev), "=&r" (__cmp)                                 \
200              : "r" (newval), "m" (*mem)                                      \
201              : "memory");                                                    \
202  __prev; })
203
204#if _MIPS_SIM == _ABIO32
205/* We can't do an atomic 64-bit operation in O32.  */
206#define __arch_exchange_xxx_64_int(mem, newval, rel, acq) \
207  (abort (), 0)
208#else
209#define __arch_exchange_xxx_64_int(mem, newval, rel, acq) \
210({ typeof (*mem) __prev; int __cmp;                                           \
211     __asm__ __volatile__ ("\n"                                               \
212     ".set      push\n\t"                                                     \
213     MIPS_PUSH_MIPS2                                                          \
214     rel        "\n"                                                          \
215     "1:\n"                                                                   \
216     "lld       %0,%3\n\t"                                                    \
217     "move      %1,%2\n\t"                                                    \
218     "scd       %1,%3\n\t"                                                    \
219     "beqz      %1,1b\n"                                                      \
220     acq        "\n\t"                                                        \
221     ".set      pop\n"                                                        \
222     "2:\n\t"                                                                 \
223              : "=&r" (__prev), "=&r" (__cmp)                                 \
224              : "r" (newval), "m" (*mem)                                      \
225              : "memory");                                                    \
226  __prev; })
227#endif
228
229#define atomic_exchange_acq(mem, value) \
230  __atomic_val_bysize (__arch_exchange_xxx, int, mem, value, "", MIPS_SYNC_STR)
231
232#define atomic_exchange_rel(mem, value) \
233  __atomic_val_bysize (__arch_exchange_xxx, int, mem, value, MIPS_SYNC_STR, "")
234
235
236/* Atomically add value and return the previous (unincremented) value.  */
237
238#define __arch_exchange_and_add_8_int(mem, newval, rel, acq) \
239  (abort (), (typeof(*mem)) 0)
240
241#define __arch_exchange_and_add_16_int(mem, newval, rel, acq) \
242  (abort (), (typeof(*mem)) 0)
243
244#define __arch_exchange_and_add_32_int(mem, value, rel, acq) \
245({ typeof (*mem) __prev; int __cmp;                                           \
246     __asm__ __volatile__ ("\n"                                               \
247     ".set      push\n\t"                                                     \
248     MIPS_PUSH_MIPS2                                                          \
249     rel        "\n"                                                          \
250     "1:\t"                                                                   \
251     "ll        %0,%3\n\t"                                                    \
252     "addu      %1,%0,%2\n\t"                                                 \
253     "sc        %1,%3\n\t"                                                    \
254     "beqz      %1,1b\n"                                                      \
255     acq        "\n\t"                                                        \
256     ".set      pop\n"                                                        \
257     "2:\n\t"                                                                 \
258              : "=&r" (__prev), "=&r" (__cmp)                                 \
259              : "r" (value), "m" (*mem)                                       \
260              : "memory");                                                    \
261  __prev; })
262
263#if _MIPS_SIM == _ABIO32
264/* We can't do an atomic 64-bit operation in O32.  */
265#define __arch_exchange_and_add_64_int(mem, value, rel, acq) \
266  (abort (), (typeof(*mem)) 0)
267#else
268#define __arch_exchange_and_add_64_int(mem, value, rel, acq) \
269({ typeof (*mem) __prev; int __cmp;                                           \
270     __asm__ __volatile__ (                                                   \
271     ".set      push\n\t"                                                     \
272     MIPS_PUSH_MIPS2                                                          \
273     rel        "\n"                                                          \
274     "1:\t"                                                                   \
275     "lld       %0,%3\n\t"                                                    \
276     "daddu     %1,%0,%2\n\t"                                                 \
277     "scd       %1,%3\n\t"                                                    \
278     "beqz      %1,1b\n"                                                      \
279     acq        "\n\t"                                                        \
280     ".set      pop\n"                                                        \
281     "2:\n\t"                                                                 \
282              : "=&r" (__prev), "=&r" (__cmp)                                 \
283              : "r" (value), "m" (*mem)                                       \
284              : "memory");                                                    \
285  __prev; })
286#endif
287
288/* ??? Barrier semantics for atomic_exchange_and_add appear to be
289   undefined.  Use full barrier for now, as that's safe.  */
290#define atomic_exchange_and_add(mem, value) \
291  __atomic_val_bysize (__arch_exchange_and_add, int, mem, value,              \
292                       MIPS_SYNC_STR, MIPS_SYNC_STR)
293
294/* TODO: More atomic operations could be implemented efficiently; only the
295   basic requirements are done.  */
296
297#define atomic_full_barrier() \
298  __asm__ __volatile__ (".set push\n\t"                                       \
299                        MIPS_PUSH_MIPS2                                       \
300                        MIPS_SYNC_STR "\n\t"                                  \
301                        ".set pop" : : : "memory")
302
303#endif /* bits/atomic.h */
Note: See TracBrowser for help on using the repository browser.