1 /* $NetBSD: atomic.h,v 1.7 2014/12/10 04:38:00 christos Exp $ */
2
3 /*
4 * Copyright (C) 2005, 2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 /* Id */
20
21 #ifndef ISC_ATOMIC_H
22 #define ISC_ATOMIC_H 1
23
24 #include <isc/platform.h>
25 #include <isc/types.h>
26
27 /*!\file
28 * static inline isc_int32_t
29 * isc_atomic_xadd(isc_int32_t *p, isc_int32_t val);
30 *
31 * This routine atomically increments the value stored in 'p' by 'val', and
32 * returns the previous value.
33 *
34 * static inline void
35 * isc_atomic_store(void *p, isc_int32_t val);
36 *
37 * This routine atomically stores the value 'val' in 'p'.
38 *
39 * static inline isc_int32_t
40 * isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val);
41 *
42 * This routine atomically replaces the value in 'p' with 'val', if the
43 * original value is equal to 'cmpval'. The original value is returned in any
44 * case.
45 */
46
47 #if defined(_AIX)
48
49 #include <sys/atomic_op.h>
50
51 #define isc_atomic_store(p, v) _clear_lock(p, v)
52
53 #ifdef __GNUC__
54 static __inline isc_int32_t
55 #else
56 static isc_int32_t
57 #endif
isc_atomic_xadd(isc_int32_t * p,isc_int32_t val)58 isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
59 int ret;
60
61 #ifdef __GNUC__
62 asm("ics");
63 #else
64 __isync();
65 #endif
66
67 ret = fetch_and_add((atomic_p)p, (int)val);
68
69 #ifdef __GNUC__
70 asm("ics");
71 #else
72 __isync();
73 #endif
74
75 return (ret);
76 }
77
78 #ifdef __GNUC__
79 static __inline int
80 #else
81 static int
82 #endif
isc_atomic_cmpxchg(atomic_p p,int old,int new)83 isc_atomic_cmpxchg(atomic_p p, int old, int new) {
84 int orig = old;
85
86 #ifdef __GNUC__
87 asm("ics");
88 #else
89 __isync();
90 #endif
91 if (compare_and_swap(p, &orig, new))
92 orig = old;
93
94 #ifdef __GNUC__
95 asm("ics");
96 #else
97 __isync();
98 #endif
99
100 return (orig);
101 }
102
103 #elif defined(ISC_PLATFORM_USEGCCASM) || defined(ISC_PLATFORM_USEMACASM)
104 static __inline isc_int32_t
isc_atomic_xadd(isc_int32_t * p,isc_int32_t val)105 isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
106 isc_int32_t orig;
107
108 __asm__ volatile (
109 #ifdef ISC_PLATFORM_USEMACASM
110 "1:"
111 "lwarx r6, 0, %1\n"
112 "mr %0, r6\n"
113 "add r6, r6, %2\n"
114 "stwcx. r6, 0, %1\n"
115 "bne- 1b\n"
116 "sync"
117 #else
118 "1:"
119 "lwarx 6, 0, %1\n"
120 "mr %0, 6\n"
121 "add 6, 6, %2\n"
122 "stwcx. 6, 0, %1\n"
123 "bne- 1b\n"
124 "sync"
125 #endif
126 : "=&r"(orig)
127 : "r"(p), "r"(val)
128 : "r6", "memory"
129 );
130
131 return (orig);
132 }
133
134 static __inline void
isc_atomic_store(void * p,isc_int32_t val)135 isc_atomic_store(void *p, isc_int32_t val) {
136 __asm__ volatile (
137 #ifdef ISC_PLATFORM_USEMACASM
138 "1:"
139 "lwarx r6, 0, %0\n"
140 "lwz r6, %1\n"
141 "stwcx. r6, 0, %0\n"
142 "bne- 1b\n"
143 "sync"
144 #else
145 "1:"
146 "lwarx 6, 0, %0\n"
147 "lwz 6, %1\n"
148 "stwcx. 6, 0, %0\n"
149 "bne- 1b\n"
150 "sync"
151 #endif
152 :
153 : "r"(p), "m"(val)
154 : "r6", "memory"
155 );
156 }
157
158 static __inline isc_int32_t
isc_atomic_cmpxchg(isc_int32_t * p,isc_int32_t cmpval,isc_int32_t val)159 isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
160 isc_int32_t orig;
161
162 __asm__ volatile (
163 #ifdef ISC_PLATFORM_USEMACASM
164 "1:"
165 "lwarx r6, 0, %1\n"
166 "mr %0,r6\n"
167 "cmpw r6, %2\n"
168 "bne 2f\n"
169 "mr r6, %3\n"
170 "stwcx. r6, 0, %1\n"
171 "bne- 1b\n"
172 "2:\n"
173 "sync"
174 #else
175 "1:"
176 "lwarx 6, 0, %1\n"
177 "mr %0,6\n"
178 "cmpw 6, %2\n"
179 "bne 2f\n"
180 "mr 6, %3\n"
181 "stwcx. 6, 0, %1\n"
182 "bne- 1b\n"
183 "2:\n"
184 "sync"
185 #endif
186 : "=&r" (orig)
187 : "r"(p), "r"(cmpval), "r"(val)
188 : "r6", "memory"
189 );
190
191 return (orig);
192 }
193
194 #else
195
196 #error "unsupported compiler. disable atomic ops by --disable-atomic"
197
198 #endif
199 #endif /* ISC_ATOMIC_H */
200