Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -151,16 +151,15 @@ OFThreadPool.m SRCS_WINDOWS = OFWin32ConsoleStdIOStream.m \ OFWindowsRegistryKey.m INCLUDES_ATOMIC = OFAtomic.h \ - OFAtomic_builtins.h \ - OFAtomic_no_threads.h \ - OFAtomic_osatomic.h \ - OFAtomic_powerpc.h \ - OFAtomic_sync_builtins.h \ - OFAtomic_x86.h + platform/GCC4/OFAtomic.h \ + platform/GCC4.7/OFAtomic.h \ + platform/PowerPC/OFAtomic.h \ + platform/macOS/OFAtomic.h \ + platform/x86/OFAtomic.h INCLUDES := ${SRCS:.m=.h} \ OFCollection.h \ OFCryptographicHash.h \ OFJSONRepresentation.h \ OFKernelEventObserver.h \ Index: src/OFAtomic.h ================================================================== --- src/OFAtomic.h +++ src/OFAtomic.h @@ -20,20 +20,166 @@ #ifndef OF_HAVE_ATOMIC_OPS # error No atomic operations available! #endif #if !defined(OF_HAVE_THREADS) -# import "OFAtomic_no_threads.h" +static OF_INLINE int +OFAtomicIntAdd(volatile int *_Nonnull p, int i) +{ + return (*p += i); +} + +static OF_INLINE int32_t +OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i) +{ + return (*p += i); +} + +static OF_INLINE void *_Nullable +OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i) +{ + return (*(char *volatile *)p += i); +} + +static OF_INLINE int +OFAtomicIntSubtract(volatile int *_Nonnull p, int i) +{ + return (*p -= i); +} + +static OF_INLINE int32_t +OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i) +{ + return (*p -= i); +} + +static OF_INLINE void *_Nullable +OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i) +{ + return (*(char *volatile *)p -= i); +} + +static OF_INLINE int +OFAtomicIntIncrease(volatile int *_Nonnull p) +{ + return ++*p; +} + +static OF_INLINE int32_t +OFAtomicInt32Increase(volatile int32_t *_Nonnull p) +{ + return ++*p; +} + +static OF_INLINE int +OFAtomicIntDecrease(volatile int *_Nonnull p) +{ + return --*p; +} + +static OF_INLINE int32_t +OFAtomicInt32Decrease(volatile int32_t *_Nonnull p) +{ + return --*p; +} + +static OF_INLINE unsigned int +OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i) +{ + return (*p |= i); +} + +static OF_INLINE uint32_t +OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i) +{ + return (*p |= i); +} + +static OF_INLINE unsigned int +OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i) +{ + return (*p &= i); +} + +static OF_INLINE uint32_t +OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i) +{ + return (*p &= i); +} + +static OF_INLINE unsigned int +OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i) +{ + return (*p ^= i); +} + +static OF_INLINE uint32_t +OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i) +{ + return (*p ^= i); +} + +static OF_INLINE bool +OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n) +{ + if (*p == o) { + *p = n; + return true; + } + + return false; +} + +static OF_INLINE bool +OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n) +{ + if (*p == o) { + *p = n; + return true; + } + + return false; +} + +static OF_INLINE bool +OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p, + void *_Nullable o, void *_Nullable n) +{ + if (*p == o) { + *p = n; + return true; + } + + return false; +} + +static OF_INLINE void +OFMemoryBarrier(void) +{ + /* nop */ +} + +static OF_INLINE void +OFAcquireMemoryBarrier(void) +{ + /* nop */ +} + +static OF_INLINE void +OFReleaseMemoryBarrier(void) +{ + /* nop */ +} #elif (defined(OF_X86_64) || defined(OF_X86)) && defined(__GNUC__) -# import "OFAtomic_x86.h" +# import "platform/x86/OFAtomic.h" #elif defined(OF_POWERPC) && defined(__GNUC__) && !defined(__APPLE_CC__) && \ !defined(OF_AIX) -# import "OFAtomic_powerpc.h" +# import "platform/PowerPC/OFAtomic.h" #elif defined(OF_HAVE_ATOMIC_BUILTINS) -# import "OFAtomic_builtins.h" +# import "platform/GCC4.7/OFAtomic.h" #elif defined(OF_HAVE_SYNC_BUILTINS) -# import "OFAtomic_sync_builtins.h" +# import "platform/GCC4/OFAtomic.h" #elif defined(OF_HAVE_OSATOMIC) -# import "OFAtomic_osatomic.h" +# import "platform/macOS/OFAtomic.h" #else # error No atomic operations available! #endif DELETED src/OFAtomic_builtins.h Index: src/OFAtomic_builtins.h ================================================================== --- src/OFAtomic_builtins.h +++ src/OFAtomic_builtins.h @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -static OF_INLINE int -OFAtomicIntAdd(volatile int *_Nonnull p, int i) -{ - return __atomic_add_fetch(p, i, __ATOMIC_RELAXED); -} - -static OF_INLINE int32_t -OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i) -{ - return __atomic_add_fetch(p, i, __ATOMIC_RELAXED); -} - -static OF_INLINE void *_Nullable -OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i) -{ - return __atomic_add_fetch(p, i, __ATOMIC_RELAXED); -} - -static OF_INLINE int -OFAtomicIntSubtract(volatile int *_Nonnull p, int i) -{ - return __atomic_sub_fetch(p, i, __ATOMIC_RELAXED); -} - -static OF_INLINE int32_t -OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i) -{ - return __atomic_sub_fetch(p, i, __ATOMIC_RELAXED); -} - -static OF_INLINE void *_Nullable -OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i) -{ - return __atomic_sub_fetch(p, i, __ATOMIC_RELAXED); -} - -static OF_INLINE int -OFAtomicIntIncrease(volatile int *_Nonnull p) -{ - return __atomic_add_fetch(p, 1, __ATOMIC_RELAXED); -} - -static OF_INLINE int32_t -OFAtomicInt32Increase(volatile int32_t *_Nonnull p) -{ - return __atomic_add_fetch(p, 1, __ATOMIC_RELAXED); -} - -static OF_INLINE int -OFAtomicIntDecrease(volatile int *_Nonnull p) -{ - return __atomic_sub_fetch(p, 1, __ATOMIC_RELAXED); -} - -static OF_INLINE int32_t -OFAtomicInt32Decrease(volatile int32_t *_Nonnull p) -{ - return __atomic_sub_fetch(p, 1, __ATOMIC_RELAXED); -} - -static OF_INLINE unsigned int -OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i) -{ - return __atomic_or_fetch(p, i, __ATOMIC_RELAXED); -} - -static OF_INLINE uint32_t -OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i) -{ - return __atomic_or_fetch(p, i, __ATOMIC_RELAXED); -} - -static OF_INLINE unsigned int -OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i) -{ - return __atomic_and_fetch(p, i, __ATOMIC_RELAXED); -} - -static OF_INLINE uint32_t -OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i) -{ - return __atomic_and_fetch(p, i, __ATOMIC_RELAXED); -} - -static OF_INLINE unsigned int -OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i) -{ - return __atomic_xor_fetch(p, i, __ATOMIC_RELAXED); -} - -static OF_INLINE uint32_t -OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i) -{ - return __atomic_xor_fetch(p, i, __ATOMIC_RELAXED); -} - -static OF_INLINE bool -OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n) -{ - return __atomic_compare_exchange(p, &o, &n, false, - __ATOMIC_RELAXED, __ATOMIC_RELAXED); -} - -static OF_INLINE bool -OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n) -{ - return __atomic_compare_exchange(p, &o, &n, false, - __ATOMIC_RELAXED, __ATOMIC_RELAXED); -} - -static OF_INLINE bool -OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p, - void *_Nullable o, void *_Nullable n) -{ - return __atomic_compare_exchange(p, &o, &n, false, - __ATOMIC_RELAXED, __ATOMIC_RELAXED); -} - -static OF_INLINE void -OFMemoryBarrier(void) -{ - __atomic_thread_fence(__ATOMIC_SEQ_CST); -} - -static OF_INLINE void -OFAcquireMemoryBarrier(void) -{ - __atomic_thread_fence(__ATOMIC_ACQUIRE); -} - -static OF_INLINE void -OFReleaseMemoryBarrier(void) -{ - __atomic_thread_fence(__ATOMIC_RELEASE); -} DELETED src/OFAtomic_no_threads.h Index: src/OFAtomic_no_threads.h ================================================================== --- src/OFAtomic_no_threads.h +++ src/OFAtomic_no_threads.h @@ -1,162 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -static OF_INLINE int -OFAtomicIntAdd(volatile int *_Nonnull p, int i) -{ - return (*p += i); -} - -static OF_INLINE int32_t -OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i) -{ - return (*p += i); -} - -static OF_INLINE void *_Nullable -OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i) -{ - return (*(char *volatile *)p += i); -} - -static OF_INLINE int -OFAtomicIntSubtract(volatile int *_Nonnull p, int i) -{ - return (*p -= i); -} - -static OF_INLINE int32_t -OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i) -{ - return (*p -= i); -} - -static OF_INLINE void *_Nullable -OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i) -{ - return (*(char *volatile *)p -= i); -} - -static OF_INLINE int -OFAtomicIntIncrease(volatile int *_Nonnull p) -{ - return ++*p; -} - -static OF_INLINE int32_t -OFAtomicInt32Increase(volatile int32_t *_Nonnull p) -{ - return ++*p; -} - -static OF_INLINE int -OFAtomicIntDecrease(volatile int *_Nonnull p) -{ - return --*p; -} - -static OF_INLINE int32_t -OFAtomicInt32Decrease(volatile int32_t *_Nonnull p) -{ - return --*p; -} - -static OF_INLINE unsigned int -OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i) -{ - return (*p |= i); -} - -static OF_INLINE uint32_t -OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i) -{ - return (*p |= i); -} - -static OF_INLINE unsigned int -OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i) -{ - return (*p &= i); -} - -static OF_INLINE uint32_t -OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i) -{ - return (*p &= i); -} - -static OF_INLINE unsigned int -OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i) -{ - return (*p ^= i); -} - -static OF_INLINE uint32_t -OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i) -{ - return (*p ^= i); -} - -static OF_INLINE bool -OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n) -{ - if (*p == o) { - *p = n; - return true; - } - - return false; -} - -static OF_INLINE bool -OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n) -{ - if (*p == o) { - *p = n; - return true; - } - - return false; -} - -static OF_INLINE bool -OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p, - void *_Nullable o, void *_Nullable n) -{ - if (*p == o) { - *p = n; - return true; - } - - return false; -} - -static OF_INLINE void -OFMemoryBarrier(void) -{ - /* nop */ -} - -static OF_INLINE void -OFAcquireMemoryBarrier(void) -{ - /* nop */ -} - -static OF_INLINE void -OFReleaseMemoryBarrier(void) -{ - /* nop */ -} DELETED src/OFAtomic_osatomic.h Index: src/OFAtomic_osatomic.h ================================================================== --- src/OFAtomic_osatomic.h +++ src/OFAtomic_osatomic.h @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include - -static OF_INLINE int -OFAtomicIntAdd(volatile int *_Nonnull p, int i) -{ - return OSAtomicAdd32(i, p); -} - -static OF_INLINE int32_t -OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i) -{ - return OSAtomicAdd32(i, p); -} - -static OF_INLINE void *_Nullable -OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i) -{ -#ifdef __LP64__ - return (void *)OSAtomicAdd64(i, (int64_t *)p); -#else - return (void *)OSAtomicAdd32(i, (int32_t *)p); -#endif -} - -static OF_INLINE int -OFAtomicIntSubtract(volatile int *_Nonnull p, int i) -{ - return OSAtomicAdd32(-i, p); -} - -static OF_INLINE int32_t -OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i) -{ - return OSAtomicAdd32(-i, p); -} - -static OF_INLINE void *_Nullable -OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i) -{ -#ifdef __LP64__ - return (void *)OSAtomicAdd64(-i, (int64_t *)p); -#else - return (void *)OSAtomicAdd32(-i, (int32_t *)p); -#endif -} - -static OF_INLINE int -OFAtomicIntIncrease(volatile int *_Nonnull p) -{ - return OSAtomicIncrement32(p); -} - -static OF_INLINE int32_t -OFAtomicInt32Increase(volatile int32_t *_Nonnull p) -{ - return OSAtomicIncrement32(p); -} - -static OF_INLINE int -OFAtomicIntDecrease(volatile int *_Nonnull p) -{ - return OSAtomicDecrement32(p); -} - -static OF_INLINE int32_t -OFAtomicInt32Decrease(volatile int32_t *_Nonnull p) -{ - return OSAtomicDecrement32(p); -} - -static OF_INLINE unsigned int -OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i) -{ - return OSAtomicOr32(i, p); -} - -static OF_INLINE uint32_t -OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i) -{ - return OSAtomicOr32(i, p); -} - -static OF_INLINE unsigned int -OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i) -{ - return OSAtomicAnd32(i, p); -} - -static OF_INLINE uint32_t -OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i) -{ - return OSAtomicAnd32(i, p); -} - -static OF_INLINE unsigned int -OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i) -{ - return OSAtomicXor32(i, p); -} - -static OF_INLINE uint32_t -OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i) -{ - return OSAtomicXor32(i, p); -} - -static OF_INLINE bool -OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n) -{ - return OSAtomicCompareAndSwapInt(o, n, p); -} - -static OF_INLINE bool -OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n) -{ - return OSAtomicCompareAndSwap32(o, n, p); -} - -static OF_INLINE bool -OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p, - void *_Nullable o, void *_Nullable n) -{ - return OSAtomicCompareAndSwapPtr(o, n, p); -} - -static OF_INLINE void -OFMemoryBarrier(void) -{ - OSMemoryBarrier(); -} - -static OF_INLINE void -OFAcquireMemoryBarrier(void) -{ - OSMemoryBarrier(); -} - -static OF_INLINE void -OFReleaseMemoryBarrier(void) -{ - OSMemoryBarrier(); -} DELETED src/OFAtomic_powerpc.h Index: src/OFAtomic_powerpc.h ================================================================== --- src/OFAtomic_powerpc.h +++ src/OFAtomic_powerpc.h @@ -1,397 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -static OF_INLINE int -OFAtomicIntAdd(volatile int *_Nonnull p, int i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %2\n\t" - "add %0, %0, %1\n\t" - "stwcx. %0, 0, %2\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE int32_t -OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %2\n\t" - "add %0, %0, %1\n\t" - "stwcx. %0, 0, %2\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE void *_Nullable -OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %2\n\t" - "add %0, %0, %1\n\t" - "stwcx. %0, 0, %2\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) - : "cc", "memory" - ); - - return (void *)i; -} - -static OF_INLINE int -OFAtomicIntSubtract(volatile int *_Nonnull p, int i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %2\n\t" - "sub %0, %0, %1\n\t" - "stwcx. %0, 0, %2\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE int32_t -OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %2\n\t" - "sub %0, %0, %1\n\t" - "stwcx. %0, 0, %2\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE void *_Nullable -OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %2\n\t" - "sub %0, %0, %1\n\t" - "stwcx. %0, 0, %2\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) - : "cc", "memory" - ); - - return (void *)i; -} - -static OF_INLINE int -OFAtomicIntIncrease(volatile int *_Nonnull p) -{ - int i; - - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %1\n\t" - "addi %0, %0, 1\n\t" - "stwcx. %0, 0, %1\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE int32_t -OFAtomicInt32Increase(volatile int32_t *_Nonnull p) -{ - int32_t i; - - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %1\n\t" - "addi %0, %0, 1\n\t" - "stwcx. %0, 0, %1\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE int -OFAtomicIntDecrease(volatile int *_Nonnull p) -{ - int i; - - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %1\n\t" - "subi %0, %0, 1\n\t" - "stwcx. %0, 0, %1\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE int32_t -OFAtomicInt32Decrease(volatile int32_t *_Nonnull p) -{ - int32_t i; - - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %1\n\t" - "subi %0, %0, 1\n\t" - "stwcx. %0, 0, %1\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE unsigned int -OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %2\n\t" - "or %0, %0, %1\n\t" - "stwcx. %0, 0, %2\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE uint32_t -OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %2\n\t" - "or %0, %0, %1\n\t" - "stwcx. %0, 0, %2\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE unsigned int -OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %2\n\t" - "and %0, %0, %1\n\t" - "stwcx. %0, 0, %2\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE uint32_t -OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %2\n\t" - "and %0, %0, %1\n\t" - "stwcx. %0, 0, %2\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE unsigned int -OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %2\n\t" - "xor %0, %0, %1\n\t" - "stwcx. %0, 0, %2\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE uint32_t -OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %2\n\t" - "xor %0, %0, %1\n\t" - "stwcx. %0, 0, %2\n\t" - "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) - : "cc", "memory" - ); - - return i; -} - -static OF_INLINE bool -OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n) -{ - int r; - - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %3\n\t" - "cmpw %0, %1\n\t" - "bne 1f\n\t" - "stwcx. %2, 0, %3\n\t" - "bne- 0b\n\t" - "li %0, 1\n\t" - "b 2f\n\t" - "1:\n\t" - "stwcx. %0, 0, %3\n\t" - "li %0, 0\n\t" - "2:" - : "=&r"(r) - : "r"(o), "r"(n), "r"(p) - : "cc", "memory" - ); - - return r; -} - -static OF_INLINE bool -OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n) -{ - int r; - - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %3\n\t" - "cmpw %0, %1\n\t" - "bne 1f\n\t" - "stwcx. %2, 0, %3\n\t" - "bne- 0b\n\t" - "li %0, 1\n\t" - "b 2f\n\t" - "1:\n\t" - "stwcx. %0, 0, %3\n\t" - "li %0, 0\n\t" - "2:" - : "=&r"(r) - : "r"(o), "r"(n), "r"(p) - : "cc", "memory" - ); - - return r; -} - -static OF_INLINE bool -OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p, - void *_Nullable o, void *_Nullable n) -{ - int r; - - __asm__ __volatile__ ( - "0:\n\t" - "lwarx %0, 0, %3\n\t" - "cmpw %0, %1\n\t" - "bne 1f\n\t" - "stwcx. %2, 0, %3\n\t" - "bne- 0b\n\t" - "li %0, 1\n\t" - "b 2f\n\t" - "1:\n\t" - "stwcx. %0, 0, %3\n\t" - "li %0, 0\n\t" - "2:" - : "=&r"(r) - : "r"(o), "r"(n), "r"(p) - : "cc", "memory" - ); - - return r; -} - -static OF_INLINE void -OFMemoryBarrier(void) -{ - __asm__ __volatile__ ( - ".long 0x7C2004AC /* lwsync */" ::: "memory" - ); -} - -static OF_INLINE void -OFAcquireMemoryBarrier(void) -{ - __asm__ __volatile__ ( - ".long 0x7C2004AC /* lwsync */" ::: "memory" - ); -} - -static OF_INLINE void -OFReleaseMemoryBarrier(void) -{ - __asm__ __volatile__ ( - ".long 0x7C2004AC /* lwsync */" ::: "memory" - ); -} DELETED src/OFAtomic_sync_builtins.h Index: src/OFAtomic_sync_builtins.h ================================================================== --- src/OFAtomic_sync_builtins.h +++ src/OFAtomic_sync_builtins.h @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -static OF_INLINE int -OFAtomicIntAdd(volatile int *_Nonnull p, int i) -{ - return __sync_add_and_fetch(p, i); -} - -static OF_INLINE int32_t -OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i) -{ - return __sync_add_and_fetch(p, i); -} - -static OF_INLINE void *_Nullable -OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i) -{ - return __sync_add_and_fetch(p, (void *)i); -} - -static OF_INLINE int -OFAtomicIntSubtract(volatile int *_Nonnull p, int i) -{ - return __sync_sub_and_fetch(p, i); -} - -static OF_INLINE int32_t -OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i) -{ - return __sync_sub_and_fetch(p, i); -} - -static OF_INLINE void *_Nullable -OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i) -{ - return __sync_sub_and_fetch(p, (void *)i); -} - -static OF_INLINE int -OFAtomicIntIncrease(volatile int *_Nonnull p) -{ - return __sync_add_and_fetch(p, 1); -} - -static OF_INLINE int32_t -OFAtomicInt32Increase(volatile int32_t *_Nonnull p) -{ - return __sync_add_and_fetch(p, 1); -} - -static OF_INLINE int -OFAtomicIntDecrease(volatile int *_Nonnull p) -{ - return __sync_sub_and_fetch(p, 1); -} - -static OF_INLINE int32_t -OFAtomicInt32Decrease(volatile int32_t *_Nonnull p) -{ - return __sync_sub_and_fetch(p, 1); -} - -static OF_INLINE unsigned int -OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i) -{ - return __sync_or_and_fetch(p, i); -} - -static OF_INLINE uint32_t -OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i) -{ - return __sync_or_and_fetch(p, i); -} - -static OF_INLINE unsigned int -OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i) -{ - return __sync_and_and_fetch(p, i); -} - -static OF_INLINE uint32_t -OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i) -{ - return __sync_and_and_fetch(p, i); -} - -static OF_INLINE unsigned int -OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i) -{ - return __sync_xor_and_fetch(p, i); -} - -static OF_INLINE uint32_t -OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i) -{ - return __sync_xor_and_fetch(p, i); -} - -static OF_INLINE bool -OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n) -{ - return __sync_bool_compare_and_swap(p, o, n); -} - -static OF_INLINE bool -OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n) -{ - return __sync_bool_compare_and_swap(p, o, n); -} - -static OF_INLINE bool -OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p, - void *_Nullable o, void *_Nullable n) -{ - return __sync_bool_compare_and_swap(p, o, n); -} - -static OF_INLINE void -OFMemoryBarrier(void) -{ - __sync_synchronize(); -} - -static OF_INLINE void -OFAcquireMemoryBarrier(void) -{ - __sync_synchronize(); -} - -static OF_INLINE void -OFReleaseMemoryBarrier(void) -{ - __sync_synchronize(); -} DELETED src/OFAtomic_x86.h Index: src/OFAtomic_x86.h ================================================================== --- src/OFAtomic_x86.h +++ src/OFAtomic_x86.h @@ -1,502 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -OF_ASSUME_NONNULL_BEGIN - -static OF_INLINE int -OFAtomicIntAdd(volatile int *_Nonnull p, int i) -{ - if (sizeof(int) == 4) - __asm__ __volatile__ ( - "lock\n\t" - "xaddl %0, %2\n\t" - "addl %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) - ); -#ifdef OF_X86_64 - else if (sizeof(int) == 8) - __asm__ __volatile__ ( - "lock\n\t" - "xaddq %0, %2\n\t" - "addq %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) - ); -#endif - else - abort(); - - return i; -} - -static OF_INLINE int32_t -OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i) -{ - __asm__ __volatile__ ( - "lock\n\t" - "xaddl %0, %2\n\t" - "addl %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) - ); - - return i; -} - -static OF_INLINE void *_Nullable -OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i) -{ -#if defined(OF_X86_64) - __asm__ __volatile__ ( - "lock\n\t" - "xaddq %0, %2\n\t" - "addq %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) - ); - - return (void *)i; -#elif defined(OF_X86) - __asm__ __volatile__ ( - "lock\n\t" - "xaddl %0, %2\n\t" - "addl %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) - ); - - return (void *)i; -#endif -} - -static OF_INLINE int -OFAtomicIntSubtract(volatile int *_Nonnull p, int i) -{ - if (sizeof(int) == 4) - __asm__ __volatile__ ( - "negl %0\n\t" - "lock\n\t" - "xaddl %0, %2\n\t" - "subl %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) - ); -#ifdef OF_X86_64 - else if (sizeof(int) == 8) - __asm__ __volatile__ ( - "negq %0\n\t" - "lock\n\t" - "xaddq %0, %2\n\t" - "subq %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) - ); -#endif - else - abort(); - - return i; -} - -static OF_INLINE int32_t -OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i) -{ - __asm__ __volatile__ ( - "negl %0\n\t" - "lock\n\t" - "xaddl %0, %2\n\t" - "subl %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) - ); - - return i; -} - -static OF_INLINE void *_Nullable -OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i) -{ -#if defined(OF_X86_64) - __asm__ __volatile__ ( - "negq %0\n\t" - "lock\n\t" - "xaddq %0, %2\n\t" - "subq %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) - ); - - return (void *)i; -#elif defined(OF_X86) - __asm__ __volatile__ ( - "negl %0\n\t" - "lock\n\t" - "xaddl %0, %2\n\t" - "subl %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) - ); - - return (void *)i; -#endif -} - -static OF_INLINE int -OFAtomicIntIncrease(volatile int *_Nonnull p) -{ - int i; - - if (sizeof(int) == 4) - __asm__ __volatile__ ( - "xorl %0, %0\n\t" - "incl %0\n\t" - "lock\n\t" - "xaddl %0, %1\n\t" - "incl %0" - : "=&r"(i) - : "m"(*p) - ); -#ifdef OF_X86_64 - else if (sizeof(int) == 8) - __asm__ __volatile__ ( - "xorq %0, %0\n\t" - "incq %0\n\t" - "lock\n\t" - "xaddq %0, %1\n\t" - "incq %0" - : "=&r"(i) - : "m"(*p) - ); -#endif - else - abort(); - - return i; -} - -static OF_INLINE int32_t -OFAtomicInt32Increase(volatile int32_t *_Nonnull p) -{ - int32_t i; - - __asm__ __volatile__ ( - "xorl %0, %0\n\t" - "incl %0\n\t" - "lock\n\t" - "xaddl %0, %1\n\t" - "incl %0" - : "=&r"(i) - : "m"(*p) - ); - - return i; -} - -static OF_INLINE int -OFAtomicIntDecrease(volatile int *_Nonnull p) -{ - int i; - - if (sizeof(int) == 4) - __asm__ __volatile__ ( - "xorl %0, %0\n\t" - "decl %0\n\t" - "lock\n\t" - "xaddl %0, %1\n\t" - "decl %0" - : "=&r"(i) - : "m"(*p) - ); -#ifdef OF_X86_64 - else if (sizeof(int) == 8) - __asm__ __volatile__ ( - "xorq %0, %0\n\t" - "decq %0\n\t" - "lock\n\t" - "xaddq %0, %1\n\t" - "decq %0" - : "=&r"(i) - : "m"(*p) - ); -#endif - else - abort(); - - return i; -} - -static OF_INLINE int32_t -OFAtomicInt32Decrease(volatile int32_t *_Nonnull p) -{ - int32_t i; - - __asm__ __volatile__ ( - "xorl %0, %0\n\t" - "decl %0\n\t" - "lock\n\t" - "xaddl %0, %1\n\t" - "decl %0" - : "=&r"(i) - : "m"(*p) - ); - - return i; -} - -static OF_INLINE unsigned int -OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i) -{ - if (sizeof(int) == 4) - __asm__ __volatile__ ( - "0:\n\t" - "movl %2, %0\n\t" - "movl %0, %%eax\n\t" - "orl %1, %0\n\t" - "lock\n\t" - "cmpxchg %0, %2\n\t" - "jne 0b" - : "=&r"(i) - : "r"(i), "m"(*p) - : "eax", "cc" - ); -#ifdef OF_X86_64 - else if (sizeof(int) == 8) - __asm__ __volatile__ ( - "0:\n\t" - "movq %2, %0\n\t" - "movq %0, %%rax\n\t" - "orq %1, %0\n\t" - "lock\n\t" - "cmpxchg %0, %2\n\t" - "jne 0b" - : "=&r"(i) - : "r"(i), "m"(*p) - : "rax", "cc" - ); -#endif - else - abort(); - - return i; -} - -static OF_INLINE uint32_t -OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "movl %2, %0\n\t" - "movl %0, %%eax\n\t" - "orl %1, %0\n\t" - "lock\n\t" - "cmpxchg %0, %2\n\t" - "jne 0b" - : "=&r"(i) - : "r"(i), "m"(*p) - : "eax", "cc" - ); - - return i; -} - -static OF_INLINE unsigned int -OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i) -{ - if (sizeof(int) == 4) - __asm__ __volatile__ ( - "0:\n\t" - "movl %2, %0\n\t" - "movl %0, %%eax\n\t" - "andl %1, %0\n\t" - "lock\n\t" - "cmpxchg %0, %2\n\t" - "jne 0b" - : "=&r"(i) - : "r"(i), "m"(*p) - : "eax", "cc" - ); -#ifdef OF_X86_64 - else if (sizeof(int) == 8) - __asm__ __volatile__ ( - "0:\n\t" - "movq %2, %0\n\t" - "movq %0, %%rax\n\t" - "andq %1, %0\n\t" - "lock\n\t" - "cmpxchg %0, %2\n\t" - "jne 0b" - : "=&r"(i) - : "r"(i), "m"(*p) - : "rax", "cc" - ); -#endif - else - abort(); - - return i; -} - -static OF_INLINE uint32_t -OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "movl %2, %0\n\t" - "movl %0, %%eax\n\t" - "andl %1, %0\n\t" - "lock\n\t" - "cmpxchg %0, %2\n\t" - "jne 0b" - : "=&r"(i) - : "r"(i), "m"(*p) - : "eax", "cc" - ); - - return i; -} - -static OF_INLINE unsigned int -OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i) -{ - if (sizeof(int) == 4) - __asm__ __volatile__ ( - "0:\n\t" - "movl %2, %0\n\t" - "movl %0, %%eax\n\t" - "xorl %1, %0\n\t" - "lock\n\t" - "cmpxchg %0, %2\n\t" - "jne 0b" - : "=&r"(i) - : "r"(i), "m"(*p) - : "eax", "cc" - ); -#ifdef OF_X86_64 - else if (sizeof(int) == 8) - __asm__ __volatile__ ( - "0:\n\t" - "movq %2, %0\n\t" - "movq %0, %%rax\n\t" - "xorq %1, %0\n\t" - "lock\n\t" - "cmpxchg %0, %2\n\t" - "jne 0b" - : "=&r"(i) - : "r"(i), "m"(*p) - : "rax", "cc" - ); -#endif - else - abort(); - - return i; -} - -static OF_INLINE uint32_t -OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i) -{ - __asm__ __volatile__ ( - "0:\n\t" - "movl %2, %0\n\t" - "movl %0, %%eax\n\t" - "xorl %1, %0\n\t" - "lock\n\t" - "cmpxchgl %0, %2\n\t" - "jne 0b" - : "=&r"(i) - : "r"(i), "m"(*p) - : "eax", "cc" - ); - - return i; -} - -static OF_INLINE bool -OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n) -{ - int r; - - __asm__ __volatile__ ( - "lock\n\t" - "cmpxchg %2, %3\n\t" - "sete %b0\n\t" - "movzbl %b0, %0" - : "=&d"(r), "+a"(o) /* use d instead of r to avoid a gcc bug */ - : "r"(n), "m"(*p) - : "cc" - ); - - return r; -} - -static OF_INLINE bool -OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n) -{ - int r; - - __asm__ __volatile__ ( - "lock\n\t" - "cmpxchg %2, %3\n\t" - "sete %b0\n\t" - "movzbl %b0, %0" - : "=&d"(r), "+a"(o) /* use d instead of r to avoid a gcc bug */ - : "r"(n), "m"(*p) - : "cc" - ); - - return r; -} - -static OF_INLINE bool -OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p, - void *_Nullable o, void *_Nullable n) -{ - int r; - - __asm__ __volatile__ ( - "lock\n\t" - "cmpxchg %2, %3\n\t" - "sete %b0\n\t" - "movzbl %b0, %0" - : "=&d"(r), "+a"(o) /* use d instead of r to avoid a gcc bug */ - : "r"(n), "m"(*p) - : "cc" - ); - - return r; -} - -static OF_INLINE void -OFMemoryBarrier(void) -{ - __asm__ __volatile__ ( - "mfence" ::: "memory" - ); -} - -static OF_INLINE void -OFAcquireMemoryBarrier(void) -{ - __asm__ __volatile__ ("" ::: "memory"); -} - -static OF_INLINE void -OFReleaseMemoryBarrier(void) -{ - __asm__ __volatile__ ("" ::: "memory"); -} - -OF_ASSUME_NONNULL_END Index: src/module.modulemap ================================================================== --- src/module.modulemap +++ src/module.modulemap @@ -3,14 +3,13 @@ /* * These are included by OFAtomic.h, but should never be included * directly. */ - exclude header "OFAtomic_builtins.h" - exclude header "OFAtomic_no_threads.h" - exclude header "OFAtomic_osatomic.h" - exclude header "OFAtomic_powerpc.h" - exclude header "OFAtomic_sync_builtins.h" - exclude header "OFAtomic_x86.h" + exclude header "platform/GCC4/OFAtomic.h" + exclude header "platform/GCC4.7/OFAtomic.h" + exclude header "platform/PowerPC/OFAtomic.h" + exclude header "platform/macOS/OFAtomic.h" + exclude header "platform/x86/OFAtomic.h" export * } ADDED src/platform/GCC4.7/OFAtomic.h Index: src/platform/GCC4.7/OFAtomic.h ================================================================== --- src/platform/GCC4.7/OFAtomic.h +++ src/platform/GCC4.7/OFAtomic.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +static OF_INLINE int +OFAtomicIntAdd(volatile int *_Nonnull p, int i) +{ + return __atomic_add_fetch(p, i, __ATOMIC_RELAXED); +} + +static OF_INLINE int32_t +OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i) +{ + return __atomic_add_fetch(p, i, __ATOMIC_RELAXED); +} + +static OF_INLINE void *_Nullable +OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i) +{ + return __atomic_add_fetch(p, i, __ATOMIC_RELAXED); +} + +static OF_INLINE int +OFAtomicIntSubtract(volatile int *_Nonnull p, int i) +{ + return __atomic_sub_fetch(p, i, __ATOMIC_RELAXED); +} + +static OF_INLINE int32_t +OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i) +{ + return __atomic_sub_fetch(p, i, __ATOMIC_RELAXED); +} + +static OF_INLINE void *_Nullable +OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i) +{ + return __atomic_sub_fetch(p, i, __ATOMIC_RELAXED); +} + +static OF_INLINE int +OFAtomicIntIncrease(volatile int *_Nonnull p) +{ + return __atomic_add_fetch(p, 1, __ATOMIC_RELAXED); +} + +static OF_INLINE int32_t +OFAtomicInt32Increase(volatile int32_t *_Nonnull p) +{ + return __atomic_add_fetch(p, 1, __ATOMIC_RELAXED); +} + +static OF_INLINE int +OFAtomicIntDecrease(volatile int *_Nonnull p) +{ + return __atomic_sub_fetch(p, 1, __ATOMIC_RELAXED); +} + +static OF_INLINE int32_t +OFAtomicInt32Decrease(volatile int32_t *_Nonnull p) +{ + return __atomic_sub_fetch(p, 1, __ATOMIC_RELAXED); +} + +static OF_INLINE unsigned int +OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i) +{ + return __atomic_or_fetch(p, i, __ATOMIC_RELAXED); +} + +static OF_INLINE uint32_t +OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i) +{ + return __atomic_or_fetch(p, i, __ATOMIC_RELAXED); +} + +static OF_INLINE unsigned int +OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i) +{ + return __atomic_and_fetch(p, i, __ATOMIC_RELAXED); +} + +static OF_INLINE uint32_t +OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i) +{ + return __atomic_and_fetch(p, i, __ATOMIC_RELAXED); +} + +static OF_INLINE unsigned int +OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i) +{ + return __atomic_xor_fetch(p, i, __ATOMIC_RELAXED); +} + +static OF_INLINE uint32_t +OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i) +{ + return __atomic_xor_fetch(p, i, __ATOMIC_RELAXED); +} + +static OF_INLINE bool +OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n) +{ + return __atomic_compare_exchange(p, &o, &n, false, + __ATOMIC_RELAXED, __ATOMIC_RELAXED); +} + +static OF_INLINE bool +OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n) +{ + return __atomic_compare_exchange(p, &o, &n, false, + __ATOMIC_RELAXED, __ATOMIC_RELAXED); +} + +static OF_INLINE bool +OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p, + void *_Nullable o, void *_Nullable n) +{ + return __atomic_compare_exchange(p, &o, &n, false, + __ATOMIC_RELAXED, __ATOMIC_RELAXED); +} + +static OF_INLINE void +OFMemoryBarrier(void) +{ + __atomic_thread_fence(__ATOMIC_SEQ_CST); +} + +static OF_INLINE void +OFAcquireMemoryBarrier(void) +{ + __atomic_thread_fence(__ATOMIC_ACQUIRE); +} + +static OF_INLINE void +OFReleaseMemoryBarrier(void) +{ + __atomic_thread_fence(__ATOMIC_RELEASE); +} ADDED src/platform/GCC4/OFAtomic.h Index: src/platform/GCC4/OFAtomic.h ================================================================== --- src/platform/GCC4/OFAtomic.h +++ src/platform/GCC4/OFAtomic.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +static OF_INLINE int +OFAtomicIntAdd(volatile int *_Nonnull p, int i) +{ + return __sync_add_and_fetch(p, i); +} + +static OF_INLINE int32_t +OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i) +{ + return __sync_add_and_fetch(p, i); +} + +static OF_INLINE void *_Nullable +OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i) +{ + return __sync_add_and_fetch(p, (void *)i); +} + +static OF_INLINE int +OFAtomicIntSubtract(volatile int *_Nonnull p, int i) +{ + return __sync_sub_and_fetch(p, i); +} + +static OF_INLINE int32_t +OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i) +{ + return __sync_sub_and_fetch(p, i); +} + +static OF_INLINE void *_Nullable +OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i) +{ + return __sync_sub_and_fetch(p, (void *)i); +} + +static OF_INLINE int +OFAtomicIntIncrease(volatile int *_Nonnull p) +{ + return __sync_add_and_fetch(p, 1); +} + +static OF_INLINE int32_t +OFAtomicInt32Increase(volatile int32_t *_Nonnull p) +{ + return __sync_add_and_fetch(p, 1); +} + +static OF_INLINE int +OFAtomicIntDecrease(volatile int *_Nonnull p) +{ + return __sync_sub_and_fetch(p, 1); +} + +static OF_INLINE int32_t +OFAtomicInt32Decrease(volatile int32_t *_Nonnull p) +{ + return __sync_sub_and_fetch(p, 1); +} + +static OF_INLINE unsigned int +OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i) +{ + return __sync_or_and_fetch(p, i); +} + +static OF_INLINE uint32_t +OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i) +{ + return __sync_or_and_fetch(p, i); +} + +static OF_INLINE unsigned int +OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i) +{ + return __sync_and_and_fetch(p, i); +} + +static OF_INLINE uint32_t +OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i) +{ + return __sync_and_and_fetch(p, i); +} + +static OF_INLINE unsigned int +OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i) +{ + return __sync_xor_and_fetch(p, i); +} + +static OF_INLINE uint32_t +OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i) +{ + return __sync_xor_and_fetch(p, i); +} + +static OF_INLINE bool +OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n) +{ + return __sync_bool_compare_and_swap(p, o, n); +} + +static OF_INLINE bool +OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n) +{ + return __sync_bool_compare_and_swap(p, o, n); +} + +static OF_INLINE bool +OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p, + void *_Nullable o, void *_Nullable n) +{ + return __sync_bool_compare_and_swap(p, o, n); +} + +static OF_INLINE void +OFMemoryBarrier(void) +{ + __sync_synchronize(); +} + +static OF_INLINE void +OFAcquireMemoryBarrier(void) +{ + __sync_synchronize(); +} + +static OF_INLINE void +OFReleaseMemoryBarrier(void) +{ + __sync_synchronize(); +} ADDED src/platform/PowerPC/OFAtomic.h Index: src/platform/PowerPC/OFAtomic.h ================================================================== --- src/platform/PowerPC/OFAtomic.h +++ src/platform/PowerPC/OFAtomic.h @@ -0,0 +1,397 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +static OF_INLINE int +OFAtomicIntAdd(volatile int *_Nonnull p, int i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %2\n\t" + "add %0, %0, %1\n\t" + "stwcx. %0, 0, %2\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(i), "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE int32_t +OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %2\n\t" + "add %0, %0, %1\n\t" + "stwcx. %0, 0, %2\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(i), "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE void *_Nullable +OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %2\n\t" + "add %0, %0, %1\n\t" + "stwcx. %0, 0, %2\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(i), "r"(p) + : "cc", "memory" + ); + + return (void *)i; +} + +static OF_INLINE int +OFAtomicIntSubtract(volatile int *_Nonnull p, int i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %2\n\t" + "sub %0, %0, %1\n\t" + "stwcx. %0, 0, %2\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(i), "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE int32_t +OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %2\n\t" + "sub %0, %0, %1\n\t" + "stwcx. %0, 0, %2\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(i), "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE void *_Nullable +OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %2\n\t" + "sub %0, %0, %1\n\t" + "stwcx. %0, 0, %2\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(i), "r"(p) + : "cc", "memory" + ); + + return (void *)i; +} + +static OF_INLINE int +OFAtomicIntIncrease(volatile int *_Nonnull p) +{ + int i; + + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %1\n\t" + "addi %0, %0, 1\n\t" + "stwcx. %0, 0, %1\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE int32_t +OFAtomicInt32Increase(volatile int32_t *_Nonnull p) +{ + int32_t i; + + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %1\n\t" + "addi %0, %0, 1\n\t" + "stwcx. %0, 0, %1\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE int +OFAtomicIntDecrease(volatile int *_Nonnull p) +{ + int i; + + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %1\n\t" + "subi %0, %0, 1\n\t" + "stwcx. %0, 0, %1\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE int32_t +OFAtomicInt32Decrease(volatile int32_t *_Nonnull p) +{ + int32_t i; + + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %1\n\t" + "subi %0, %0, 1\n\t" + "stwcx. %0, 0, %1\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE unsigned int +OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %2\n\t" + "or %0, %0, %1\n\t" + "stwcx. %0, 0, %2\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(i), "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE uint32_t +OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %2\n\t" + "or %0, %0, %1\n\t" + "stwcx. %0, 0, %2\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(i), "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE unsigned int +OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %2\n\t" + "and %0, %0, %1\n\t" + "stwcx. %0, 0, %2\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(i), "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE uint32_t +OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %2\n\t" + "and %0, %0, %1\n\t" + "stwcx. %0, 0, %2\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(i), "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE unsigned int +OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %2\n\t" + "xor %0, %0, %1\n\t" + "stwcx. %0, 0, %2\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(i), "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE uint32_t +OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %2\n\t" + "xor %0, %0, %1\n\t" + "stwcx. %0, 0, %2\n\t" + "bne- 0b" + : "=&r"(i) + : "r"(i), "r"(p) + : "cc", "memory" + ); + + return i; +} + +static OF_INLINE bool +OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n) +{ + int r; + + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %3\n\t" + "cmpw %0, %1\n\t" + "bne 1f\n\t" + "stwcx. %2, 0, %3\n\t" + "bne- 0b\n\t" + "li %0, 1\n\t" + "b 2f\n\t" + "1:\n\t" + "stwcx. %0, 0, %3\n\t" + "li %0, 0\n\t" + "2:" + : "=&r"(r) + : "r"(o), "r"(n), "r"(p) + : "cc", "memory" + ); + + return r; +} + +static OF_INLINE bool +OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n) +{ + int r; + + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %3\n\t" + "cmpw %0, %1\n\t" + "bne 1f\n\t" + "stwcx. %2, 0, %3\n\t" + "bne- 0b\n\t" + "li %0, 1\n\t" + "b 2f\n\t" + "1:\n\t" + "stwcx. %0, 0, %3\n\t" + "li %0, 0\n\t" + "2:" + : "=&r"(r) + : "r"(o), "r"(n), "r"(p) + : "cc", "memory" + ); + + return r; +} + +static OF_INLINE bool +OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p, + void *_Nullable o, void *_Nullable n) +{ + int r; + + __asm__ __volatile__ ( + "0:\n\t" + "lwarx %0, 0, %3\n\t" + "cmpw %0, %1\n\t" + "bne 1f\n\t" + "stwcx. %2, 0, %3\n\t" + "bne- 0b\n\t" + "li %0, 1\n\t" + "b 2f\n\t" + "1:\n\t" + "stwcx. %0, 0, %3\n\t" + "li %0, 0\n\t" + "2:" + : "=&r"(r) + : "r"(o), "r"(n), "r"(p) + : "cc", "memory" + ); + + return r; +} + +static OF_INLINE void +OFMemoryBarrier(void) +{ + __asm__ __volatile__ ( + ".long 0x7C2004AC /* lwsync */" ::: "memory" + ); +} + +static OF_INLINE void +OFAcquireMemoryBarrier(void) +{ + __asm__ __volatile__ ( + ".long 0x7C2004AC /* lwsync */" ::: "memory" + ); +} + +static OF_INLINE void +OFReleaseMemoryBarrier(void) +{ + __asm__ __volatile__ ( + ".long 0x7C2004AC /* lwsync */" ::: "memory" + ); +} ADDED src/platform/macOS/OFAtomic.h Index: src/platform/macOS/OFAtomic.h ================================================================== --- src/platform/macOS/OFAtomic.h +++ src/platform/macOS/OFAtomic.h @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include + +static OF_INLINE int +OFAtomicIntAdd(volatile int *_Nonnull p, int i) +{ + return OSAtomicAdd32(i, p); +} + +static OF_INLINE int32_t +OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i) +{ + return OSAtomicAdd32(i, p); +} + +static OF_INLINE void *_Nullable +OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i) +{ +#ifdef __LP64__ + return (void *)OSAtomicAdd64(i, (int64_t *)p); +#else + return (void *)OSAtomicAdd32(i, (int32_t *)p); +#endif +} + +static OF_INLINE int +OFAtomicIntSubtract(volatile int *_Nonnull p, int i) +{ + return OSAtomicAdd32(-i, p); +} + +static OF_INLINE int32_t +OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i) +{ + return OSAtomicAdd32(-i, p); +} + +static OF_INLINE void *_Nullable +OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i) +{ +#ifdef __LP64__ + return (void *)OSAtomicAdd64(-i, (int64_t *)p); +#else + return (void *)OSAtomicAdd32(-i, (int32_t *)p); +#endif +} + +static OF_INLINE int +OFAtomicIntIncrease(volatile int *_Nonnull p) +{ + return OSAtomicIncrement32(p); +} + +static OF_INLINE int32_t +OFAtomicInt32Increase(volatile int32_t *_Nonnull p) +{ + return OSAtomicIncrement32(p); +} + +static OF_INLINE int +OFAtomicIntDecrease(volatile int *_Nonnull p) +{ + return OSAtomicDecrement32(p); +} + +static OF_INLINE int32_t +OFAtomicInt32Decrease(volatile int32_t *_Nonnull p) +{ + return OSAtomicDecrement32(p); +} + +static OF_INLINE unsigned int +OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i) +{ + return OSAtomicOr32(i, p); +} + +static OF_INLINE uint32_t +OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i) +{ + return OSAtomicOr32(i, p); +} + +static OF_INLINE unsigned int +OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i) +{ + return OSAtomicAnd32(i, p); +} + +static OF_INLINE uint32_t +OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i) +{ + return OSAtomicAnd32(i, p); +} + +static OF_INLINE unsigned int +OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i) +{ + return OSAtomicXor32(i, p); +} + +static OF_INLINE uint32_t +OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i) +{ + return OSAtomicXor32(i, p); +} + +static OF_INLINE bool +OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n) +{ + return OSAtomicCompareAndSwapInt(o, n, p); +} + +static OF_INLINE bool +OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n) +{ + return OSAtomicCompareAndSwap32(o, n, p); +} + +static OF_INLINE bool +OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p, + void *_Nullable o, void *_Nullable n) +{ + return OSAtomicCompareAndSwapPtr(o, n, p); +} + +static OF_INLINE void +OFMemoryBarrier(void) +{ + OSMemoryBarrier(); +} + +static OF_INLINE void +OFAcquireMemoryBarrier(void) +{ + OSMemoryBarrier(); +} + +static OF_INLINE void +OFReleaseMemoryBarrier(void) +{ + OSMemoryBarrier(); +} ADDED src/platform/x86/OFAtomic.h Index: src/platform/x86/OFAtomic.h ================================================================== --- src/platform/x86/OFAtomic.h +++ src/platform/x86/OFAtomic.h @@ -0,0 +1,502 @@ +/* + * Copyright (c) 2008-2021 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +OF_ASSUME_NONNULL_BEGIN + +static OF_INLINE int +OFAtomicIntAdd(volatile int *_Nonnull p, int i) +{ + if (sizeof(int) == 4) + __asm__ __volatile__ ( + "lock\n\t" + "xaddl %0, %2\n\t" + "addl %1, %0" + : "+&r"(i) + : "r"(i), "m"(*p) + ); +#ifdef OF_X86_64 + else if (sizeof(int) == 8) + __asm__ __volatile__ ( + "lock\n\t" + "xaddq %0, %2\n\t" + "addq %1, %0" + : "+&r"(i) + : "r"(i), "m"(*p) + ); +#endif + else + abort(); + + return i; +} + +static OF_INLINE int32_t +OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i) +{ + __asm__ __volatile__ ( + "lock\n\t" + "xaddl %0, %2\n\t" + "addl %1, %0" + : "+&r"(i) + : "r"(i), "m"(*p) + ); + + return i; +} + +static OF_INLINE void *_Nullable +OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i) +{ +#if defined(OF_X86_64) + __asm__ __volatile__ ( + "lock\n\t" + "xaddq %0, %2\n\t" + "addq %1, %0" + : "+&r"(i) + : "r"(i), "m"(*p) + ); + + return (void *)i; +#elif defined(OF_X86) + __asm__ __volatile__ ( + "lock\n\t" + "xaddl %0, %2\n\t" + "addl %1, %0" + : "+&r"(i) + : "r"(i), "m"(*p) + ); + + return (void *)i; +#endif +} + +static OF_INLINE int +OFAtomicIntSubtract(volatile int *_Nonnull p, int i) +{ + if (sizeof(int) == 4) + __asm__ __volatile__ ( + "negl %0\n\t" + "lock\n\t" + "xaddl %0, %2\n\t" + "subl %1, %0" + : "+&r"(i) + : "r"(i), "m"(*p) + ); +#ifdef OF_X86_64 + else if (sizeof(int) == 8) + __asm__ __volatile__ ( + "negq %0\n\t" + "lock\n\t" + "xaddq %0, %2\n\t" + "subq %1, %0" + : "+&r"(i) + : "r"(i), "m"(*p) + ); +#endif + else + abort(); + + return i; +} + +static OF_INLINE int32_t +OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i) +{ + __asm__ __volatile__ ( + "negl %0\n\t" + "lock\n\t" + "xaddl %0, %2\n\t" + "subl %1, %0" + : "+&r"(i) + : "r"(i), "m"(*p) + ); + + return i; +} + +static OF_INLINE void *_Nullable +OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i) +{ +#if defined(OF_X86_64) + __asm__ __volatile__ ( + "negq %0\n\t" + "lock\n\t" + "xaddq %0, %2\n\t" + "subq %1, %0" + : "+&r"(i) + : "r"(i), "m"(*p) + ); + + return (void *)i; +#elif defined(OF_X86) + __asm__ __volatile__ ( + "negl %0\n\t" + "lock\n\t" + "xaddl %0, %2\n\t" + "subl %1, %0" + : "+&r"(i) + : "r"(i), "m"(*p) + ); + + return (void *)i; +#endif +} + +static OF_INLINE int +OFAtomicIntIncrease(volatile int *_Nonnull p) +{ + int i; + + if (sizeof(int) == 4) + __asm__ __volatile__ ( + "xorl %0, %0\n\t" + "incl %0\n\t" + "lock\n\t" + "xaddl %0, %1\n\t" + "incl %0" + : "=&r"(i) + : "m"(*p) + ); +#ifdef OF_X86_64 + else if (sizeof(int) == 8) + __asm__ __volatile__ ( + "xorq %0, %0\n\t" + "incq %0\n\t" + "lock\n\t" + "xaddq %0, %1\n\t" + "incq %0" + : "=&r"(i) + : "m"(*p) + ); +#endif + else + abort(); + + return i; +} + +static OF_INLINE int32_t +OFAtomicInt32Increase(volatile int32_t *_Nonnull p) +{ + int32_t i; + + __asm__ __volatile__ ( + "xorl %0, %0\n\t" + "incl %0\n\t" + "lock\n\t" + "xaddl %0, %1\n\t" + "incl %0" + : "=&r"(i) + : "m"(*p) + ); + + return i; +} + +static OF_INLINE int +OFAtomicIntDecrease(volatile int *_Nonnull p) +{ + int i; + + if (sizeof(int) == 4) + __asm__ __volatile__ ( + "xorl %0, %0\n\t" + "decl %0\n\t" + "lock\n\t" + "xaddl %0, %1\n\t" + "decl %0" + : "=&r"(i) + : "m"(*p) + ); +#ifdef OF_X86_64 + else if (sizeof(int) == 8) + __asm__ __volatile__ ( + "xorq %0, %0\n\t" + "decq %0\n\t" + "lock\n\t" + "xaddq %0, %1\n\t" + "decq %0" + : "=&r"(i) + : "m"(*p) + ); +#endif + else + abort(); + + return i; +} + +static OF_INLINE int32_t +OFAtomicInt32Decrease(volatile int32_t *_Nonnull p) +{ + int32_t i; + + __asm__ __volatile__ ( + "xorl %0, %0\n\t" + "decl %0\n\t" + "lock\n\t" + "xaddl %0, %1\n\t" + "decl %0" + : "=&r"(i) + : "m"(*p) + ); + + return i; +} + +static OF_INLINE unsigned int +OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i) +{ + if (sizeof(int) == 4) + __asm__ __volatile__ ( + "0:\n\t" + "movl %2, %0\n\t" + "movl %0, %%eax\n\t" + "orl %1, %0\n\t" + "lock\n\t" + "cmpxchg %0, %2\n\t" + "jne 0b" + : "=&r"(i) + : "r"(i), "m"(*p) + : "eax", "cc" + ); +#ifdef OF_X86_64 + else if (sizeof(int) == 8) + __asm__ __volatile__ ( + "0:\n\t" + "movq %2, %0\n\t" + "movq %0, %%rax\n\t" + "orq %1, %0\n\t" + "lock\n\t" + "cmpxchg %0, %2\n\t" + "jne 0b" + : "=&r"(i) + : "r"(i), "m"(*p) + : "rax", "cc" + ); +#endif + else + abort(); + + return i; +} + +static OF_INLINE uint32_t +OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "movl %2, %0\n\t" + "movl %0, %%eax\n\t" + "orl %1, %0\n\t" + "lock\n\t" + "cmpxchg %0, %2\n\t" + "jne 0b" + : "=&r"(i) + : "r"(i), "m"(*p) + : "eax", "cc" + ); + + return i; +} + +static OF_INLINE unsigned int +OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i) +{ + if (sizeof(int) == 4) + __asm__ __volatile__ ( + "0:\n\t" + "movl %2, %0\n\t" + "movl %0, %%eax\n\t" + "andl %1, %0\n\t" + "lock\n\t" + "cmpxchg %0, %2\n\t" + "jne 0b" + : "=&r"(i) + : "r"(i), "m"(*p) + : "eax", "cc" + ); +#ifdef OF_X86_64 + else if (sizeof(int) == 8) + __asm__ __volatile__ ( + "0:\n\t" + "movq %2, %0\n\t" + "movq %0, %%rax\n\t" + "andq %1, %0\n\t" + "lock\n\t" + "cmpxchg %0, %2\n\t" + "jne 0b" + : "=&r"(i) + : "r"(i), "m"(*p) + : "rax", "cc" + ); +#endif + else + abort(); + + return i; +} + +static OF_INLINE uint32_t +OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "movl %2, %0\n\t" + "movl %0, %%eax\n\t" + "andl %1, %0\n\t" + "lock\n\t" + "cmpxchg %0, %2\n\t" + "jne 0b" + : "=&r"(i) + : "r"(i), "m"(*p) + : "eax", "cc" + ); + + return i; +} + +static OF_INLINE unsigned int +OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i) +{ + if (sizeof(int) == 4) + __asm__ __volatile__ ( + "0:\n\t" + "movl %2, %0\n\t" + "movl %0, %%eax\n\t" + "xorl %1, %0\n\t" + "lock\n\t" + "cmpxchg %0, %2\n\t" + "jne 0b" + : "=&r"(i) + : "r"(i), "m"(*p) + : "eax", "cc" + ); +#ifdef OF_X86_64 + else if (sizeof(int) == 8) + __asm__ __volatile__ ( + "0:\n\t" + "movq %2, %0\n\t" + "movq %0, %%rax\n\t" + "xorq %1, %0\n\t" + "lock\n\t" + "cmpxchg %0, %2\n\t" + "jne 0b" + : "=&r"(i) + : "r"(i), "m"(*p) + : "rax", "cc" + ); +#endif + else + abort(); + + return i; +} + +static OF_INLINE uint32_t +OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i) +{ + __asm__ __volatile__ ( + "0:\n\t" + "movl %2, %0\n\t" + "movl %0, %%eax\n\t" + "xorl %1, %0\n\t" + "lock\n\t" + "cmpxchgl %0, %2\n\t" + "jne 0b" + : "=&r"(i) + : "r"(i), "m"(*p) + : "eax", "cc" + ); + + return i; +} + +static OF_INLINE bool +OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n) +{ + int r; + + __asm__ __volatile__ ( + "lock\n\t" + "cmpxchg %2, %3\n\t" + "sete %b0\n\t" + "movzbl %b0, %0" + : "=&d"(r), "+a"(o) /* use d instead of r to avoid a gcc bug */ + : "r"(n), "m"(*p) + : "cc" + ); + + return r; +} + +static OF_INLINE bool +OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n) +{ + int r; + + __asm__ __volatile__ ( + "lock\n\t" + "cmpxchg %2, %3\n\t" + "sete %b0\n\t" + "movzbl %b0, %0" + : "=&d"(r), "+a"(o) /* use d instead of r to avoid a gcc bug */ + : "r"(n), "m"(*p) + : "cc" + ); + + return r; +} + +static OF_INLINE bool +OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p, + void *_Nullable o, void *_Nullable n) +{ + int r; + + __asm__ __volatile__ ( + "lock\n\t" + "cmpxchg %2, %3\n\t" + "sete %b0\n\t" + "movzbl %b0, %0" + : "=&d"(r), "+a"(o) /* use d instead of r to avoid a gcc bug */ + : "r"(n), "m"(*p) + : "cc" + ); + + return r; +} + +static OF_INLINE void +OFMemoryBarrier(void) +{ + __asm__ __volatile__ ( + "mfence" ::: "memory" + ); +} + +static OF_INLINE void +OFAcquireMemoryBarrier(void) +{ + __asm__ __volatile__ ("" ::: "memory"); +} + +static OF_INLINE void +OFReleaseMemoryBarrier(void) +{ + __asm__ __volatile__ ("" ::: "memory"); +} + +OF_ASSUME_NONNULL_END