Merge pull request #2321 from gebart/pr/atomic-counters

core: Atomic counters
dev/timer
Oleg Hahm 8 years ago
commit 021226fcbe

@ -0,0 +1,59 @@
/*
* Copyright (C) 2014 Freie Universität Berlin
* Copyright (C) 2015 Eistec AB
*
* 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.
*/
/**
* @ingroup core_util
* @{
*
* @file
* @brief Generic implementation of the kernel's atomic interface
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
* @author Oliver Hahm <oliver.hahm@inria.fr>
* @author Joakim Gebart <joakim.gebart@eistec.se>
*
* @}
*/
#include "irq.h"
#include "cpu.h"
#include "atomic.h"
#if (ARCH_HAS_ATOMIC_SET_RETURN == 0)
unsigned int atomic_set_return(unsigned int *val, unsigned int set)
{
unsigned int mask = disableIRQ();
unsigned int old_val = *val;
*val = set;
restoreIRQ(mask);
return old_val;
}
#endif
/* Set ARCH_HAS_ATOMIC_COMPARE_AND_SWAP within cpu.h to override this function */
#if (ARCH_HAS_ATOMIC_COMPARE_AND_SWAP == 0)
int atomic_cas(atomic_int_t *var, int old, int now)
{
unsigned int mask = disableIRQ();
if (ATOMIC_VALUE(*var) != old) {
restoreIRQ(mask);
return 0;
}
ATOMIC_VALUE(*var) = now;
restoreIRQ(mask);
return 1;
}
#endif

