|
Packit Service |
310c69 |
/*
|
|
Packit Service |
310c69 |
* Copyright (c) 2020 Red Hat, Inc.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* This program is free software; you can redistribute it and/or
|
|
Packit Service |
310c69 |
* modify it under the terms of the GNU General Public License
|
|
Packit Service |
310c69 |
* as published by the Free Software Foundation; either version 2
|
|
Packit Service |
310c69 |
* of the License, or (at your option) any later version.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* This program is distributed in the hope that it will be useful,
|
|
Packit Service |
310c69 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
310c69 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
310c69 |
* GNU General Public License for more details.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* You should have received a copy of the GNU General Public License
|
|
Packit Service |
310c69 |
* along with this program; if not, write to the Free Software
|
|
Packit Service |
310c69 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
Packit Service |
310c69 |
* 02110-1301, USA.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* $Id: //eng/vdo-releases/aluminum/src/c++/vdo/base/atomic.h#2 $
|
|
Packit Service |
310c69 |
*/
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
#ifndef ATOMIC_H
|
|
Packit Service |
310c69 |
#define ATOMIC_H
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
#include "atomicDefs.h"
|
|
Packit Service |
310c69 |
#include "compiler.h"
|
|
Packit Service |
310c69 |
#include "typeDefs.h"
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
#define ATOMIC_INITIALIZER(value) { (value) }
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
typedef struct {
|
|
Packit Service |
310c69 |
atomic_t value;
|
|
Packit Service |
310c69 |
} __attribute__((aligned(4))) Atomic32;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
typedef struct {
|
|
Packit Service |
310c69 |
atomic64_t value;
|
|
Packit Service |
310c69 |
} __attribute__((aligned(8))) Atomic64;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
typedef struct {
|
|
Packit Service |
310c69 |
Atomic32 value;
|
|
Packit Service |
310c69 |
} __attribute__((aligned(4))) AtomicBool;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Memory load operations that precede this fence will be prevented from
|
|
Packit Service |
310c69 |
* changing order with any that follow this fence, by either the compiler or
|
|
Packit Service |
310c69 |
* the CPU. This can be used to ensure that the load operations accessing
|
|
Packit Service |
310c69 |
* the fields of a structure are not re-ordered so they actually take effect
|
|
Packit Service |
310c69 |
* before a pointer to the structure is resolved.
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE void loadFence(void)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
smp_rmb();
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Memory store operations that precede this fence will be prevented from
|
|
Packit Service |
310c69 |
* changing order with any that follow this fence, by either the compiler or
|
|
Packit Service |
310c69 |
* the CPU. This can be used to ensure that the store operations initializing
|
|
Packit Service |
310c69 |
* the fields of a structure are not re-ordered so they actually take effect
|
|
Packit Service |
310c69 |
* after a pointer to the structure is published.
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE void storeFence(void)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
smp_wmb();
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Generate a full memory fence for the compiler and CPU. Load and store
|
|
Packit Service |
310c69 |
* operations issued before the fence will not be re-ordered with operations
|
|
Packit Service |
310c69 |
* issued after the fence.
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE void memoryFence(void)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
smp_mb();
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Access the value of a 32-bit atomic variable, ensuring that the load is not
|
|
Packit Service |
310c69 |
* re-ordered by the compiler or CPU with any subsequent load operations.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param atom a pointer to the atomic variable to access
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return the value that was in the atom at the moment it was accessed
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE uint32_t atomicLoad32(const Atomic32 *atom)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
uint32_t value = atomic_read(&atom->value);
|
|
Packit Service |
310c69 |
loadFence();
|
|
Packit Service |
310c69 |
return value;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Access the value of a 64-bit atomic variable, ensuring that the memory load
|
|
Packit Service |
310c69 |
* is not re-ordered by the compiler or CPU with any subsequent load
|
|
Packit Service |
310c69 |
* operations.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param atom a pointer to the atomic variable to access
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return the value that was in the atom at the moment it was accessed
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE uint64_t atomicLoad64(const Atomic64 *atom)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
uint64_t value = atomic64_read(&atom->value);
|
|
Packit Service |
310c69 |
loadFence();
|
|
Packit Service |
310c69 |
return value;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Access the value of a boolean atomic variable, ensuring that the load is not
|
|
Packit Service |
310c69 |
* re-ordered by the compiler or CPU with any subsequent load operations.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param atom a pointer to the atomic variable to access
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return the value that was in the atom at the moment it was accessed
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE bool atomicLoadBool(const AtomicBool *atom)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return (atomicLoad32(&atom->value) > 0);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Set the value of a 32-bit atomic variable, ensuring that the memory store
|
|
Packit Service |
310c69 |
* operation is not re-ordered by the compiler or CPU with any preceding store
|
|
Packit Service |
310c69 |
* operations.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param atom a pointer to the atomic variable to modify
|
|
Packit Service |
310c69 |
* @param newValue the value to assign to the atomic variable
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE void atomicStore32(Atomic32 *atom, uint32_t newValue)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
storeFence();
|
|
Packit Service |
310c69 |
atomic_set(&atom->value, newValue);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Set the value of a 64-bit atomic variable, ensuring that the memory store
|
|
Packit Service |
310c69 |
* operation is not re-ordered by the compiler or CPU with any preceding store
|
|
Packit Service |
310c69 |
* operations.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param atom a pointer to the atomic variable to modify
|
|
Packit Service |
310c69 |
* @param newValue the value to assign to the atomic variable
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE void atomicStore64(Atomic64 *atom, uint64_t newValue)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
storeFence();
|
|
Packit Service |
310c69 |
atomic64_set(&atom->value, newValue);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Set the value of a boolean atomic variable, ensuring that the memory store
|
|
Packit Service |
310c69 |
* operation is not re-ordered by the compiler or CPU with any preceding store
|
|
Packit Service |
310c69 |
* operations.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param atom a pointer to the atomic variable to modify
|
|
Packit Service |
310c69 |
* @param newValue the value to assign to the atomic variable
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE void atomicStoreBool(AtomicBool *atom, bool newValue)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
atomicStore32(&atom->value, (newValue ? 1 : 0));
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Add a 32-bit signed delta to a 32-bit atomic variable.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param atom a pointer to the atomic variable
|
|
Packit Service |
310c69 |
* @param delta the value to be added (or subtracted) from the variable
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return the new value of the atom after the add operation
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE uint32_t atomicAdd32(Atomic32 *atom, int32_t delta)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return atomic_add_return(delta, &atom->value);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Add a 64-bit signed delta to a 64-bit atomic variable.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param atom a pointer to the atomic variable
|
|
Packit Service |
310c69 |
* @param delta the value to be added (or subtracted) from the variable
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return the new value of the atom after the add operation
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE uint64_t atomicAdd64(Atomic64 *atom, int64_t delta)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return atomic64_add_return(delta, &atom->value);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Atomic 32-bit compare-and-swap. If the atom is identical to a required
|
|
Packit Service |
310c69 |
* value, atomically replace it with the new value and return true, otherwise
|
|
Packit Service |
310c69 |
* do nothing and return false.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param atom a pointer to the atomic variable
|
|
Packit Service |
310c69 |
* @param requiredValue the value that must be present to perform the swap
|
|
Packit Service |
310c69 |
* @param newValue the value to be swapped for the required value
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return true if the atom was changed, false otherwise
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE bool compareAndSwap32(Atomic32 *atom,
|
|
Packit Service |
310c69 |
uint32_t requiredValue,
|
|
Packit Service |
310c69 |
uint32_t newValue)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
/*
|
|
Packit Service |
310c69 |
* Our initial implementation, for x86, effectively got a full
|
|
Packit Service |
310c69 |
* memory barrier because of how "lock cmpxchg" operates. The
|
|
Packit Service |
310c69 |
* atomic_cmpxchg interface provides for a full barrier *if* the
|
|
Packit Service |
310c69 |
* exchange is done, but not necessarily if it is not.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* Do we need the full barrier always? We need to investigate that,
|
|
Packit Service |
310c69 |
* as part of (eventually) converting to using that API directly.
|
|
Packit Service |
310c69 |
* For now, play it safe, and ensure the same behavior on other
|
|
Packit Service |
310c69 |
* architectures too.
|
|
Packit Service |
310c69 |
*/
|
|
Packit Service |
310c69 |
#ifndef __x86_64__
|
|
Packit Service |
310c69 |
smp_mb();
|
|
Packit Service |
310c69 |
#endif
|
|
Packit Service |
310c69 |
int oldValue = atomic_cmpxchg(&atom->value, requiredValue, newValue);
|
|
Packit Service |
310c69 |
#ifndef __x86_64__
|
|
Packit Service |
310c69 |
smp_mb();
|
|
Packit Service |
310c69 |
#endif
|
|
Packit Service |
310c69 |
return requiredValue == (uint32_t) oldValue;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Atomic 64-bit compare-and-swap. If the atom is identical to a required
|
|
Packit Service |
310c69 |
* value, atomically replace it with the new value and return true, otherwise
|
|
Packit Service |
310c69 |
* do nothing and return false.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param atom a pointer to the atomic variable
|
|
Packit Service |
310c69 |
* @param requiredValue the value that must be present to perform the swap
|
|
Packit Service |
310c69 |
* @param newValue the value to be swapped for the required value
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return true if the atom was changed, false otherwise
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE bool compareAndSwap64(Atomic64 *atom,
|
|
Packit Service |
310c69 |
uint64_t requiredValue,
|
|
Packit Service |
310c69 |
uint64_t newValue)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
#ifndef __x86_64__
|
|
Packit Service |
310c69 |
smp_mb();
|
|
Packit Service |
310c69 |
#endif
|
|
Packit Service |
310c69 |
long oldValue = atomic64_cmpxchg(&atom->value, requiredValue, newValue);
|
|
Packit Service |
310c69 |
#ifndef __x86_64__
|
|
Packit Service |
310c69 |
smp_mb();
|
|
Packit Service |
310c69 |
#endif
|
|
Packit Service |
310c69 |
return requiredValue == (uint64_t) oldValue;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Atomic boolean compare-and-swap. If the atom is identical to a required
|
|
Packit Service |
310c69 |
* value, atomically replace it with the new value and return true, otherwise
|
|
Packit Service |
310c69 |
* do nothing and return false.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param atom a pointer to the atomic variable
|
|
Packit Service |
310c69 |
* @param requiredValue the value that must be present to perform the swap
|
|
Packit Service |
310c69 |
* @param newValue the value to be swapped for the required value
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return true if the atom was changed, false otherwise
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE bool compareAndSwapBool(AtomicBool *atom,
|
|
Packit Service |
310c69 |
bool requiredValue,
|
|
Packit Service |
310c69 |
bool newValue)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return compareAndSwap32(&atom->value, (requiredValue ? 1 : 0),
|
|
Packit Service |
310c69 |
(newValue ? 1 : 0));
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Access the value of a 32-bit atomic variable using relaxed memory order,
|
|
Packit Service |
310c69 |
* without any compiler or CPU fences.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param atom a pointer to the atomic variable to access
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return the value that was in the atom at the moment it was accessed
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE uint32_t relaxedLoad32(const Atomic32 *atom)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return atomic_read(&atom->value);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Access the value of a 64-bit atomic variable using relaxed memory order,
|
|
Packit Service |
310c69 |
* without any compiler or CPU fences.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param atom a pointer to the atomic variable to access
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return the value that was in the atom at the moment it was accessed
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE uint64_t relaxedLoad64(const Atomic64 *atom)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return atomic64_read(&atom->value);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Access the value of a boolean atomic variable using relaxed memory order,
|
|
Packit Service |
310c69 |
* without any compiler or CPU fences.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param atom a pointer to the atomic variable to access
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return the value that was in the atom at the moment it was accessed
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE bool relaxedLoadBool(const AtomicBool *atom)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return (relaxedLoad32(&atom->value) > 0);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Set the value of a 32-bit atomic variable using relaxed memory order,
|
|
Packit Service |
310c69 |
* without any compiler or CPU fences.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param atom a pointer to the atomic variable to modify
|
|
Packit Service |
310c69 |
* @param newValue the value to assign to the atomic variable
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE void relaxedStore32(Atomic32 *atom, uint32_t newValue)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
atomic_set(&atom->value, newValue);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Set the value of a 64-bit atomic variable using relaxed memory order,
|
|
Packit Service |
310c69 |
* without any compiler or CPU fences.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param atom a pointer to the atomic variable to modify
|
|
Packit Service |
310c69 |
* @param newValue the value to assign to the atomic variable
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE void relaxedStore64(Atomic64 *atom, uint64_t newValue)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
atomic64_set(&atom->value, newValue);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Set the value of a boolean atomic variable using relaxed memory order,
|
|
Packit Service |
310c69 |
* without any compiler or CPU fences.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param atom a pointer to the atomic variable to modify
|
|
Packit Service |
310c69 |
* @param newValue the value to assign to the atomic variable
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE void relaxedStoreBool(AtomicBool *atom, bool newValue)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
relaxedStore32(&atom->value, (newValue ? 1 : 0));
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Non-atomically add a 32-bit signed delta to a 32-bit atomic variable,
|
|
Packit Service |
310c69 |
* without any compiler or CPU fences.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param atom a pointer to the atomic variable
|
|
Packit Service |
310c69 |
* @param delta the value to be added (or subtracted) from the variable
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return the new value of the atom after the add operation
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE uint32_t relaxedAdd32(Atomic32 *atom, int32_t delta)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
uint32_t newValue = (relaxedLoad32(atom) + delta);
|
|
Packit Service |
310c69 |
relaxedStore32(atom, newValue);
|
|
Packit Service |
310c69 |
return newValue;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Non-atomically add a 64-bit signed delta to a 64-bit atomic variable,
|
|
Packit Service |
310c69 |
* without any compiler or CPU fences.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param atom a pointer to the atomic variable
|
|
Packit Service |
310c69 |
* @param delta the value to be added (or subtracted) from the variable
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return the new value of the atom after the add operation
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE uint64_t relaxedAdd64(Atomic64 *atom, int64_t delta)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
uint64_t newValue = (relaxedLoad64(atom) + delta);
|
|
Packit Service |
310c69 |
relaxedStore64(atom, newValue);
|
|
Packit Service |
310c69 |
return newValue;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
#endif /* ATOMIC_H */
|