Skip to content

Atomic and non-temporal intrinsics discard actual alignment on custom aligned fields #7472

Description

@corleypc

Found while working on #7382
Not fixed there, because it needs decisions, decisions. :)

Atomic, volatile and non-temporal loads/stores of fields of #packed or custom aligned structs, unions, raw unions use wrong alignment leading to segfaults. More precisely, the correct alignment is explicitly replaced by field natural type alignment.

Minimal example for non-temporal stores. (segfault on Linux, x64, default arch target, LLVM22)

package main
import "base:intrinsics"
import "core:fmt"

P :: struct #packed { a: u8, v: #simd[4]f32 }
@(export) nt :: proc(p: ^P, x: #simd[4]f32) 
{ intrinsics.non_temporal_store(&p.v, x) }

main :: proc () {
    s: P
    x: #simd[4]f32
    
    #force_no_inline nt(&s, x)   // segfault
    fmt.println(s)
}

So why not fix it in #7382? There are a bunch of other alignment bugs fixed there already.

No significant issue with non-temporal access on x86, in particular. With correctly supplied alignment LLVM would issue two 8-byte non-temporal stores instead of the 16-byte store, and these don't need to be aligned. The main problem is that LLVM would fallback to a libcall for misaligned atomic loads/stores. In particular, on Linux LLVM needs to link libatomic and Odin doesn't link this. And, IIRC, there is no misaligned atomic access in Windows CRT at all, so nothing to link to there.

Alternative solutions:

  • Ban atomic access on misaligned fields altogether, this can be done trivially in the checker (or in the backend at issue time).
  • Keep a table with locks per address in the runtime and export custom atomic_load, atomic_store, and likely atomic_exchange and atomic_compare_and_exchange to be used for misaligned access only (aligned access still inlines). This should work fine for a single module executable; access to the same address from a DLL would mess it up (each DLL gets its own table in a multi-DLL process). And, obviously, not lock free. And no interop with libatomic if the address is being accessed from both Odin and system/C.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions