Skip to content

Commit

Permalink
kernel: atomic: consistently use named type for atomic pointer values
Browse files Browse the repository at this point in the history
There's a typedef for non-pointer values compatible with atomic
non-pointer objects.  Add a similar typedef for pointer values, and
the corresponding macro for initializing atomic pointer types.

This also will simplify replacing the Zephyr atomic API with one
based on C11 atomics, should that be desirable.  C11 atomic pointer
values are not void*.

Signed-off-by: Peter Bigot <[email protected]>
  • Loading branch information
pabigot authored and carlescufi committed Apr 19, 2021
1 parent 50cf28a commit f69a381
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 29 deletions.
12 changes: 12 additions & 0 deletions include/sys/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ extern "C" {
typedef int atomic_t;
typedef atomic_t atomic_val_t;
typedef void *atomic_ptr_t;
typedef atomic_ptr_t atomic_ptr_val_t;

/* Low-level primitives come in several styles: */

Expand Down Expand Up @@ -56,6 +57,17 @@ typedef void *atomic_ptr_t;
*/
#define ATOMIC_INIT(i) (i)

/**
* @brief Initialize an atomic pointer variable.
*
* This macro can be used to initialize an atomic pointer variable. For
* example,
* @code atomic_ptr_t my_ptr = ATOMIC_PTR_INIT(&data); @endcode
*
* @param p Pointer value to assign to atomic pointer variable.
*/
#define ATOMIC_PTR_INIT(p) (p)

/**
* @cond INTERNAL_HIDDEN
*/
Expand Down
10 changes: 5 additions & 5 deletions include/sys/atomic_builtin.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ static inline bool atomic_cas(atomic_t *target, atomic_val_t old_value,
* @param new_value New value to store.
* @return true if @a new_value is written, false otherwise.
*/
static inline bool atomic_ptr_cas(atomic_ptr_t *target, void *old_value,
void *new_value)
static inline bool atomic_ptr_cas(atomic_ptr_t *target, atomic_ptr_val_t old_value,
atomic_ptr_val_t new_value)
{
return __atomic_compare_exchange_n(target, &old_value, new_value,
0, __ATOMIC_SEQ_CST,
Expand Down Expand Up @@ -150,7 +150,7 @@ static inline atomic_val_t atomic_get(const atomic_t *target)
*
* @return Value of @a target.
*/
static inline void *atomic_ptr_get(const atomic_ptr_t *target)
static inline atomic_ptr_val_t atomic_ptr_get(const atomic_ptr_t *target)
{
return __atomic_load_n(target, __ATOMIC_SEQ_CST);
}
Expand Down Expand Up @@ -188,7 +188,7 @@ static inline atomic_val_t atomic_set(atomic_t *target, atomic_val_t value)
*
* @return Previous value of @a target.
*/
static inline void *atomic_ptr_set(atomic_ptr_t *target, void *value)
static inline atomic_ptr_val_t atomic_ptr_set(atomic_ptr_t *target, atomic_ptr_val_t value)
{
return __atomic_exchange_n(target, value, __ATOMIC_SEQ_CST);
}
Expand Down Expand Up @@ -220,7 +220,7 @@ static inline atomic_val_t atomic_clear(atomic_t *target)
*
* @return Previous value of @a target.
*/
static inline void *atomic_ptr_clear(atomic_ptr_t *target)
static inline atomic_ptr_val_t atomic_ptr_clear(atomic_ptr_t *target)
{
return atomic_ptr_set(target, NULL);
}
Expand Down
10 changes: 5 additions & 5 deletions include/sys/atomic_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ extern "C" {
__syscall bool atomic_cas(atomic_t *target, atomic_val_t old_value,
atomic_val_t new_value);

__syscall bool atomic_ptr_cas(atomic_ptr_t *target, void *old_value,
void *new_value);
__syscall bool atomic_ptr_cas(atomic_ptr_t *target, atomic_ptr_val_t old_value,
atomic_ptr_val_t new_value);

__syscall atomic_val_t atomic_add(atomic_t *target, atomic_val_t value);

Expand All @@ -41,19 +41,19 @@ static inline atomic_val_t atomic_dec(atomic_t *target)

extern atomic_val_t atomic_get(const atomic_t *target);

extern void *atomic_ptr_get(const atomic_ptr_t *target);
extern atomic_ptr_val_t atomic_ptr_get(const atomic_ptr_t *target);

__syscall atomic_val_t atomic_set(atomic_t *target, atomic_val_t value);

__syscall void *atomic_ptr_set(atomic_ptr_t *target, void *value);
__syscall atomic_ptr_val_t atomic_ptr_set(atomic_ptr_t *target, atomic_ptr_val_t value);

static inline atomic_val_t atomic_clear(atomic_t *target)
{
return atomic_set(target, 0);

}

static inline void *atomic_ptr_clear(atomic_ptr_t *target)
static inline atomic_ptr_val_t atomic_ptr_clear(atomic_ptr_t *target)
{
return atomic_ptr_set(target, NULL);

Expand Down
19 changes: 11 additions & 8 deletions kernel/atomic_c.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ bool z_vrfy_atomic_cas(atomic_t *target, atomic_val_t old_value,
#include <syscalls/atomic_cas_mrsh.c>
#endif /* CONFIG_USERSPACE */

bool z_impl_atomic_ptr_cas(atomic_ptr_t *target, void *old_value,
void *new_value)
bool z_impl_atomic_ptr_cas(atomic_ptr_t *target, atomic_ptr_val_t old_value,
atomic_ptr_val_t new_value)
{
k_spinlock_key_t key;
int ret = false;
Expand All @@ -126,8 +126,9 @@ bool z_impl_atomic_ptr_cas(atomic_ptr_t *target, void *old_value,
}

#ifdef CONFIG_USERSPACE
static inline bool z_vrfy_atomic_ptr_cas(atomic_ptr_t *target, void *old_value,
void *new_value)
static inline bool z_vrfy_atomic_ptr_cas(atomic_ptr_t *target,
atomic_ptr_val_t old_value,
atomic_ptr_val_t new_value)
{
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(target, sizeof(atomic_ptr_t)));

Expand Down Expand Up @@ -213,7 +214,7 @@ atomic_val_t atomic_get(const atomic_t *target)
return *target;
}

void *atomic_ptr_get(const atomic_ptr_t *target)
atomic_ptr_val_t atomic_ptr_get(const atomic_ptr_t *target)
{
return *target;
}
Expand Down Expand Up @@ -247,10 +248,11 @@ atomic_val_t z_impl_atomic_set(atomic_t *target, atomic_val_t value)

ATOMIC_SYSCALL_HANDLER_TARGET_VALUE(atomic_set);

void *z_impl_atomic_ptr_set(atomic_ptr_t *target, void *value)
atomic_ptr_val_t z_impl_atomic_ptr_set(atomic_ptr_t *target,
atomic_ptr_val_t value)
{
k_spinlock_key_t key;
void *ret;
atomic_ptr_val_t ret;

key = k_spin_lock(&lock);

Expand All @@ -263,7 +265,8 @@ void *z_impl_atomic_ptr_set(atomic_ptr_t *target, void *value)
}

#ifdef CONFIG_USERSPACE
static inline void *z_vrfy_atomic_ptr_set(atomic_ptr_t *target, void *value)
static inline atomic_ptr_val_t z_vrfy_atomic_ptr_set(atomic_ptr_t *target,
atomic_ptr_val_t value)
{
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(target, sizeof(atomic_ptr_t)));

Expand Down
22 changes: 11 additions & 11 deletions tests/kernel/common/src/atomic.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,12 @@ void test_atomic(void)
zassert_true((target == value), "atomic_cas");

/* atomic_ptr_cas() */
ptr_target = (atomic_ptr_t)4;
ptr_value = (void *)5;
old_ptr_value = (void *)6;
ptr_target = ATOMIC_PTR_INIT((void *)4);
ptr_value = (atomic_ptr_val_t)5;
old_ptr_value = (atomic_ptr_val_t)6;
zassert_false(atomic_ptr_cas(&ptr_target, old_ptr_value, ptr_value),
"atomic_ptr_cas");
ptr_target = (void *)6;
ptr_target = (atomic_ptr_val_t)6;
zassert_true(atomic_ptr_cas(&ptr_target, old_ptr_value, ptr_value),
"atomic_ptr_cas");
zassert_true((ptr_target == ptr_value), "atomic_ptr_cas");
Expand Down Expand Up @@ -147,8 +147,8 @@ void test_atomic(void)
zassert_true((atomic_get(&target) == 50), "atomic_get");

/* atomic_ptr_get() */
ptr_target = (atomic_ptr_t)50;
zassert_true((atomic_ptr_get(&ptr_target) == (void *)50),
ptr_target = ATOMIC_PTR_INIT((void *)50);
zassert_true((atomic_ptr_get(&ptr_target) == (atomic_ptr_val_t)50),
"atomic_ptr_get");

/* atomic_set() */
Expand All @@ -158,9 +158,9 @@ void test_atomic(void)
zassert_true((target == value), "atomic_set");

/* atomic_ptr_set() */
ptr_target = (atomic_ptr_t)42;
ptr_value = (void *)77;
zassert_true((atomic_ptr_set(&ptr_target, ptr_value) == (void *)42),
ptr_target = ATOMIC_PTR_INIT((void *)42);
ptr_value = (atomic_ptr_val_t)77;
zassert_true((atomic_ptr_set(&ptr_target, ptr_value) == (atomic_ptr_val_t)42),
"atomic_ptr_set");
zassert_true((ptr_target == ptr_value), "atomic_ptr_set");

Expand All @@ -170,8 +170,8 @@ void test_atomic(void)
zassert_true((target == 0), "atomic_clear");

/* atomic_ptr_clear() */
ptr_target = (atomic_ptr_t)100;
zassert_true((atomic_ptr_clear(&ptr_target) == (void *)100),
ptr_target = ATOMIC_PTR_INIT((void *)100);
zassert_true((atomic_ptr_clear(&ptr_target) == (atomic_ptr_val_t)100),
"atomic_ptr_clear");
zassert_true((ptr_target == NULL), "atomic_ptr_clear");

Expand Down

0 comments on commit f69a381

Please sign in to comment.