1170431Spjd/*-
2170431Spjd * Copyright (c) 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org>
3170431Spjd * All rights reserved.
4170431Spjd *
5170431Spjd * Redistribution and use in source and binary forms, with or without
6170431Spjd * modification, are permitted provided that the following conditions
7170431Spjd * are met:
8170431Spjd * 1. Redistributions of source code must retain the above copyright
9170431Spjd *    notice, this list of conditions and the following disclaimer.
10170431Spjd * 2. Redistributions in binary form must reproduce the above copyright
11170431Spjd *    notice, this list of conditions and the following disclaimer in the
12170431Spjd *    documentation and/or other materials provided with the distribution.
13170431Spjd *
14170431Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15170431Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16170431Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17170431Spjd * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18170431Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19170431Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20170431Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21170431Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22170431Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23170431Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24170431Spjd * SUCH DAMAGE.
25170431Spjd *
26170431Spjd * $FreeBSD$
27170431Spjd */
28170431Spjd
29170431Spjd#ifndef _OPENSOLARIS_SYS_ATOMIC_H_
30170431Spjd#define	_OPENSOLARIS_SYS_ATOMIC_H_
31170431Spjd
32170431Spjd#include <sys/types.h>
33170431Spjd#include <machine/atomic.h>
34170431Spjd
35179202Sjb#define	casptr(_a, _b, _c)	\
36179202Sjb	atomic_cmpset_ptr((volatile uintptr_t *)(_a), (uintptr_t)(_b), (uintptr_t) (_c))
37179202Sjb#define cas32	atomic_cmpset_32
38179202Sjb
39218007Sjchandra#if !defined(__LP64__) && !defined(__mips_n32)
40170431Spjdextern void atomic_add_64(volatile uint64_t *target, int64_t delta);
41185029Spjdextern void atomic_dec_64(volatile uint64_t *target);
42218007Sjchandra#endif
43170431Spjd#ifndef __sparc64__
44219089Spjdextern uint32_t atomic_cas_32(volatile uint32_t *target, uint32_t cmp,
45219089Spjd    uint32_t newval);
46170431Spjdextern uint64_t atomic_cas_64(volatile uint64_t *target, uint64_t cmp,
47170431Spjd    uint64_t newval);
48170431Spjd#endif
49170431Spjdextern uint64_t atomic_add_64_nv(volatile uint64_t *target, int64_t delta);
50170431Spjdextern uint8_t atomic_or_8_nv(volatile uint8_t *target, uint8_t value);
51170431Spjdextern void membar_producer(void);
52170431Spjd
53183154Simp#if defined(__sparc64__) || defined(__powerpc__) || defined(__arm__) || \
54183154Simp    defined(__mips__)
55170431Spjdextern void atomic_or_8(volatile uint8_t *target, uint8_t value);
56170431Spjd#else
57170431Spjdstatic __inline void
58170431Spjdatomic_or_8(volatile uint8_t *target, uint8_t value)
59170431Spjd{
60170431Spjd	atomic_set_8(target, value);
61170431Spjd}
62170431Spjd#endif
63170431Spjd
64170431Spjdstatic __inline uint32_t
65170431Spjdatomic_add_32_nv(volatile uint32_t *target, int32_t delta)
66170431Spjd{
67170431Spjd	return (atomic_fetchadd_32(target, delta) + delta);
68170431Spjd}
69170431Spjd
70170431Spjdstatic __inline u_int
71170431Spjdatomic_add_int_nv(volatile u_int *target, int delta)
72170431Spjd{
73170431Spjd	return (atomic_add_32_nv(target, delta));
74170431Spjd}
75170431Spjd
76170431Spjdstatic __inline void
77170431Spjdatomic_dec_32(volatile uint32_t *target)
78170431Spjd{
79170431Spjd	atomic_subtract_32(target, 1);
80170431Spjd}
81170431Spjd
82170431Spjdstatic __inline uint32_t
83170431Spjdatomic_dec_32_nv(volatile uint32_t *target)
84170431Spjd{
85170431Spjd	return (atomic_fetchadd_32(target, -1) - 1);
86170431Spjd}
87170431Spjd
88218007Sjchandra#if defined(__LP64__) || defined(__mips_n32)
89170431Spjdstatic __inline void
90185029Spjdatomic_dec_64(volatile uint64_t *target)
91185029Spjd{
92185029Spjd	atomic_subtract_64(target, 1);
93185029Spjd}
94185029Spjd#endif
95185029Spjd
96185029Spjdstatic __inline void
97170431Spjdatomic_inc_32(volatile uint32_t *target)
98170431Spjd{
99170431Spjd	atomic_add_32(target, 1);
100170431Spjd}
101170431Spjd
102170431Spjdstatic __inline uint32_t
103170431Spjdatomic_inc_32_nv(volatile uint32_t *target)
104170431Spjd{
105170431Spjd	return (atomic_add_32_nv(target, 1));
106170431Spjd}
107170431Spjd
108170431Spjdstatic __inline void
109170431Spjdatomic_inc_64(volatile uint64_t *target)
110170431Spjd{
111170431Spjd	atomic_add_64(target, 1);
112170431Spjd}
113170431Spjd
114170431Spjdstatic __inline uint64_t
115170431Spjdatomic_inc_64_nv(volatile uint64_t *target)
116170431Spjd{
117170431Spjd	return (atomic_add_64_nv(target, 1));
118170431Spjd}
119170431Spjd
120219089Spjd#if !defined(COMPAT_32BIT) && defined(__LP64__)
121170431Spjdstatic __inline void *
122170431Spjdatomic_cas_ptr(volatile void *target, void *cmp,  void *newval)
123170431Spjd{
124219089Spjd	return ((void *)atomic_cas_64((volatile uint64_t *)target,
125219089Spjd	    (uint64_t)cmp, (uint64_t)newval));
126170431Spjd}
127219089Spjd#else
128219089Spjdstatic __inline void *
129219089Spjdatomic_cas_ptr(volatile void *target, void *cmp,  void *newval)
130219089Spjd{
131219089Spjd	return ((void *)atomic_cas_32((volatile uint32_t *)target,
132219089Spjd	    (uint32_t)cmp, (uint32_t)newval));
133219089Spjd}
134219089Spjd#endif	/* !defined(COMPAT_32BIT) && defined(__LP64__) */
135170431Spjd
136170431Spjd#endif	/* !_OPENSOLARIS_SYS_ATOMIC_H_ */
137