@ -1,5 +1,6 @@
/*
* Copyright (C) 2014 Freie Universität Berlin
* Copyright (C) 2015 Eistec AB
*
* 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
@ -10,21 +11,31 @@
* @addtogroup core_util
* @{
*
* @file atomic.h
* @brief Atomic getter and setter functions
* @file
* @brief Functions for atomic handling of variables
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
* @author Joakim Gebart <joakim.gebart@eistec.se>
*/
#ifndef _ATOMIC_H
#define _ATOMIC_H
#ifndef ATOMIC_H_
#define ATOMIC_H_
#include "arch/atomic_arch.h"
#ifdef __cplusplus
extern "C" {
extern "C" {
#endif
/**
* @brief Integer variable for use in atomic counters.
*/
typedef struct atomic_int {
volatile int value;
} atomic_int_t;
/**
* @brief Sets a new and returns the old value of a variable atomically
*
@ -35,9 +46,119 @@
*/
unsigned int atomic_set_return(unsigned int *val, unsigned int set);
/**
* @brief Initializer for atomic variables
*
* @param[in] val initial value for the atomic integer
*/
#define ATOMIC_INIT(val) {(val)}
/**
* @brief Atomic Compare and Swap
*
* Updates the value in var iff the current value of var is equal to old.
*
* @param[inout] var Atomic variable to update
* @param[in] old The old value to compare against
* @param[in] now The new value to write to var
*
* @return 1 if the write completed successfully
* @return 0 if the write failed.
*/
int atomic_cas(atomic_int_t *var, int old, int now);
/**
* @brief Increment a counter variable by one atomically and return the old value.
*
* @param[inout] var Pointer to a counter variable.
*
* @return The value of *val* before the increment.
*/
static inline int atomic_inc(atomic_int_t *var)
{
int old;
do {
old = var->value;
} while (!atomic_cas(var, old, old + 1));
return old;
}
/**
* @brief Decrement a counter variable by one atomically and return the old value.
*
* @param[inout] var Pointer to a counter variable.
*
* @return The value of *val* before the decrement.
*/
static inline int atomic_dec(atomic_int_t *var)
{
int old;
do {
old = var->value;
} while (!atomic_cas(var, old, old - 1));
return old;
}
/**
* @brief Set an atomic variable to 1.
*
* @param[inout] var Pointer to an atomic variable to update
*
* @return 1 if the old value was 0 and the variable was successfully updated
* @return 0 if the variable was already set
*/
static inline int atomic_set_to_one(atomic_int_t *var)
{
do {
if (var->value != 0) {
return 0;
}
} while (!atomic_cas(var, 0, 1));
return 1;
}
/**
* @brief Set an atomic variable to 0.
*
* @param[inout] var Pointer to an atomic variable to update
*
* @return 1 if the old value was not 0 and the variable was successfully updated
* @return 0 if the variable was already cleared
*/
static inline int atomic_set_to_zero(atomic_int_t *var)
{
int old;
do {
old = var->value;
if (old == 0) {
return 0;
}
} while (!atomic_cas(var, old, 0));
return 1;
}
/**
* @brief Get the value of an atomic int
*
* @param[in] var Atomic variable
*
* @return the value of the atomic integer
*
* @note This can be used for non-thread-safe assignment of the atomic integer
*/
#define ATOMIC_VALUE(var) ((var).value)
#ifdef __cplusplus
}
#endif
#endif /* _ATOMIC_H */
#endif /* ATOMIC_H_ */
/** @} */

@ -6,8 +6,8 @@
* directory for more details.
*/
#ifndef _ARM_CPU_H
#define _ARM_CPU_H
#ifndef ARM_CPU_H_
#define ARM_CPU_H_
#include <stdint.h>
#include "VIC.h"
@ -17,6 +17,11 @@
extern "C" {
#endif
/**
* @brief ARM has architecture specific atomic_set_return in atomic.s
*/
#define ARCH_HAS_ATOMIC_SET_RETURN 1
#define NEW_TASK_CPSR 0x1F
#define WORDSIZE 32
@ -44,4 +49,4 @@ int uart0_puts(char *astring, int length);
}
#endif
#endif // _ARM_CPU_H
#endif /* ARM_CPU_H_ */

@ -1,33 +0,0 @@
/*
* Copyright (C) 2014 Freie Universität Berlin, Hinnerk van Bruinehsen
*
* 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.
*/
/**
* @ingroup cpu_atmega_common
* @{
*
* @file atomic_arch.c
* @brief Implementation of the kernels atomic interface
*
* @author Stefan Pfeiffer <stefan.pfeiffer@fu-berlin.de>
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
* @author Hinnerk van Bruinehsen <h.v.bruinehsen@fu-berlin.de>
*
* @}
*/
#include "arch/atomic_arch.h"
#include "irq.h"
unsigned int atomic_arch_set_return(unsigned int *to_set, unsigned int value)
{
disableIRQ();
unsigned int old = *to_set;
*to_set = value;
enableIRQ();
return old;
}

@ -1,33 +0,0 @@
/*
* Copyright (C) 2014 Freie Universität Berlin
*
* 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.
*/
/**
* @ingroup cpu_cortexm0_common
* @{
*
* @file
* @brief Implementation of the kernels atomic interface
*
* @author Stefan Pfeiffer <stefan.pfeiffer@fu-berlin.de>
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*
* @}
*/
#include "arch/atomic_arch.h"
#include "irq.h"
unsigned int atomic_arch_set_return(unsigned int *to_set, unsigned int value)
{
disableIRQ();
unsigned int old = *to_set;
*to_set = value;
enableIRQ();
return old;
}

@ -7,26 +7,40 @@
*/
/**
* @ingroup cpu_cortex-m3
* @ingroup cpu_cortexm3_common
* @{
*
* @file atomic_arch.c
* @file
* @brief Implementation of the kernels atomic interface
*
* @author Stefan Pfeiffer <stefan.pfeiffer@fu-berlin.de>
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
* @author Joakim Gebart <joakim.gebart@eistec.se>
*
* @}
*/
#include "arch/atomic_arch.h"
#include <stdint.h>
#include "atomic.h"
#include "irq.h"
#include "cpu.h"
unsigned int atomic_arch_set_return(unsigned int *to_set, unsigned int value)
int atomic_cas(atomic_int_t *var, int old, int now)
{
disableIRQ();
unsigned int old = *to_set;
*to_set = value;
enableIRQ();
return old;
int tmp;
int status;
/* Load exclusive */
tmp = __LDREXW((volatile uint32_t *)(&ATOMIC_VALUE(*var)));
if (tmp != old) {
/* Clear memory exclusivity */
__CLREX();
return 0;
}
/* Try to write the new value */
status = __STREXW(now, (volatile uint32_t *)(&ATOMIC_VALUE(*var)));
return (status == 0);
}

@ -1,5 +0,0 @@
/**
* @defgroup cpu_cortex-m3 Cortex-M3 common
* @brief ARM Cortex-M specific code
* @ingroup cpu
*/

@ -7,7 +7,9 @@
*/
/**
* @addtogroup cpu_cortex-m3
* @defgroup cpu_cortexm3_common ARM Cortex-M3 common
* @ingroup cpu
* @brief Common implementations and headers for Cortex-M3 family based micro-controllers
* @{
*
* @file
@ -18,10 +20,16 @@
*
* @author Stefan Pfeiffer <stefan.pfeiffer@fu-berlin.de>
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
* @author Joakim Gebart <joakim.gebart@eistec.se>
*/
#ifndef __CORTEXM_COMMON_H
#define __CORTEXM_COMMON_H
#ifndef CORTEXM_COMMON_H_
#define CORTEXM_COMMON_H_
/**
* @brief Cortex-M3 has architecture specific atomic operations in atomic_arch.c.
*/
#define ARCH_HAS_ATOMIC_COMPARE_AND_SWAP 1
#include "cpu-conf.h"
@ -47,5 +55,5 @@ void cpu_init(void);
}
#endif
#endif /* __CORTEXM_COMMON_H */
#endif /* CORTEXM_COMMON_H_ */
/** @} */

