]> git.saurik.com Git - apple/libc.git/blobdiff - arm/sys/OSAtomic.h
Libc-825.24.tar.gz
[apple/libc.git] / arm / sys / OSAtomic.h
diff --git a/arm/sys/OSAtomic.h b/arm/sys/OSAtomic.h
new file mode 100644 (file)
index 0000000..7745403
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef __ARM_OSATOMIC_SHIMS__
+#define __ARM_OSATOMIC_SHIMS__
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#define fastpath(x)    ((typeof(x))__builtin_expect((long)(x), ~0l))
+#define slowpath(x)    ((typeof(x))__builtin_expect((long)(x), 0l))
+
+#if defined(__arm__)
+#include <arm/arch.h>
+
+#define _osatomic_load_exclusive(p, r) \
+       __asm__ __volatile__( \
+       "ldrex  %[_r], %[_p]" \
+       : [_r] "=&r" (r) \
+       : [_p] "m" (*(p)) : "memory")
+
+#define _osatomic_load_exclusive64(p, r) \
+       do { \
+               register uint32_t rl asm("r4"), rh asm("r5"); \
+               __asm__ __volatile__( \
+                       "ldrexd %[_rl], %[_rh], %[_p]" \
+                       : [_rl] "=r" (rl), [_rh] "=r" (rh) \
+                       : [_p] "m" (*(p)) : "memory"); \
+               r = (typeof(r))(((uint64_t)rh << 32) | (uint64_t)rl); \
+       } while (0);
+
+#define _osatomic_store_exclusive(p, r, t) \
+       __asm__ __volatile__( \
+       "strex  %[_t], %[_r], %[_p]" \
+       : [_t] "=&r" (t) \
+       : [_p] "m" (*(p)), [_r] "r" (r) : "memory")
+
+#define _osatomic_store_exclusive64(p, r, t) \
+       do { \
+               register uint32_t rl asm("r4"), rh asm("r5"); \
+               rh = (uint32_t)(r >> 32); \
+               rl = (uint32_t)(r); \
+               __asm__ __volatile__( \
+                       "strexd %[_t], %[_rl], %[_rh], %[_p]" \
+                       : [_t] "=&r" (t) \
+                       : [_p] "m" (*(p)), [_rl] "r" (rl), [_rh] "r" (rh) : "memory"); \
+       } while (0);
+
+#if defined(_ARM_ARCH_7)
+
+#ifdef _OSATOMIC_WFE
+#      define MP_SPIN_TRIES            10
+#      define _osatomic_pause()        __asm__ __volatile__("wfe")
+#else
+#      define MP_SPIN_TRIES            1000
+#      define _osatomic_pause()        __asm__ __volatile__("yield")
+#endif // _OSATOMIC_WFE
+
+#define _osatomic_barrier() \
+       __asm__ __volatile__( \
+       "dmb    ish" \
+       : : : "memory")
+
+#define _osatomic_store_barrier() \
+       __asm__ __volatile__( \
+       "dmb    ishst" \
+       : : : "memory")
+
+#elif defined(_ARM_ARCH_6) && !defined(__thumb__) // _ARM_ARCH_7
+
+#define _osatomic_barrier() \
+       __asm__ __volatile__( \
+       "mcr    p15, 0, %0, c7, c10, 5" \
+       : : "r" (0) : "memory")
+
+#define _osatomic_store_barrier() _osatomic_barrier()
+#define _osatomic_pause()
+
+#elif defined(_ARM_ARCH_6) && defined(__thumb__)
+#error Atomic operations not available on ARMv6 Thumb
+#endif // _ARM_ARCH_7
+
+#if !defined(_ARM_ARCH_7)
+#      ifndef _OSATOMIC_NO_BARRIERS
+#              define __OSATOMIC_SUFFIX        ""
+#              define __OSATOMIC_BARRIER       "Barrier"
+#              define _OSATOMIC_ALIAS_NB(x)
+#      else
+#              define _OSATOMIC_EXTRAS                 1
+#              define __OSATOMIC_SUFFIX        ""
+#              define __OSATOMIC_BARRIER       ""
+#              define _OSATOMIC_ALIAS_NB(x)
+#      endif // _OSATOMIC_NO_BARRIERS
+#else
+#      define _OSATOMIC_EXTRAS                 1
+#      ifndef _OSATOMIC_NO_BARRIERS
+#              ifdef _OSATOMIC_WFE
+#                      define __OSATOMIC_SUFFIX "$VARIANT$wfe"
+#              else
+#                      define __OSATOMIC_SUFFIX "$VARIANT$mp"
+#              endif // _OSATOMIC_ONLY_WFE
+#              define __OSATOMIC_BARRIER "Barrier" __OSATOMIC_SUFFIX
+#              define _OSATOMIC_ALIAS_NB(x)
+#      else
+#              define __OSATOMIC_SUFFIX "$VARIANT$up"
+#              define __OSATOMIC_BARRIER "Barrier" __OSATOMIC_SUFFIX
+// Undefine the barrier operations
+#              undef _osatomic_barrier
+#              define _osatomic_barrier()
+#              undef _osatomic_store_barrier
+#              define _osatomic_store_barrier()
+// Aliases to alias non-barrier operations to UP variant names
+#              if defined(__thumb__)
+#                      define _OSATOMIC_ALIAS_NB(sym)  __asm __volatile__(".globl _" __STRING(sym) "; .thumb_func _" __STRING(sym) " ; .set _" __STRING(sym) ", _" __STRING(sym) __OSATOMIC_BARRIER)
+#              else
+#                      define _OSATOMIC_ALIAS_NB(sym)  __asm __volatile__(".globl _" __STRING(sym) "; .set _" __STRING(sym) ", _" __STRING(sym) __OSATOMIC_BARRIER)
+#              endif // __thumb__
+#      endif // _OSATOMIC_NO_BARRIERS
+#endif // !_ARM_ARCH_7
+
+// Allow us to mark up functions as being uni/multiprocessor.
+#define _OSATOMIC_VARIANT(sym) __asm("_" __STRING(sym) __OSATOMIC_SUFFIX)
+#define _OSATOMIC_VARIANT_B(sym)       __asm("_" __STRING(sym) __OSATOMIC_BARRIER)
+
+#if defined(__thumb__)
+       // For aliasing CompareAndSwap operations of the same size
+       #define _OSATOMIC_ALIAS_B(newsym, sym)  \
+               __asm __volatile__( \
+                       ".globl _" __STRING(newsym) __OSATOMIC_BARRIER ";" \
+                       ".thumb_func _" __STRING(newsym) __OSATOMIC_BARRIER ";" \
+                       ".set _" __STRING(newsym) __OSATOMIC_BARRIER ", _" __STRING(sym) __OSATOMIC_BARRIER \
+               )
+
+       #define _OSATOMIC_ALIAS(newsym, sym)    \
+               __asm __volatile__( \
+                       ".globl _" __STRING(newsym) __OSATOMIC_SUFFIX ";" \
+                       ".thumb_func _" __STRING(newsym) __OSATOMIC_SUFFIX ";" \
+                       ".set _" __STRING(newsym) __OSATOMIC_SUFFIX ", _" __STRING(sym) __OSATOMIC_SUFFIX \
+               )
+#else
+       // For aliasing CompareAndSwap operations of the same size
+       #define _OSATOMIC_ALIAS_B(newsym, sym)  \
+               __asm __volatile__( \
+                       ".globl _" __STRING(newsym) __OSATOMIC_BARRIER ";" \
+                       ".set _" __STRING(newsym) __OSATOMIC_BARRIER ", _" __STRING(sym) __OSATOMIC_BARRIER \
+               )
+
+       #define _OSATOMIC_ALIAS(newsym, sym)    \
+               __asm __volatile__( \
+                       ".globl _" __STRING(newsym) __OSATOMIC_SUFFIX ";" \
+                       ".set _" __STRING(newsym) __OSATOMIC_SUFFIX ", _" __STRING(sym) __OSATOMIC_SUFFIX \
+               )
+#endif // __thumb__
+
+#endif // __arm__
+
+#endif // __ARM_OSATOMIC_SHIMS__