Skip to content

Commit

Permalink
atomics: Constify loads
Browse files Browse the repository at this point in the history
In order to match reality, allow using these functions with pointers on
const objects, and bring us closer to C11.

Remove the '+' modifier in the atomic_load_acq_64_i586()'s inline asm
statement's constraint for '*p' (the value to load).  CMPXCHG8B always
writes back some value, even when the value exchange does not happen in
which case what was read is written back.  atomic_load_acq_64_i586()
further takes care of the operation atomically writing back the same
value that was read in any case.  All in all, this makes the inline
asm's write back undetectable by any other code, whether executing on
other CPUs or code on the same CPU before and after the call to
atomic_load_acq_64_i586(), except for the fact that CMPXCHG8B will
trigger a #GP(0) if the memory address is part of a read-only mapping.
This unfortunate property is however out of scope of the C abstract
machine, and in particular independent of whether the 'uint64_t' pointed
to is declared 'const' or not.

Approved by:    markj (mentor)
MFC after:      5 days
Sponsored by:   The FreeBSD Foundation
Differential Revision:  https://reviews.freebsd.org/D46887
  • Loading branch information
OlCe2 committed Dec 16, 2024
1 parent 4a26b63 commit 5e9a82e
Show file tree
Hide file tree
Showing 9 changed files with 40 additions and 36 deletions.
2 changes: 1 addition & 1 deletion sys/amd64/include/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ __storeload_barrier(void)

#define ATOMIC_LOAD(TYPE) \
static __inline u_##TYPE \
atomic_load_acq_##TYPE(volatile u_##TYPE *p) \
atomic_load_acq_##TYPE(const volatile u_##TYPE *p) \
{ \
u_##TYPE res; \
\
Expand Down
8 changes: 4 additions & 4 deletions sys/arm/include/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,7 @@ atomic_fetchadd_long(volatile u_long *p, u_long val)
}

static __inline uint32_t
atomic_load_acq_32(volatile uint32_t *p)
atomic_load_acq_32(const volatile uint32_t *p)
{
uint32_t v;

Expand All @@ -618,7 +618,7 @@ atomic_load_acq_32(volatile uint32_t *p)
}

static __inline uint64_t
atomic_load_64(volatile uint64_t *p)
atomic_load_64(const volatile uint64_t *p)
{
uint64_t ret;

Expand All @@ -637,7 +637,7 @@ atomic_load_64(volatile uint64_t *p)
}

static __inline uint64_t
atomic_load_acq_64(volatile uint64_t *p)
atomic_load_acq_64(const volatile uint64_t *p)
{
uint64_t ret;

Expand All @@ -647,7 +647,7 @@ atomic_load_acq_64(volatile uint64_t *p)
}