@ -7,7 +7,7 @@
*/
/**
* @ingroup cpu_cortex-m3
* @ingroup cpu_cortexm3_common
* @{
*
* @file irq_arch.c

@ -7,7 +7,7 @@
*/
/**
* @ingroup cpu_cortex-m3
* @ingroup cpu_cortexm3_common
* @{
*
* @file thread_arch.c

@ -15,18 +15,32 @@
*
* @author Stefan Pfeiffer <stefan.pfeiffer@fu-berlin.de>
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
* @author Joakim Gebart <joakim.gebart@eistec.se>
*
* @}
*/
#include "arch/atomic_arch.h"
#include <stdint.h>
#include "atomic.h"
#include "irq.h"
#include "cpu.h"
unsigned int atomic_arch_set_return(unsigned int *to_set, unsigned int value)
int atomic_cas(atomic_int_t *var, int old, int now)
{
disableIRQ();
unsigned int old = *to_set;
*to_set = value;
enableIRQ();
return old;
int tmp;
int status;
/* Load exclusive */
tmp = __LDREXW((volatile uint32_t *)(&ATOMIC_VALUE(*var)));
if (tmp != old) {
/* Clear memory exclusivity */
__CLREX();
return 0;
}
/* Try to write the new value */
status = __STREXW(now, (volatile uint32_t *)(&ATOMIC_VALUE(*var)));
return (status == 0);
}

@ -20,10 +20,16 @@
*
* @author Stefan Pfeiffer <stefan.pfeiffer@fu-berlin.de>
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
* @author Joakim Gebart <joakim.gebart@eistec.se>
*/
#ifndef __CORTEXM_COMMON_H
#define __CORTEXM_COMMON_H
#ifndef CORTEXM_COMMON_H_
#define CORTEXM_COMMON_H_
/**
* @brief Cortex-M4 has architecture specific atomic operations in atomic_arch.c.
*/
#define ARCH_HAS_ATOMIC_COMPARE_AND_SWAP 1
#include "cpu-conf.h"
@ -49,5 +55,5 @@ void cpu_init(void);
}
#endif
#endif /* __CORTEXM_COMMON_H */
#endif /* CORTEXM_COMMON_H_ */
/** @} */

@ -1,32 +0,0 @@
/*
* Copyright (C) 2014 Freie Universität Berlin
*
* 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.
*/
/**
* @ingroup cpu
* @{
*
* @file atomic.c
* @brief atomic set and return function
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
* @author Oliver Hahm <oliver.hahm@inria.fr>
*
* @}
*/
#include "atomic.h"
#include "cpu.h"
unsigned int atomic_set_return(unsigned int *val, unsigned int set)
{
dINT();
unsigned int old_val = *val;
*val = set;
eINT();
return old_val;
}

@ -1,36 +0,0 @@
/**
* Native CPU atomic.h implementation
*
* Copyright (C) 2013 Ludwig Ortmann <ludwig.ortmann@fu-berlin.de>
*
* 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.
*
* @ingroup arch
* @{
* @file
* @author Ludwig Ortmann <ludwig.ortmann@fu-berlin.de>
* @}
*/
#include "atomic.h"
#include "irq.h"
#include "debug.h"
unsigned int atomic_set_return(unsigned int *val, unsigned int set)
{
unsigned int old_val;
unsigned int old_state;
DEBUG("atomic_set_return\n");
old_state = disableIRQ();
old_val = *val;
*val = set;
restoreIRQ(old_state);
return old_val;
}

