1/*
2 * Copyright (C) 2005, 2007  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: atomic.h,v 1.6 2007/06/18 23:47:47 tbox Exp $ */
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_xadd(p, v) fetch_and_add(p, v)
50#define isc_atomic_store(p, v) _clear_lock(p, v)
51
52#ifdef __GNUC__
53static inline int
54#else
55static int
56#endif
57isc_atomic_cmpxchg(atomic_p p, int old, int new) {
58        int orig = old;
59
60#ifdef __GNUC__
61        asm("ics");
62#else
63         __isync();
64#endif
65        if (compare_and_swap(p, &orig, new))
66		return (old);
67        return (orig);
68}
69
70#elif defined(ISC_PLATFORM_USEGCCASM) || defined(ISC_PLATFORM_USEMACASM)
71static inline isc_int32_t
72isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
73	isc_int32_t orig;
74
75	__asm__ volatile (
76#ifdef ISC_PLATFORM_USEMACASM
77		"1:"
78		"lwarx r6, 0, %1\n"
79	    	"mr %0, r6\n"
80		"add r6, r6, %2\n"
81		"stwcx. r6, 0, %1\n"
82		"bne- 1b"
83#else
84		"1:"
85		"lwarx 6, 0, %1\n"
86	    	"mr %0, 6\n"
87		"add 6, 6, %2\n"
88		"stwcx. 6, 0, %1\n"
89		"bne- 1b"
90#endif
91		: "=&r"(orig)
92		: "r"(p), "r"(val)
93		: "r6", "memory"
94		);
95
96	return (orig);
97}
98
99static inline void
100isc_atomic_store(void *p, isc_int32_t val) {
101	__asm__ volatile (
102#ifdef ISC_PLATFORM_USEMACASM
103		"1:"
104		"lwarx r6, 0, %0\n"
105		"lwz r6, %1\n"
106		"stwcx. r6, 0, %0\n"
107		"bne- 1b"
108#else
109		"1:"
110		"lwarx 6, 0, %0\n"
111		"lwz 6, %1\n"
112		"stwcx. 6, 0, %0\n"
113		"bne- 1b"
114#endif
115		:
116		: "r"(p), "m"(val)
117		: "r6", "memory"
118		);
119}
120
121static inline isc_int32_t
122isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
123	isc_int32_t orig;
124
125	__asm__ volatile (
126#ifdef ISC_PLATFORM_USEMACASM
127		"1:"
128		"lwarx r6, 0, %1\n"
129		"mr %0,r6\n"
130		"cmpw r6, %2\n"
131		"bne 2f\n"
132		"mr r6, %3\n"
133		"stwcx. r6, 0, %1\n"
134		"bne- 1b\n"
135		"2:"
136#else
137		"1:"
138		"lwarx 6, 0, %1\n"
139		"mr %0,6\n"
140		"cmpw 6, %2\n"
141		"bne 2f\n"
142		"mr 6, %3\n"
143		"stwcx. 6, 0, %1\n"
144		"bne- 1b\n"
145		"2:"
146#endif
147		: "=&r" (orig)
148		: "r"(p), "r"(cmpval), "r"(val)
149		: "r6", "memory"
150		);
151
152	return (orig);
153}
154
155#else
156
157#error "unsupported compiler.  disable atomic ops by --disable-atomic"
158
159#endif
160#endif /* ISC_ATOMIC_H */
161