static __inline u_long
atomic_load_acq_long(volatile u_long *p)
atomic_load_acq_long(const volatile u_long *p)
{
u_long v;

Expand Down
2 changes: 1 addition & 1 deletion sys/arm64/include/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ _ATOMIC_TEST_OP(set, orr, set)

#define _ATOMIC_LOAD_ACQ_IMPL(t, w, s) \
static __inline uint##t##_t \
atomic_load_acq_##t(volatile uint##t##_t *p) \
atomic_load_acq_##t(const volatile uint##t##_t *p) \
{ \
uint##t##_t ret; \
\
Expand Down
28 changes: 16 additions & 12 deletions sys/i386/include/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ atomic_testandclear_int(volatile u_int *p, u_int v)

#define ATOMIC_LOAD(TYPE) \
static __inline u_##TYPE \
atomic_load_acq_##TYPE(volatile u_##TYPE *p) \
atomic_load_acq_##TYPE(const volatile u_##TYPE *p) \
{ \
u_##TYPE res; \
\
Expand Down Expand Up @@ -302,8 +302,8 @@ atomic_thread_fence_seq_cst(void)
#ifdef WANT_FUNCTIONS
int atomic_cmpset_64_i386(volatile uint64_t *, uint64_t, uint64_t);
int atomic_cmpset_64_i586(volatile uint64_t *, uint64_t, uint64_t);
uint64_t atomic_load_acq_64_i386(volatile uint64_t *);
uint64_t atomic_load_acq_64_i586(volatile uint64_t *);
uint64_t atomic_load_acq_64_i386(const volatile uint64_t *);
uint64_t atomic_load_acq_64_i586(const volatile uint64_t *);
void atomic_store_rel_64_i386(volatile uint64_t *, uint64_t);
void atomic_store_rel_64_i586(volatile uint64_t *, uint64_t);
uint64_t atomic_swap_64_i386(volatile uint64_t *, uint64_t);
Expand Down Expand Up @@ -353,12 +353,12 @@ atomic_fcmpset_64_i386(volatile uint64_t *dst, uint64_t *expect, uint64_t src)
}

static __inline uint64_t
atomic_load_acq_64_i386(volatile uint64_t *p)
atomic_load_acq_64_i386(const volatile uint64_t *p)
{
volatile uint32_t *q;
const volatile uint32_t *q;
uint64_t res;

q = (volatile uint32_t *)p;
q = (const volatile uint32_t *)p;
__asm __volatile(
" pushfl ; "
" cli ; "
Expand Down Expand Up @@ -447,18 +447,22 @@ atomic_fcmpset_64_i586(volatile uint64_t *dst, uint64_t *expect, uint64_t src)
return (res);
}

/*
* Architecturally always writes back some value to '*p' so will trigger
* a #GP(0) on read-only mappings.
*/
static __inline uint64_t
atomic_load_acq_64_i586(volatile uint64_t *p)
atomic_load_acq_64_i586(const volatile uint64_t *p)
{
uint64_t res;

__asm __volatile(
" movl %%ebx,%%eax ; "
" movl %%ecx,%%edx ; "
" lock; cmpxchg8b %1"
: "=&A" (res), /* 0 */
"+m" (*p) /* 1 */
: : "memory", "cc");
: "=&A" (res) /* 0 */
: "m" (*p) /* 1 */
: "memory", "cc");
return (res);
}

Expand Down Expand Up @@ -514,7 +518,7 @@ atomic_fcmpset_64(volatile uint64_t *dst, uint64_t *expect, uint64_t src)
}

static __inline uint64_t
atomic_load_acq_64(volatile uint64_t *p)
atomic_load_acq_64(const volatile uint64_t *p)
{

if ((cpu_feature & CPUID_CX8) == 0)
Expand Down Expand Up @@ -842,7 +846,7 @@ atomic_swap_long(volatile u_long *p, u_long v)
#define atomic_subtract_rel_ptr(p, v) \
atomic_subtract_rel_int((volatile u_int *)(p), (u_int)(v))
#define atomic_load_acq_ptr(p) \
atomic_load_acq_int((volatile u_int *)(p))
atomic_load_acq_int((const volatile u_int *)(p))
#define atomic_store_rel_ptr(p, v) \
atomic_store_rel_int((volatile u_int *)(p), (v))
#define atomic_cmpset_ptr(dst, old, new) \
Expand Down
6 changes: 3 additions & 3 deletions sys/powerpc/include/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ atomic_readandclear_long(volatile u_long *addr)
*/
#define ATOMIC_STORE_LOAD(TYPE) \
static __inline u_##TYPE \
atomic_load_acq_##TYPE(volatile u_##TYPE *p) \
atomic_load_acq_##TYPE(const volatile u_##TYPE *p) \
{ \
u_##TYPE v; \
\
Expand Down Expand Up @@ -534,10 +534,10 @@ ATOMIC_STORE_LOAD(long)
#define atomic_store_rel_ptr atomic_store_rel_long
#else
static __inline u_long
atomic_load_acq_long(volatile u_long *addr)
atomic_load_acq_long(const volatile u_long *addr)
{

return ((u_long)atomic_load_acq_int((volatile u_int *)addr));
return ((u_long)atomic_load_acq_int((const volatile u_int *)addr));
}

static __inline void
Expand Down
4 changes: 2 additions & 2 deletions sys/riscv/include/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ ATOMIC_FCMPSET_ACQ_REL(16);

#define atomic_load_acq_16 atomic_load_acq_16
static __inline uint16_t
atomic_load_acq_16(volatile uint16_t *p)
atomic_load_acq_16(const volatile uint16_t *p)
{
uint16_t ret;

Expand Down Expand Up @@ -312,7 +312,7 @@ ATOMIC_CMPSET_ACQ_REL(32);
ATOMIC_FCMPSET_ACQ_REL(32);

static __inline uint32_t
atomic_load_acq_32(volatile uint32_t *p)
atomic_load_acq_32(const volatile uint32_t *p)
{
uint32_t ret;

Expand Down
2 changes: 1 addition & 1 deletion sys/sys/_atomic64e.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ int atomic_fcmpset_64(volatile u_int64_t *, u_int64_t *, u_int64_t);

u_int64_t atomic_fetchadd_64(volatile u_int64_t *, u_int64_t);

u_int64_t atomic_load_64(volatile u_int64_t *);
u_int64_t atomic_load_64(const volatile u_int64_t *);
#define atomic_load_acq_64 atomic_load_64

void atomic_readandclear_64(volatile u_int64_t *);
Expand Down
4 changes: 2 additions & 2 deletions sys/sys/_atomic_subword.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ atomic_fcmpset_16(__volatile uint16_t *addr, uint16_t *old, uint16_t val)

#ifndef atomic_load_acq_8
static __inline uint8_t
atomic_load_acq_8(volatile uint8_t *p)
atomic_load_acq_8(const volatile uint8_t *p)
{
int shift;
uint8_t ret;
Expand All @@ -189,7 +189,7 @@ atomic_load_acq_8(volatile uint8_t *p)

#ifndef atomic_load_acq_16
static __inline uint16_t
atomic_load_acq_16(volatile uint16_t *p)
atomic_load_acq_16(const volatile uint16_t *p)
{
int shift;
uint16_t ret;
Expand Down
20 changes: 10 additions & 10 deletions sys/sys/atomic_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,18 @@

#include <sys/types.h>

#define __atomic_load_bool_relaxed(p) (*(volatile _Bool *)(p))
#define __atomic_load_bool_relaxed(p) (*(const volatile _Bool *)(p))
#define __atomic_store_bool_relaxed(p, v) \
(*(volatile _Bool *)(p) = (_Bool)(v))

#define __atomic_load_char_relaxed(p) (*(volatile u_char *)(p))
#define __atomic_load_short_relaxed(p) (*(volatile u_short *)(p))
#define __atomic_load_int_relaxed(p) (*(volatile u_int *)(p))
#define __atomic_load_long_relaxed(p) (*(volatile u_long *)(p))
#define __atomic_load_8_relaxed(p) (*(volatile uint8_t *)(p))
#define __atomic_load_16_relaxed(p) (*(volatile uint16_t *)(p))
#define __atomic_load_32_relaxed(p) (*(volatile uint32_t *)(p))
#define __atomic_load_64_relaxed(p) (*(volatile uint64_t *)(p))
#define __atomic_load_char_relaxed(p) (*(const volatile u_char *)(p))
#define __atomic_load_short_relaxed(p) (*(const volatile u_short *)(p))
#define __atomic_load_int_relaxed(p) (*(const volatile u_int *)(p))
#define __atomic_load_long_relaxed(p) (*(const volatile u_long *)(p))
#define __atomic_load_8_relaxed(p) (*(const volatile uint8_t *)(p))
#define __atomic_load_16_relaxed(p) (*(const volatile uint16_t *)(p))
#define __atomic_load_32_relaxed(p) (*(const volatile uint32_t *)(p))
#define __atomic_load_64_relaxed(p) (*(const volatile uint64_t *)(p))

#define __atomic_store_char_relaxed(p, v) \
(*(volatile u_char *)(p) = (u_char)(v))
Expand Down Expand Up @@ -124,7 +124,7 @@
__atomic_store_generic(p, v, int64_t, uint64_t, 64)
#endif

#define atomic_load_ptr(p) (*(volatile __typeof(*p) *)(p))
#define atomic_load_ptr(p) (*(const volatile __typeof(*p) *)(p))
#define atomic_store_ptr(p, v) (*(volatile __typeof(*p) *)(p) = (v))

/*
Expand Down

0 comments on commit 5e9a82e

Please sign in to comment.