Skip to content

libc: Improve C11/C23 stdatomic conformance and GCC compatibility#2185

Open
kfv wants to merge 9 commits into
freebsd:mainfrom
kfv:libc/stdatomic
Open

libc: Improve C11/C23 stdatomic conformance and GCC compatibility#2185
kfv wants to merge 9 commits into
freebsd:mainfrom
kfv:libc/stdatomic

Conversation

@kfv
Copy link
Copy Markdown
Contributor

@kfv kfv commented May 10, 2026

This series improves stdatomic.h conformance, compatibility, and test coverage across C11/C23 modes.

Highlights include:

  • Add the missing kill_dependency macro
  • Add the C23 atomics feature test macro
  • Restrict ATOMIC_VAR_INIT to pre-C23 modes
  • Make atomic_flag selection and initialisation conform to lock-free and C23 requirements
  • Fix atomic_init() for GCC atomic objects
  • Fix GCC pointer semantics for atomic_fetch_add() and atomic_fetch_sub() on atomic pointer types
  • Expand regression coverage for interface semantics, compile-time assertions, and behavioural conformance

This also includes several non-functional reorganisations to align the header structure more closely with ISO C and improve maintainability.

@clausecker
Copy link
Copy Markdown
Contributor

This is probably one for @EdSchouten.

@bms
Copy link
Copy Markdown

bms commented May 16, 2026

I haven't drilled on the atomics because I'm not using them (yet), but I have been reviewing some of Jens Gustedt's work over the last week. I'm all about the richness.

kfv added 9 commits May 17, 2026 15:33
Signed-off-by: Faraz Vahedi <kfv@kfv.io>
Omit `ATOMIC_VAR_INIT` when targeting C23, where it has been removed.
Retain it for earlier C standards and for C++ (as it still remains in
C++23, albeit marked as deprecated since C17 and C++20.)

Also separate `atomic_init` definitions from `ATOMIC_VAR_INIT` to
avoid coupling with a deprecated initialisation mechanism.

No functional change intended for `atomic_init`; this is purely a
conformance and cleanup adjustment.

Signed-off-by: Faraz Vahedi <kfv@kfv.io>
Add `kill_dependency` as specified by C11 §7.17.3.1.

The macro is required to break dependency chains in
expressions without affecting the value.

No functional impact beyond providing the required,
value-preserving definition.

Signed-off-by: Faraz Vahedi <kfv@kfv.io>
Place the `memory_order` enumeration constants alongside the corresponding
typedef under the §7.17.3 heading.

The previous layout separated the fallback constant definitions from the
enum, which could obscure their relationship. These fallbacks exist only
to provide values when the compiler does not supply the builtins.

The removed comment encoded implementation-specific assumptions about
compiler-provided definitions and implied a relationship between Clang/GCC
macros and fallback values. In practice, the fallback definitions exist
solely to ensure the enumerators are defined when compiler intrinsics are
absent, and do not depend on any particular numeric mapping.

No functional change; this is a mere structural and clarity improvement.

Signed-off-by: Faraz Vahedi <kfv@kfv.io>
Reorder definitions of specified generic operations on atomic types
so they follow the sequence in ISO/IEC 9899:2024 §7.17.7:

1. `atomic_store`
2. `atomic_load`
3. `atomic_exchange`
4. `atomic_compare_exchange`
5. `atomic_fetch`

This aligns the header layout with the standard, making it easier
to cross-check against the normative text and maintain consistency
with the rest of the header.

The behaviour of the macros remains unchanged; this is purely a
reorganisation and documentation improvement.

Signed-off-by: Faraz Vahedi <kfv@kfv.io>
Select the `atomic_flag` backing type according to the C standard
requirements that `atomic_flag` operations be lock-free.

C11 §7.17.1.5 defines `atomic_flag` as:

> a structure type representing a lock-free, primitive atomic flag

and §7.17.8.2 further requires:

> Operations on an object of type atomic_flag shall be lock free

Therefore:

- Prefer `atomic_bool` when `ATOMIC_BOOL_LOCK_FREE == 2`
- Fall back to `atomic_uchar` when `ATOMIC_CHAR_LOCK_FREE == 2`
- Trigger a translation failure if neither type is lock-free

Adjust `ATOMIC_FLAG_INIT` for C23 initialisation rules:

- Use `{ ATOMIC_VAR_INIT(0) }` in pre-C23 modes
- Use `{ 0 }` in C23 and later

Preserve `atomic_flag_test_and_set_explicit()` semantics by
normalising the exchanged value with `!= 0`, ensuring consistent
boolean results regardless of whether the underlying
representation is `atomic_bool` or `atomic_uchar`.

Signed-off-by: Faraz Vahedi <kfv@kfv.io>
Add a dedicated `__GNUC_ATOMICS` path that initialises via
`atomic_store_explicit(obj, value, memory_order_relaxed)`.

This ensures the required initialisation semantics without
assuming any particular object representation.

Previously, `atomic_init` on GCC fell through to the legacy
`__val` member path intended only for old struct-backed
atomic objects. For current atomic objects, this caused the
following compilation error:

> error: request for member '__val' in something not a
  structure or union

As a result, valid code such as `atomic_init(&x, 1)` failed
to compile when using GCC.

This fix restores compatibility with standard-conforming
callers while other code paths remain unchanged.

Signed-off-by: Faraz Vahedi <kfv@kfv.io>
Correct the GCC implementation of `atomic_fetch_add_explicit()`
and `atomic_fetch_sub_explicit()` for atomic pointer types.

The previous implementation passed the operand directly to the
builtins. For pointer objects, this could result in raw byte-wise
address arithmetic rather than the required C atomic pointer
semantics, where the operand is interpreted as a `ptrdiff_t`
element count.

As a result, operations such as `atomic_fetch_sub_explicit(&p, 2, ...)`
could produce an incorrect post-operation pointer value.

Fix this by applying pointer scaling in the GCC path before invoking
the builtin, mirroring the existing legacy fallback implementation.
Pointer operands are now scaled by the size of the pointed-to type,
while integer atomic behaviour remains unchanged.

Signed-off-by: Faraz Vahedi <kfv@kfv.io>
Extend the existing test utility to cover recent stdatomic
changes and improve validation of interface semantics,
compile-time assertions, and behavioural conformance.

Signed-off-by: Faraz Vahedi <kfv@kfv.io>
@kfv kfv force-pushed the libc/stdatomic branch from a5b0a1f to 9129bcd Compare May 17, 2026 12:20
@kfv
Copy link
Copy Markdown
Contributor Author

kfv commented May 17, 2026

[UPDATE] Remove _STDATOMIC_H_ include guard as __STDC_VERSION_STDATOMIC_H__ standard feature-test macro would suffice, consistent with the established pattern in <stdbit.h>, <stdbool.h>, and <stdckdint.h>.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants