* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
#include <isc/platform.h>
#ifdef ISC_PLATFORM_USEGCCASM
* This routine atomically increments the value stored in 'p' by 'val', and
* returns the previous value.
static __inline__ int32_t
isc_atomic_xadd(int32_t *p, int32_t val) {
#ifdef ISC_PLATFORM_USETHREADS
#ifdef ISC_PLATFORM_HAVEXADDQ
static __inline__ int64_t
isc_atomic_xaddq(int64_t *p, int64_t val) {
#ifdef ISC_PLATFORM_USETHREADS
#endif /* ISC_PLATFORM_HAVEXADDQ */
* This routine atomically stores the value 'val' in 'p' (32-bit version).
isc_atomic_store(int32_t *p, int32_t val) {
#ifdef ISC_PLATFORM_USETHREADS
* xchg should automatically lock memory, but we add it
* explicitly just in case (it at least doesn't harm)
#ifdef ISC_PLATFORM_HAVEATOMICSTOREQ
* This routine atomically stores the value 'val' in 'p' (64-bit version).
isc_atomic_storeq(int64_t *p, int64_t val) {
#ifdef ISC_PLATFORM_USETHREADS
* xchg should automatically lock memory, but we add it
* explicitly just in case (it at least doesn't harm)
#endif /* ISC_PLATFORM_HAVEATOMICSTOREQ */
* This routine atomically replaces the value in 'p' with 'val', if the
* original value is equal to 'cmpval'. The original value is returned in any
static __inline__ int32_t
isc_atomic_cmpxchg(int32_t *p, int32_t cmpval, int32_t val) {
#ifdef ISC_PLATFORM_USETHREADS
: "r"(val), "m"(*p), "a"(cmpval)
#elif defined(ISC_PLATFORM_USESTDASM)
* The following are "generic" assembly code which implements the same
* functionality in case the gcc extension cannot be used. It should be
* better to avoid inlining below, since we directly refer to specific
* positions of the stack frame, which would not actually point to the
* intended address in the embedded mnemonic.
isc_atomic_xadd(int32_t *p, int32_t val) {
#ifdef ISC_PLATFORM_USETHREADS
* set the return value directly in the register so that we
* can avoid guessing the correct position in the stack for a
isc_atomic_store(int32_t *p, int32_t val) {
#ifdef ISC_PLATFORM_USETHREADS
isc_atomic_cmpxchg(int32_t *p, int32_t cmpval, int32_t val) {
"movl 12(%ebp), %eax\n" /* must be %eax for cmpxchgl */
#ifdef ISC_PLATFORM_USETHREADS
* If (%ecx) == %eax then (%ecx) := %edx.
% %eax is set to old (%ecx), which will be the return value.
#else /* !ISC_PLATFORM_USEGCCASM && !ISC_PLATFORM_USESTDASM */
#error "unsupported compiler. disable atomic ops by --disable-atomic"
#endif /* ISC_ATOMIC_H */