1258945Sroberto/*
2258945Sroberto * Copyright (C) 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
3258945Sroberto *
4258945Sroberto * Permission to use, copy, modify, and/or distribute this software for any
5258945Sroberto * purpose with or without fee is hereby granted, provided that the above
6258945Sroberto * copyright notice and this permission notice appear in all copies.
7258945Sroberto *
8258945Sroberto * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9258945Sroberto * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10258945Sroberto * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11258945Sroberto * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12258945Sroberto * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13258945Sroberto * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14258945Sroberto * PERFORMANCE OF THIS SOFTWARE.
15258945Sroberto */
16258945Sroberto
17258945Sroberto/* $Id: atomic.h,v 1.5 2007/06/19 23:47:18 tbox Exp $ */
18258945Sroberto
19258945Sroberto/*
20258945Sroberto * This code was written based on FreeBSD's kernel source whose copyright
21258945Sroberto * follows:
22258945Sroberto */
23258945Sroberto
24258945Sroberto/*-
25258945Sroberto * Copyright (c) 1998 Doug Rabson.
26258945Sroberto * Copyright (c) 2001 Jake Burkholder.
27258945Sroberto * All rights reserved.
28258945Sroberto *
29258945Sroberto * Redistribution and use in source and binary forms, with or without
30258945Sroberto * modification, are permitted provided that the following conditions
31258945Sroberto * are met:
32258945Sroberto * 1. Redistributions of source code must retain the above copyright
33258945Sroberto *    notice, this list of conditions and the following disclaimer.
34258945Sroberto * 2. Redistributions in binary form must reproduce the above copyright
35258945Sroberto *    notice, this list of conditions and the following disclaimer in the
36258945Sroberto *    documentation and/or other materials provided with the distribution.
37258945Sroberto *
38258945Sroberto * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
39258945Sroberto * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40258945Sroberto * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41258945Sroberto * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
42258945Sroberto * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
43258945Sroberto * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
44258945Sroberto * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45258945Sroberto * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46258945Sroberto * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
47258945Sroberto * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48258945Sroberto * SUCH DAMAGE.
49258945Sroberto *
50258945Sroberto *	from: FreeBSD: src/sys/i386/include/atomic.h,v 1.20 2001/02/11
51280849Scy * $FreeBSD:  258945 2013-12-04 21:33:17Z roberto $
52258945Sroberto */
53258945Sroberto
54258945Sroberto#ifndef ISC_ATOMIC_H
55258945Sroberto#define ISC_ATOMIC_H 1
56258945Sroberto
57258945Sroberto#include <isc/platform.h>
58258945Sroberto#include <isc/types.h>
59258945Sroberto
60258945Sroberto#define	ASI_P	0x80		/* Primary Address Space Identifier */
61258945Sroberto
62258945Sroberto#ifdef ISC_PLATFORM_USEGCCASM
63258945Sroberto
64258945Sroberto/*
65258945Sroberto * This routine atomically increments the value stored in 'p' by 'val', and
66258945Sroberto * returns the previous value.
67258945Sroberto */
68258945Srobertostatic inline isc_int32_t
69258945Srobertoisc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
70258945Sroberto	isc_int32_t prev, swapped;
71258945Sroberto
72258945Sroberto	for (prev = *(volatile isc_int32_t *)p; ; prev = swapped) {
73258945Sroberto		swapped = prev + val;
74258945Sroberto		__asm__ volatile(
75258945Sroberto			"casa [%1] %2, %3, %0"
76258945Sroberto			: "+r"(swapped)
77258945Sroberto			: "r"(p), "n"(ASI_P), "r"(prev));
78258945Sroberto		if (swapped == prev)
79258945Sroberto			break;
80258945Sroberto	}
81258945Sroberto
82258945Sroberto	return (prev);
83258945Sroberto}
84258945Sroberto
85258945Sroberto/*
86258945Sroberto * This routine atomically stores the value 'val' in 'p'.
87258945Sroberto */
88258945Srobertostatic inline void
89258945Srobertoisc_atomic_store(isc_int32_t *p, isc_int32_t val) {
90258945Sroberto	isc_int32_t prev, swapped;
91258945Sroberto
92258945Sroberto	for (prev = *(volatile isc_int32_t *)p; ; prev = swapped) {
93258945Sroberto		swapped = val;
94258945Sroberto		__asm__ volatile(
95258945Sroberto			"casa [%1] %2, %3, %0"
96258945Sroberto			: "+r"(swapped)
97258945Sroberto			: "r"(p), "n"(ASI_P), "r"(prev)
98258945Sroberto			: "memory");
99258945Sroberto		if (swapped == prev)
100258945Sroberto			break;
101258945Sroberto	}
102258945Sroberto}
103258945Sroberto
104258945Sroberto/*
105258945Sroberto * This routine atomically replaces the value in 'p' with 'val', if the
106258945Sroberto * original value is equal to 'cmpval'.  The original value is returned in any
107258945Sroberto * case.
108258945Sroberto */
109258945Srobertostatic inline isc_int32_t
110258945Srobertoisc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
111258945Sroberto	isc_int32_t temp = val;
112258945Sroberto
113258945Sroberto	__asm__ volatile(
114258945Sroberto		"casa [%1] %2, %3, %0"
115258945Sroberto		: "+r"(temp)
116258945Sroberto		: "r"(p), "n"(ASI_P), "r"(cmpval));
117258945Sroberto
118258945Sroberto	return (temp);
119258945Sroberto}
120258945Sroberto
121258945Sroberto#else  /* ISC_PLATFORM_USEGCCASM */
122258945Sroberto
123258945Sroberto#error "unsupported compiler.  disable atomic ops by --disable-atomic"
124258945Sroberto
125258945Sroberto#endif /* ISC_PLATFORM_USEGCCASM */
126258945Sroberto
127258945Sroberto#endif /* ISC_ATOMIC_H */
128