(atomic_decrement_if_positive): Adjust for the correct atomic_compare_and_exchange_ac...
[kopensolaris-gnu/glibc.git] / include / atomic.h
1 /* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
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 _ATOMIC_H
21 #define _ATOMIC_H       1
22
23 #include <stdlib.h>
24
25 #include <bits/atomic.h>
26
27
28 #ifndef atomic_compare_and_exchange_acq
29 # define atomic_compare_and_exchange_acq(mem, newval, oldval) \
30   ({ __typeof (__arch_compare_and_exchange_32_acq (mem, newval, oldval))      \
31          __result;                                                            \
32      if (sizeof (*mem) == 1)                                                  \
33        __result = __arch_compare_and_exchange_8_acq (mem, newval, oldval);    \
34      else if (sizeof (*mem) == 2)                                             \
35        __result = __arch_compare_and_exchange_16_acq (mem, newval, oldval);   \
36      else if (sizeof (*mem) == 4)                                             \
37        __result = __arch_compare_and_exchange_32_acq (mem, newval, oldval);   \
38      else if (sizeof (*mem) == 8)                                             \
39        __result = __arch_compare_and_exchange_64_acq (mem, newval, oldval);   \
40      else                                                                     \
41        abort ();                                                              \
42      __result; })
43 #endif
44
45
46 #ifndef atomic_compare_and_exchange_rel
47 # define atomic_compare_and_exchange_rel(mem, oldval, newval) \
48   atomic_compare_and_exchange_acq (mem, oldval, newval)
49 #endif
50
51
52 /* Store NEWVALUE in *MEM and return the old value.  */
53 #ifndef atomic_exchange
54 # define atomic_exchange(mem, newvalue) \
55   ({ __typeof (*mem) __oldval;                                                \
56      __typeof (mem) __memp = (mem);                                           \
57      __typeof (*mem) __value = (newvalue);                                    \
58                                                                               \
59      do                                                                       \
60        __oldval = (*__memp);                                                  \
61      while (__builtin_expect (atomic_compare_and_exchange_acq (__memp,        \
62                                                                __value,       \
63                                                                __oldval), 0));\
64                                                                               \
65      __oldval; })
66 #endif
67
68
69 /* Add VALUE to *MEM and return the old value of *MEM.  */
70 #ifndef atomic_exchange_and_add
71 # define atomic_exchange_and_add(mem, value) \
72   ({ __typeof (*mem) __oldval;                                                \
73      __typeof (mem) __memp = (mem);                                           \
74      __typeof (*mem) __value = (value);                                       \
75                                                                               \
76      do                                                                       \
77        __oldval = (*__memp);                                                  \
78      while (__builtin_expect (atomic_compare_and_exchange_acq (__memp,        \
79                                                                __oldval       \
80                                                                + __value,     \
81                                                                __oldval), 0));\
82                                                                               \
83      __oldval; })
84 #endif
85
86
87 #ifndef atomic_add
88 # define atomic_add(mem, value) (void) atomic_exchange_and_add (mem, value)
89 #endif
90
91
92 #ifndef atomic_increment
93 # define atomic_increment(mem) atomic_add (mem, 1)
94 #endif
95
96
97 #ifndef atomic_increment_and_test
98 # define atomic_increment_and_test(mem) \
99   (atomic_exchange_and_add (mem, 1) == 0)
100 #endif
101
102
103 #ifndef atomic_decrement
104 # define atomic_decrement(mem) atomic_add (mem, -1)
105 #endif
106
107
108 #ifndef atomic_decrement_and_test
109 # define atomic_decrement_and_test(mem) \
110   (atomic_exchange_and_add (mem, -1) == 0)
111 #endif
112
113
114 /* Decrement *MEM if it is > 0, and return the old value.  */
115 #ifndef atomic_decrement_if_positive
116 # define atomic_decrement_if_positive(mem) \
117   ({ __typeof (*mem) __oldval;                                                \
118      __typeof (mem) __memp;                                                   \
119                                                                               \
120      __val = *__memp;                                                         \
121      do                                                                       \
122        {                                                                      \
123          __oldval = *__memp;                                                  \
124          if (__builtin_expect (__oldval <= 0, 0))                             \
125            break;                                                             \
126        }                                                                      \
127      while (__builtin_expect (atomic_compare_and_exchange_acq (__memp,        \
128                                                                __oldval - 1,  \
129                                                                __oldval), 0));\
130      __oldval; })
131 #endif
132
133
134 #ifndef atomic_add_negative
135 # define atomic_add_negative(mem, value) \
136   (atomic_exchange_and_add (mem, value) < 0)
137 #endif
138
139
140 #ifndef atomic_add_zero
141 # define atomic_add_zero(mem, value) \
142   (atomic_exchange_and_add (mem, value) == 0)
143 #endif
144
145
146 #ifndef atomic_bit_set
147 # define atomic_bit_set(mem, bit) \
148   (void) atomic_bit_test_set(mem, bit)
149 #endif
150
151
152 #ifndef atomic_bit_test_set
153 # define atomic_bit_test_set(mem, bit) \
154   ({ __typeof (*mem) __oldval;                                                \
155      __typeof (mem) __memp = (mem);                                           \
156      __typeof (*mem) __mask = (1 << (bit));                                   \
157                                                                               \
158      do                                                                       \
159        __oldval = (*__memp);                                                  \
160      while (__builtin_expect (atomic_compare_and_exchange_acq (__memp,        \
161                                                                __oldval       \
162                                                                | __mask,      \
163                                                                __oldval), 0));\
164                                                                               \
165      __oldval & __mask; })
166 #endif
167
168
169 #ifndef atomic_full_barrier
170 # define atomic_full_barrier() __asm ("" ::: "memory")
171 #endif
172
173
174 #ifndef atomic_read_barrier
175 # define atomic_read_barrier() atomic_full_barrier()
176 #endif
177
178
179 #ifndef atomic_write_barrier
180 # define atomic_write_barrier() atomic_full_barrier()
181 #endif
182
183 #endif  /* atomic.h */