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