1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/sys/include/volatile_utils.h
Marian Buschsieweke 8b0007f33a
sys/atomic_utils: return previous value
Update the `atomic_fetch_<OPERATION>_u<WIDTH>()` functions to return the old
value the target contained prior to applying the operation. This makes this
API much more versatile and closer to C11 atomics.
2020-12-16 18:09:35 +01:00

356 lines
10 KiB
C

/*
* Copyright (C) 2020 Otto-von-Guericke-Universität Magdeburg
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @defgroup sys_atomic_utils_volatile Helpers for volatile accesses
* @ingroup sys_atomic_utils
* @{
*
* @file
* @brief Utility functions for non-atomic but volatile access
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
*
* This functions intentionally have the same signature as the
* @ref sys_atomic_utils but don't guarantee atomic access and sequential
* consistency (or any other consistency). They basically only guarantee that
* no compiler optimization is applied to that operation and that the compiler
* will not reorder these operations in regard to each other or other `volatile`
* accesses.
*
* @warning In most cases using this over @ref sys_atomic_utils is a bug!
*/
#ifndef VOLATILE_UTILS_H
#define VOLATILE_UTILS_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Load an 8 bit value completely unoptimized
* @param var Address to load the value from
* @return The value read unoptimized from address @p var
*/
static inline uint8_t volatile_load_u8(const volatile uint8_t *var)
{
return *var;
}
/**
* @brief Load an 16 bit value completely unoptimized
* @param var Address to load the value from
* @return The value read unoptimized from address @p var
*/
static inline uint16_t volatile_load_u16(const volatile uint16_t *var)
{
return *var;
}
/**
* @brief Load an 32 bit value completely unoptimized
* @param var Address to load the value from
* @return The value read unoptimized from address @p var
*/
static inline uint32_t volatile_load_u32(const volatile uint32_t *var)
{
return *var;
}
/**
* @brief Load an 64 bit value completely unoptimized
* @param var Address to load the value from
* @return The value read unoptimized from address @p var
*/
static inline uint64_t volatile_load_u64(const volatile uint64_t *var)
{
return *var;
}
/**
* @brief Store an 8 bit value completely unoptimized
* @param dest Address to write the given value unoptimized to
* @param val Value to write unoptimized
*/
static inline void volatile_store_u8(volatile uint8_t *dest, uint8_t val)
{
*dest = val;
}
/**
* @brief Store a 16 bit value completely unoptimized
* @param dest Address to write the given value unoptimized to
* @param val Value to write unoptimized
*/
static inline void volatile_store_u16(volatile uint16_t *dest, uint16_t val)
{
*dest = val;
}
/**
* @brief Store a 32 bit value completely unoptimized
* @param dest Address to write the given value unoptimized to
* @param val Value to write unoptimized
*/
static inline void volatile_store_u32(volatile uint32_t *dest, uint32_t val)
{
*dest = val;
}
/**
* @brief Store a 64 bit value completely unoptimized
* @param dest Address to write the given value unoptimized to
* @param val Value to write unoptimized
*/
static inline void volatile_store_u64(volatile uint64_t *dest, uint64_t val)
{
*dest = val;
}
/**
* @brief Unoptimized version of `*dest += val`
* @param dest Address of the value to add to
* @param val Value to add
*/
static inline uint8_t volatile_fetch_add_u8(volatile uint8_t *dest, uint8_t val)
{
uint8_t result = *dest;
*dest = result + val;
return result;
}
/**
* @brief Unoptimized version of `*dest -= val`
* @param dest Address of the value to apply the operation on
* @param val Second operand
*/
static inline uint8_t volatile_fetch_sub_u8(volatile uint8_t *dest, uint8_t val)
{
uint8_t result = *dest;
*dest = result - val;
return result;
}
/**
* @brief Unoptimized version of `*dest |= val`
* @param dest Address of the value to apply the operation on
* @param val Second operand
*/
static inline uint8_t volatile_fetch_or_u8(volatile uint8_t *dest, uint8_t val)
{
uint8_t result = *dest;
*dest = result | val;
return result;
}
/**
* @brief Unoptimized version of `*dest ^= val`
* @param dest Address of the value to apply the operation on
* @param val Second operand
*/
static inline uint8_t volatile_fetch_xor_u8(volatile uint8_t *dest, uint8_t val)
{
uint8_t result = *dest;
*dest = result ^ val;
return result;
}
/**
* @brief Unoptimized version of `*dest &= val`
* @param dest Address of the value to apply the operation on
* @param val Second operand
*/
static inline uint8_t volatile_fetch_and_u8(volatile uint8_t *dest, uint8_t val)
{
uint8_t result = *dest;
*dest = result & val;
return result;
}
/**
* @brief Unoptimized version of `*dest += val`
* @param dest Address of the value to add to
* @param val Value to add
*/
static inline uint16_t volatile_fetch_add_u16(volatile uint16_t *dest,
uint16_t val)
{
uint16_t result = *dest;
*dest = result + val;
return result;
}
/**
* @brief Unoptimized version of `*dest -= val`
* @param dest Address of the value to apply the operation on
* @param val Second operand
*/
static inline uint16_t volatile_fetch_sub_u16(volatile uint16_t *dest,
uint16_t val)
{
uint16_t result = *dest;
*dest = result - val;
return result;
}
/**
* @brief Unoptimized version of `*dest |= val`
* @param dest Address of the value to apply the operation on
* @param val Second operand
*/
static inline uint16_t volatile_fetch_or_u16(volatile uint16_t *dest,
uint16_t val)
{
uint16_t result = *dest;
*dest = result | val;
return result;
}
/**
* @brief Unoptimized version of `*dest ^= val`
* @param dest Address of the value to apply the operation on
* @param val Second operand
*/
static inline uint16_t volatile_fetch_xor_u16(volatile uint16_t *dest,
uint16_t val)
{
uint16_t result = *dest;
*dest = result ^ val;
return result;
}
/**
* @brief Unoptimized version of `*dest &= val`
* @param dest Address of the value to apply the operation on
* @param val Second operand
*/
static inline uint16_t volatile_fetch_and_u16(volatile uint16_t *dest,
uint16_t val)
{
uint16_t result = *dest;
*dest = result & val;
return result;
}
/**
* @brief Unoptimized version of `*dest += val`
* @param dest Address of the value to add to
* @param val Value to add
*/
static inline uint32_t volatile_fetch_add_u32(volatile uint32_t *dest,
uint32_t val)
{
uint32_t result = *dest;
*dest = result + val;
return result;
}
/**
* @brief Unoptimized version of `*dest -= val`
* @param dest Address of the value to apply the operation on
* @param val Second operand
*/
static inline uint32_t volatile_fetch_sub_u32(volatile uint32_t *dest,
uint32_t val)
{
uint32_t result = *dest;
*dest = result - val;
return result;
}
/**
* @brief Unoptimized version of `*dest |= val`
* @param dest Address of the value to apply the operation on
* @param val Second operand
*/
static inline uint32_t volatile_fetch_or_u32(volatile uint32_t *dest,
uint32_t val)
{
uint32_t result = *dest;
*dest = result | val;
return result;
}
/**
* @brief Unoptimized version of `*dest ^= val`
* @param dest Address of the value to apply the operation on
* @param val Second operand
*/
static inline uint32_t volatile_fetch_xor_u32(volatile uint32_t *dest,
uint32_t val)
{
uint32_t result = *dest;
*dest = result ^ val;
return result;
}
/**
* @brief Unoptimized version of `*dest &= val`
* @param dest Address of the value to apply the operation on
* @param val Second operand
*/
static inline uint32_t volatile_fetch_and_u32(volatile uint32_t *dest,
uint32_t val)
{
uint32_t result = *dest;
*dest = result & val;
return result;
}
/**
* @brief Unoptimized version of `*dest += val`
* @param dest Address of the value to add to
* @param val Value to add
*/
static inline uint64_t volatile_fetch_add_u64(volatile uint64_t *dest,
uint64_t val)
{
uint64_t result = *dest;
*dest = result + val;
return result;
}
/**
* @brief Unoptimized version of `*dest -= val`
* @param dest Address of the value to apply the operation on
* @param val Second operand
*/
static inline uint64_t volatile_fetch_sub_u64(volatile uint64_t *dest,
uint64_t val)
{
uint64_t result = *dest;
*dest = result - val;
return result;
}
/**
* @brief Unoptimized version of `*dest |= val`
* @param dest Address of the value to apply the operation on
* @param val Second operand
*/
static inline uint64_t volatile_fetch_or_u64(volatile uint64_t *dest,
uint64_t val)
{
uint64_t result = *dest;
*dest = result | val;
return result;
}
/**
* @brief Unoptimized version of `*dest ^= val`
* @param dest Address of the value to apply the operation on
* @param val Second operand
*/
static inline uint64_t volatile_fetch_xor_u64(volatile uint64_t *dest,
uint64_t val)
{
uint64_t result = *dest;
*dest = result ^ val;
return result;
}
/**
* @brief Unoptimized version of `*dest &= val`
* @param dest Address of the value to apply the operation on
* @param val Second operand
*/
static inline uint64_t volatile_fetch_and_u64(volatile uint64_t *dest,
uint64_t val)
{
uint64_t result = *dest;
*dest = result & val;
return result;
}
#ifdef __cplusplus
}
#endif
#endif /* VOLATILE_UTILS_H */
/** @} */