Commit dda8feb
committed
platform_darwin.m: port OSAtomicCompareAndSwap32 to retro_atomic.h
Apple deprecated <libkern/OSAtomic.h> in macOS 10.12 (2016) in
favour of C11 <stdatomic.h>. platform_darwin.m had two callers
of OSAtomicCompareAndSwap32 left for the GCD-based filesystem
watcher's "did anything change since last check?" flag. Replace
both with retro_atomic.h primitives.
Counter pattern, not CAS-flag
-----------------------------
The previous design used a 32-bit flag set/cleared via CAS:
- setter: OSAtomicCompareAndSwap32(0, 1, &has_changes)
from the GCD vnode event handler
- reader: OSAtomicCompareAndSwap32(1, 0, &has_changes)
from main thread; return value answers
"did at least one event fire since the last call?"
The reader's CAS is load-bearing -- it has to read-and-clear
atomically or risk losing a notification fired between the read
and the clear. retro_atomic.h does not expose a CAS primitive;
its docstring explicitly says "no compare-exchange, add only when
a real caller needs it."
Rather than add CAS to retro_atomic.h for this single caller,
restructure the field as a monotonic counter:
- setter: retro_atomic_fetch_add_int(&event_count, 1)
- reader: acquire-load event_count; compare to last_seen
cursor; update last_seen; return whether they
differ. last_seen is main-thread-only state, no
atomic primitive needed.
This is strictly more flexible than the flag. The "did anything
change?" semantic is preserved exactly (now != last_seen <=> at
least one event), and the count is available if a future caller
wants to batch events or report event volume. Multi-reader
fan-out becomes possible (each reader owns its own last_seen
cursor) without further changes.
Wraparound: 32-bit signed int at GCD vnode-event rates wraps in
centuries. The (now != last_seen) comparison remains correct
across wraparound under modular int arithmetic.
Backwards / forwards compatibility
----------------------------------
darwin_watch_data_t is file-private to platform_darwin.m -- not
declared in any header, no external code touches it. The public
path_change_data_t wrapper (frontend/frontend_driver.h) is
unchanged. The frontend_ctx_driver vtable entry
(check_for_path_changes) keeps its signature and bool return.
Caller-observable semantic is identical: returns true exactly
once per "at least one event since last call", false otherwise,
no notifications lost. The internal state difference (counter
vs flag) is invisible across the function boundary.
Performance
-----------
Reader path (called ~60 Hz from runloop.c when
video_shader_watch_files is enabled, Apple-only):
- Pre: one atomic CAS (1, 0).
- Post: one acquire-load + two non-atomic ops.
Net: strictly cheaper. ldar vs cas/ldaxr-stlxr loop on AArch64.
Setter path (GCD vnode event handler, sub-millisecond/day total):
- Pre: one CAS (may no-op if flag is already set).
- Post: one fetch_add (always stores).
Net: one extra store on the cold path. Below measurement
noise at the actual event rate.
Cache footprint: +4 bytes per watcher (last_seen). event_count
and last_seen sit on the same cache line; setter invalidates it
on every event, reader reloads next call. At 60 Hz reader vs.
sparse setter, max ~3 microseconds/sec of cache-miss cost --
negligible, and the function is not on a hot path regardless.
Field type and initialisation
-----------------------------
Field changes from `volatile int32_t has_changes` to
`retro_atomic_int_t event_count`. The retro_atomic_int_t is
int-sized and int-aligned across all 7 retro_atomic.h backends
(verified via the gfx_thumbnail port and retro_atomic_test),
so no struct-layout impact -- but the type itself is
backend-dependent: _Atomic int under C11, std::atomic<int> under
C++11, plain int under MSVC, volatile int on the fallback.
Plain assignment to _Atomic int is illegal under C11 stdatomic,
so the calloc-then-assign-zero idiom is replaced with
retro_atomic_int_init. The calloc remains; the explicit init is
belt-and-braces (zero-bit-pattern is a valid initial state for
every backend, but the API requires the init for type-system
reasons under C11).
Verified
--------
- retro_atomic.h still has no CAS / exchange primitive after
this commit. Audit confirms platform_darwin.m was the last
OSAtomic* caller in the tree (gfx/gfx_thumbnail.h's mention
is documentation referencing the backend-cascade list, not
a call site).
- Smoke test mirroring the changed code blocks compiles and
runs clean under: gcc -O2/-Wall/-Werror, clang -x objective-c,
clang -x objective-c++ -std=c++11 (CXX_BUILD-style),
forced C11 stdatomic backend. Runtime: events fire ->
reader returns true once, then false; subsequent events ->
true once again. Idempotent on no-events.
- Full platform_darwin.m compilation requires Apple SDK
(Mach + Foundation + GCD + IOKit) and is not exercised on
Linux CI; verification on macOS hardware needed before merge.1 parent b894479 commit dda8feb
1 file changed
Lines changed: 74 additions & 13 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
| 30 | + | |
30 | 31 | | |
31 | 32 | | |
32 | 33 | | |
| |||
144 | 145 | | |
145 | 146 | | |
146 | 147 | | |
147 | | - | |
| 148 | + | |
148 | 149 | | |
149 | 150 | | |
150 | 151 | | |
| |||
159 | 160 | | |
160 | 161 | | |
161 | 162 | | |
162 | | - | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
163 | 184 | | |
164 | 185 | | |
165 | 186 | | |
| |||
929 | 950 | | |
930 | 951 | | |
931 | 952 | | |
932 | | - | |
933 | | - | |
| 953 | + | |
| 954 | + | |
934 | 955 | | |
935 | 956 | | |
936 | 957 | | |
937 | 958 | | |
938 | 959 | | |
939 | 960 | | |
940 | 961 | | |
941 | | - | |
| 962 | + | |
942 | 963 | | |
943 | 964 | | |
944 | 965 | | |
| |||
989 | 1010 | | |
990 | 1011 | | |
991 | 1012 | | |
992 | | - | |
| 1013 | + | |
| 1014 | + | |
| 1015 | + | |
| 1016 | + | |
| 1017 | + | |
| 1018 | + | |
993 | 1019 | | |
994 | 1020 | | |
995 | 1021 | | |
| |||
1052 | 1078 | | |
1053 | 1079 | | |
1054 | 1080 | | |
1055 | | - | |
1056 | | - | |
1057 | | - | |
1058 | | - | |
| 1081 | + | |
| 1082 | + | |
| 1083 | + | |
| 1084 | + | |
| 1085 | + | |
| 1086 | + | |
| 1087 | + | |
| 1088 | + | |
| 1089 | + | |
| 1090 | + | |
| 1091 | + | |
| 1092 | + | |
| 1093 | + | |
| 1094 | + | |
| 1095 | + | |
| 1096 | + | |
1059 | 1097 | | |
1060 | | - | |
| 1098 | + | |
| 1099 | + | |
1061 | 1100 | | |
1062 | 1101 | | |
1063 | 1102 | | |
| |||
1122 | 1161 | | |
1123 | 1162 | | |
1124 | 1163 | | |
1125 | | - | |
1126 | | - | |
| 1164 | + | |
| 1165 | + | |
| 1166 | + | |
| 1167 | + | |
| 1168 | + | |
| 1169 | + | |
| 1170 | + | |
| 1171 | + | |
| 1172 | + | |
| 1173 | + | |
| 1174 | + | |
| 1175 | + | |
| 1176 | + | |
| 1177 | + | |
| 1178 | + | |
| 1179 | + | |
| 1180 | + | |
| 1181 | + | |
| 1182 | + | |
| 1183 | + | |
| 1184 | + | |
| 1185 | + | |
| 1186 | + | |
| 1187 | + | |
1127 | 1188 | | |
1128 | 1189 | | |
1129 | 1190 | | |
| |||
0 commit comments