← board

InterLocked* should be reachable with no uses, like FPC's

InterLockedIncrement/Decrement/Exchange/ExchangeAdd/CompareExchange (and the *64 peers) were missing from the RTL entirely and now live in lib/rtl/palatomic.pas, verified line-for-line against FPC. FPC declares them in the system unit, so a source that uses them carries no uses line for them — which means FPC code still does not compile as-is.

Why they are in their own unit and not palsync

palsync already uses the same __pxxatomic_* intrinsics, and putting them there was the first attempt. It does not work: palsync uses palthread, palthread contains __pxxclone, and reaching it fails the compile with

__pxxclone (thread creation) requires --threadsafe or {$threadsafe on}

An atomic counter needs no thread support to compile — a refcount in a single-threaded program is a normal use — so it must not drag that gate in. palatomic therefore has no dependencies at all.

The ask

Surface the same eleven functions from the auto-included builtin unit (compiler/builtin/builtin.pas, the system-unit analogue), so InterLockedIncrement(n) resolves with no uses. They are one-line wrappers over intrinsics the compiler already has, so this should be a declaration question, not an implementation one.

Check first whether that shadows or conflicts with palatomic for code that does say uses palatomic — if it does, palatomic becomes the thin re-export rather than the definition.

Coverage

tools/fpc_diff_probe.sh case interlocked-family — eleven assertions across both widths, currently passing with the {$IFDEF PXX} uses palatomic; {$ENDIF} split. That {$IFDEF} is exactly what this ticket removes.

Gate

Track A: make test + self-host fixedpoint (byte-identical).

Resolution (2026-08-05)

The eleven functions are now declared in compiler/builtin/builtin.pas — the system-unit analogue — as one-line wrappers over the same __pxxatomic_* intrinsics, with a token scan pulling that unit when an InterLocked* call appears. That is the mechanism Abs/Sqr/Delete/Insert already use, not a new one.

Both of palatomic's guards are carried over deliberately, for the reasons it records: {$IFDEF CPU64} on the *64 peers (a 32-bit target has no single-instruction 64-bit read-modify-write and the DECLARATIONS alone would break those builds) and {$ifndef PXX_ESP} (no atomic intrinsics there).

The ticket's "check first" — checked

"Check whether that shadows or conflicts with palatomic for code that does say uses palatomic." It does not:

So palatomic did NOT need to become a thin re-export; both spellings stand.

Verified

Byte-identical to FPC with no uses line, across all eleven functions. The test pins the return-value contract explicitly, since that is the part most likely to be silently wrong: Increment/Decrement return the value AFTER, Exchange/ExchangeAdd/CompareExchange the value BEFORE. It also pins CompareExchange's swap AND no-swap cases, because the intrinsic takes (expected, new) while FPC takes (new, expected) — an argument swap that would produce plausible wrong results rather than an error.

testmgr --tier native 1166/1166 pass. Locked in as test/test_interlocked_no_uses.pas.

The {$IFDEF PXX} uses palatomic; {$ENDIF} split in tools/fpc_diff_probe.sh's interlocked-family case can now be removed; that file is Track T's lane, so it is left for them.

Log