@ -26,8 +26,8 @@
* @author René Kijewski <rene.kijewski@fu-berlin.de>
*/
#ifndef CPU__X86__CPU__H__
#define CPU__X86__CPU__H__
#ifndef CPU_X86_CPU_H_
#define CPU_X86_CPU_H_
#include "attributes.h"
#include "irq.h"
@ -43,6 +43,12 @@
extern "C" {
#endif
/**
* @brief x86 has architecture specific atomic operations in x86_atomic.c.
*/
#define ARCH_HAS_ATOMIC_SET_RETURN 1
#define ARCH_HAS_ATOMIC_COMPARE_AND_SWAP 1
static inline void __attribute__((always_inline)) dINT(void)
{
asm volatile ("cli");

@ -1,5 +1,5 @@
/*
* Copyright (C) 2014 René Kijewski <rene.kijewski@fu-berlin.de>
* Copyright (C) 2014-2015 René Kijewski <rene.kijewski@fu-berlin.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -28,6 +28,7 @@
* @}
*/
#include <stdint.h>
#include "atomic.h"
unsigned int atomic_set_return(unsigned int *val, unsigned int set)
@ -35,3 +36,14 @@ unsigned int atomic_set_return(unsigned int *val, unsigned int set)
asm volatile ("lock xchg %0, %1" : "+m"(*val), "+r"(set));
return set;
}
int atomic_cas(atomic_int_t *dest, int known_value, int new_value)
{
uint8_t successful;
asm volatile ("lock cmpxchgl %2, %0\n"
"seteb %1"
: "+m"(ATOMIC_VALUE(*dest)), "=g"(successful)
: "r"(new_value), "a"(known_value)
: "flags");
return successful;
}

@ -1,5 +1,6 @@
/*
* Copyright (C) 2014 Martine Lenders <mlenders@inf.fu-berlin.de>
* Copyright (C) 2015 Eistec AB
*
* 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
@ -63,6 +64,196 @@ static void test_atomic_set_return_null_random(void)
TEST_ASSERT_EQUAL_INT(r, res);
}
/* Test atomic_set_to_one on a variable set to 0 */
static void test_atomic_set_to_one_zero(void)
{
atomic_int_t res = ATOMIC_INIT(0);
TEST_ASSERT_EQUAL_INT(1, atomic_set_to_one(&res));
TEST_ASSERT_EQUAL_INT(1, ATOMIC_VALUE(res));
}
/* Test atomic_set_to_one on a variable set to 1 */
static void test_atomic_set_to_one_one(void)
{
atomic_int_t res = ATOMIC_INIT(1);
TEST_ASSERT_EQUAL_INT(0, atomic_set_to_one(&res));
TEST_ASSERT_EQUAL_INT(1, ATOMIC_VALUE(res));
}
/* Test atomic_set_to_one twice */
static void test_atomic_set_to_one_twice(void)
{
atomic_int_t res = ATOMIC_INIT(0);
TEST_ASSERT_EQUAL_INT(1, atomic_set_to_one(&res));
TEST_ASSERT_EQUAL_INT(1, ATOMIC_VALUE(res));
TEST_ASSERT_EQUAL_INT(0, atomic_set_to_one(&res));
TEST_ASSERT_EQUAL_INT(1, ATOMIC_VALUE(res));
}
/* Test atomic_set_to_zero on a variable set to 0 */
static void test_atomic_set_to_zero_zero(void)
{
atomic_int_t res = ATOMIC_INIT(0);
TEST_ASSERT_EQUAL_INT(0, atomic_set_to_zero(&res));
TEST_ASSERT_EQUAL_INT(0, ATOMIC_VALUE(res));
}
/* Test atomic_set_to_zero on a variable set to 1 */
static void test_atomic_set_to_zero_one(void)
{
atomic_int_t res = ATOMIC_INIT(1);
TEST_ASSERT_EQUAL_INT(1, atomic_set_to_zero(&res));
TEST_ASSERT_EQUAL_INT(0, ATOMIC_VALUE(res));
}
/* Test atomic_set_to_zero twice */
static void test_atomic_set_to_zero_twice(void)
{
atomic_int_t res = ATOMIC_INIT(1);
TEST_ASSERT_EQUAL_INT(1, atomic_set_to_zero(&res));
TEST_ASSERT_EQUAL_INT(0, ATOMIC_VALUE(res));
TEST_ASSERT_EQUAL_INT(0, atomic_set_to_zero(&res));
TEST_ASSERT_EQUAL_INT(0, ATOMIC_VALUE(res));
}
/* Test atomic_inc */
static void test_atomic_inc_positive(void)
{
atomic_int_t res = ATOMIC_INIT(0);
TEST_ASSERT_EQUAL_INT(0, atomic_inc(&res));
TEST_ASSERT_EQUAL_INT(1, ATOMIC_VALUE(res));
TEST_ASSERT_EQUAL_INT(1, atomic_inc(&res));
TEST_ASSERT_EQUAL_INT(2, ATOMIC_VALUE(res));
ATOMIC_VALUE(res) = 0;
for (int i = 0; i < 512; ++i) {
TEST_ASSERT_EQUAL_INT(i, atomic_inc(&res));
TEST_ASSERT_EQUAL_INT(i + 1, ATOMIC_VALUE(res));
}
}
static void test_atomic_inc_negative(void)
{
atomic_int_t res = ATOMIC_INIT(-99);
for (int i = -99; i < 123; ++i) {
TEST_ASSERT_EQUAL_INT(i, atomic_inc(&res));
TEST_ASSERT_EQUAL_INT(i + 1, ATOMIC_VALUE(res));
}
}
static void test_atomic_inc_rollover(void)
{
atomic_int_t res = ATOMIC_INIT(INT_MAX - 30);
for (int i = 0; i < 30; ++i) {
TEST_ASSERT_EQUAL_INT(INT_MAX - 30 + i, atomic_inc(&res));
TEST_ASSERT_EQUAL_INT(INT_MAX - 30 + i + 1, ATOMIC_VALUE(res));
}
TEST_ASSERT_EQUAL_INT(INT_MAX, atomic_inc(&res));
TEST_ASSERT_EQUAL_INT(INT_MIN, ATOMIC_VALUE(res));
TEST_ASSERT_EQUAL_INT(INT_MIN, atomic_inc(&res));
TEST_ASSERT_EQUAL_INT(INT_MIN + 1, ATOMIC_VALUE(res));
TEST_ASSERT_EQUAL_INT(INT_MIN + 1, atomic_inc(&res));
TEST_ASSERT_EQUAL_INT(INT_MIN + 2, ATOMIC_VALUE(res));
}
/* Test atomic_dec */
static void test_atomic_dec_negative(void)
{
atomic_int_t res = ATOMIC_INIT(0);
TEST_ASSERT_EQUAL_INT(0, atomic_dec(&res));
TEST_ASSERT_EQUAL_INT(-1, ATOMIC_VALUE(res));
TEST_ASSERT_EQUAL_INT(-1, atomic_dec(&res));
TEST_ASSERT_EQUAL_INT(-2, ATOMIC_VALUE(res));
ATOMIC_VALUE(res) = 0;
for (int i = 0; i < 512; ++i) {
TEST_ASSERT_EQUAL_INT(-i, atomic_dec(&res));
TEST_ASSERT_EQUAL_INT(-i - 1, ATOMIC_VALUE(res));
}
}
static void test_atomic_dec_positive(void)
{
atomic_int_t res = ATOMIC_INIT(99);
for (int i = 99; i < -123; --i) {
TEST_ASSERT_EQUAL_INT(i, atomic_dec(&res));
TEST_ASSERT_EQUAL_INT(i - 1, ATOMIC_VALUE(res));
}
}
static void test_atomic_dec_rollover(void)
{
atomic_int_t res = ATOMIC_INIT(INT_MIN + 30);
for (int i = 0; i < 30; ++i) {
TEST_ASSERT_EQUAL_INT(INT_MIN + 30 - i, atomic_dec(&res));
TEST_ASSERT_EQUAL_INT(INT_MIN + 30 - i - 1, ATOMIC_VALUE(res));
}
TEST_ASSERT_EQUAL_INT(INT_MIN, atomic_dec(&res));
TEST_ASSERT_EQUAL_INT(INT_MAX, ATOMIC_VALUE(res));
TEST_ASSERT_EQUAL_INT(INT_MAX, atomic_dec(&res));
TEST_ASSERT_EQUAL_INT(INT_MAX - 1, ATOMIC_VALUE(res));
TEST_ASSERT_EQUAL_INT(INT_MAX - 1, atomic_dec(&res));
TEST_ASSERT_EQUAL_INT(INT_MAX - 2, ATOMIC_VALUE(res));
}
/* Test atomic_cas with a correct old value */
static void test_atomic_cas_same(void)
{
atomic_int_t res = ATOMIC_INIT(0);
TEST_ASSERT_EQUAL_INT(1, atomic_cas(&res, 0, 1234567));
TEST_ASSERT_EQUAL_INT(1234567, ATOMIC_VALUE(res));
TEST_ASSERT_EQUAL_INT(1, atomic_cas(&res, 1234567, -987654321));
TEST_ASSERT_EQUAL_INT(-987654321, ATOMIC_VALUE(res));
TEST_ASSERT_EQUAL_INT(1, atomic_cas(&res, -987654321, -987654321));
TEST_ASSERT_EQUAL_INT(-987654321, ATOMIC_VALUE(res));
TEST_ASSERT_EQUAL_INT(1, atomic_cas(&res, -987654321, 0));
TEST_ASSERT_EQUAL_INT(0, ATOMIC_VALUE(res));
}
/* Test atomic_cas with a non-matching old value */
static void test_atomic_cas_diff(void)
{
atomic_int_t res = ATOMIC_INIT(32767);
TEST_ASSERT_EQUAL_INT(0, atomic_cas(&res, 65535, 12345));
TEST_ASSERT_EQUAL_INT(32767, ATOMIC_VALUE(res));
ATOMIC_VALUE(res) = -12345687;
TEST_ASSERT_EQUAL_INT(0, atomic_cas(&res, 12345687, 123456789));
TEST_ASSERT_EQUAL_INT(-12345687, ATOMIC_VALUE(res));
TEST_ASSERT_EQUAL_INT(0, atomic_cas(&res, 12345687, 12345687));
TEST_ASSERT_EQUAL_INT(-12345687, ATOMIC_VALUE(res));
TEST_ASSERT_EQUAL_INT(0, atomic_cas(&res, 12345687, -12345687));
TEST_ASSERT_EQUAL_INT(-12345687, ATOMIC_VALUE(res));
}
/* Test ATOMIC_VALUE */
static void test_atomic_value(void)
{
atomic_int_t res = ATOMIC_INIT(12345);
atomic_int_t *ptr = &res;
TEST_ASSERT_EQUAL_INT(12345, ATOMIC_VALUE(res));
ATOMIC_VALUE(res) = 54332;
TEST_ASSERT_EQUAL_INT(54332, ATOMIC_VALUE(res));
TEST_ASSERT_EQUAL_INT(54332, res.value);
res.value = 1232342131;
TEST_ASSERT_EQUAL_INT(ATOMIC_VALUE(res), res.value);
TEST_ASSERT_EQUAL_INT(ATOMIC_VALUE(*ptr), res.value);
}
/* ATOMIC_INIT is implicitly tested by the other tests */
Test *tests_core_atomic_tests(void)
{
EMB_UNIT_TESTFIXTURES(fixtures) {
@ -72,6 +263,21 @@ Test *tests_core_atomic_tests(void)
new_TestFixture(test_atomic_set_return_limit_null),
new_TestFixture(test_atomic_set_return_null_limit),
new_TestFixture(test_atomic_set_return_null_random),
new_TestFixture(test_atomic_set_to_one_one),
new_TestFixture(test_atomic_set_to_one_zero),
new_TestFixture(test_atomic_set_to_one_twice),
new_TestFixture(test_atomic_set_to_zero_one),
new_TestFixture(test_atomic_set_to_zero_zero),
new_TestFixture(test_atomic_set_to_zero_twice),
new_TestFixture(test_atomic_inc_positive),
new_TestFixture(test_atomic_inc_negative),
new_TestFixture(test_atomic_inc_rollover),
new_TestFixture(test_atomic_dec_positive),
new_TestFixture(test_atomic_dec_negative),
new_TestFixture(test_atomic_dec_rollover),
new_TestFixture(test_atomic_cas_same),
new_TestFixture(test_atomic_cas_diff),
new_TestFixture(test_atomic_value),
};
EMB_UNIT_TESTCALLER(core_atomic_tests, NULL, NULL,

Loading…
Cancel
Save