atomic.h revision 6a9ca708361200b105f7a016216808e6058d17cb
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
* Copyright 2015 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
*/
#ifndef _ASM_ATOMIC_H
#define _ASM_ATOMIC_H
#include <sys/ccompile.h>
#ifdef __cplusplus
extern "C" {
#endif
/* BEGIN CSTYLED */
/*
* This file contains a number of static inline functions implementing
* various atomic variable functions. Note that these are *not* all of the
* pure assembly. In the absence of an identically named function in this
* header file, any use of the function will result in the compiler emitting
* a function call as usual. On the other hand, if an identically named
* function exists in this header as a static inline, the compiler will
* inline its contents and the linker never sees the symbol reference. We
* use this to avoid implementing some of the more complex and less used
* functions and instead falling back to function calls. Note that in some
* cases (e.g., atomic_inc_64) we implement a static inline only on AMD64
* but not i386.
*/
/*
* Instruction suffixes for various operand sizes (assuming AMD64)
*/
#define SUF_8 "b"
#define SUF_16 "w"
#define SUF_32 "l"
#define SUF_64 "q"
#if defined(__amd64)
#define __ATOMIC_OP64(...)
#else
#error "port me"
#endif
extern __GNU_INLINE void \
{ \
: "+m" (*target) \
: /* no inputs */ \
: "cc"); \
}
extern __GNU_INLINE void \
{ \
: "+m" (*target) \
: "cc"); \
}
/*
* We don't use the above macro here because atomic_add_ptr has an
* inconsistent type. The first argument should really be a 'volatile void
* **'.
*/
extern __GNU_INLINE void
{
: "+m" (*tmp)
: "ir" (delta)
: "cc");
}
extern __GNU_INLINE type \
{ \
: "cc"); \
return (ret); \
}
/*
* We don't use the above macro here because atomic_cas_ptr has an
* inconsistent type. The first argument should really be a 'volatile void
* **'.
*/
extern __GNU_INLINE void *
{
void *ret;
: "cc");
return (ret);
}
extern __GNU_INLINE type \
{ \
op " %1,%0" \
return (val); \
}
/*
* We don't use the above macro here because atomic_swap_ptr has an
* inconsistent type. The first argument should really be a 'volatile void
* **'.
*/
extern __GNU_INLINE void *
{
return (val);
}
#else
#error "port me"
#endif
/* END CSTYLED */
#endif /* !__lint && __GNUC__ */
#ifdef __cplusplus
}
#endif
#endif /* _ASM_ATOMIC_H */