nx_atomic_intrinsic_test.nx source
↩ module page · 113 lines · 4153 B
1// nx_atomic_intrinsic_test.nx -- exercise the __atomic_* compiler
2// builtins. Single-threaded smoke; SMP semantics get exercised by
3// nx_thread_pool integration tests once threads ship.
4//
5// Each test isolates one builtin so a failure points at the exact
6// codegen path: load / store / cas / faa / fence.
7
8import "nx_kernel_v2.nx"
9import "nx_log.nx"
10
11// The memory-ordering constants are no longer declared here: they moved to nx_syscalls.nx on
12// 2026-08-25 and this file already imports it transitively. This local copy was one of THREE
13// independent declarations of the same values (corpus_complete=1); it is deleted rather than kept
14// in sync, because a constant with three homes is three rulers that agree until one does not.
15
16func t1_load_store_round_trip() -> i64 {
17 let raw: *u8 = sys_mmap(16)
18 let cell: *i64 = raw as *i64
19 *cell = 0
20 __atomic_store_i64(cell, 42, NX_MO_SEQ_CST)
21 let r: i64 = __atomic_load_i64(cell, NX_MO_SEQ_CST)
22 if r != 42 { return 1 }
23 return 0
24}
25
26func t2_cas_success() -> i64 {
27 let raw: *u8 = sys_mmap(16)
28 let cell: *i64 = raw as *i64
29 *cell = 100
30 let ok: i64 = __atomic_cas_i64(cell, 100, 200, NX_MO_SEQ_CST)
31 if ok != 1 { return 21 }
32 if *cell != 200 { return 22 }
33 return 0
34}
35
36func t3_cas_failure_leaves_cell() -> i64 {
37 let raw: *u8 = sys_mmap(16)
38 let cell: *i64 = raw as *i64
39 *cell = 100
40 let r: i64 = __atomic_cas_i64(cell, 999, 7, NX_MO_SEQ_CST)
41 if r != 0 { return 31 }
42 if *cell != 100 { return 32 }
43 return 0
44}
45
46func t4_faa_returns_prior() -> i64 {
47 let raw: *u8 = sys_mmap(16)
48 let cell: *i64 = raw as *i64
49 *cell = 10
50 let prior: i64 = __atomic_faa_i64(cell, 5, NX_MO_SEQ_CST)
51 if prior != 10 { return 41 }
52 if *cell != 15 { return 42 }
53 let prior2: i64 = __atomic_faa_i64(cell, -3, NX_MO_SEQ_CST)
54 if prior2 != 15 { return 43 }
55 if *cell != 12 { return 44 }
56 return 0
57}
58
59func t5_fence_compiles_and_runs() -> i64 {
60 __atomic_fence(NX_MO_SEQ_CST)
61 __atomic_fence(NX_MO_RELAXED)
62 __atomic_fence(NX_MO_ACQUIRE)
63 __atomic_fence(NX_MO_RELEASE)
64 return 0
65}
66
67// Composite spinlock pattern. Take + take-fail + release + take.
68func t6_spinlock_via_cas() -> i64 {
69 let raw: *u8 = sys_mmap(16)
70 let lock: *i64 = raw as *i64
71 *lock = 0
72 let take_a: i64 = __atomic_cas_i64(lock, 0, 1, NX_MO_ACQUIRE)
73 if take_a != 1 { return 61 }
74 let take_b: i64 = __atomic_cas_i64(lock, 0, 1, NX_MO_ACQUIRE)
75 if take_b != 0 { return 62 }
76 __atomic_store_i64(lock, 0, NX_MO_RELEASE)
77 let take_c: i64 = __atomic_cas_i64(lock, 0, 1, NX_MO_ACQUIRE)
78 if take_c != 1 { return 63 }
79 return 0
80}
81
82func main() -> nx_exit {
83 println("=== nx_atomic intrinsic smoke (compiler-builtin codegen) ===" as *u8)
84
85 let r1: i64 = t1_load_store_round_trip()
86 if r1 != 0 { println("T1 load/store FAIL" as *u8); return r1 }
87 println("T1 load/store PASS __atomic_load_i64 + __atomic_store_i64 round-trip" as *u8)
88
89 let r2: i64 = t2_cas_success()
90 if r2 != 0 { println("T2 cas success FAIL" as *u8); return r2 }
91 println("T2 cas success PASS __atomic_cas_i64 swaps + reports 1" as *u8)
92
93 let r3: i64 = t3_cas_failure_leaves_cell()
94 if r3 != 0 { println("T3 cas failure FAIL" as *u8); return r3 }
95 println("T3 cas failure PASS __atomic_cas_i64 leaves cell + reports 0" as *u8)
96
97 let r4: i64 = t4_faa_returns_prior()
98 if r4 != 0 { println("T4 faa FAIL" as *u8); return r4 }
99 println("T4 faa PASS __atomic_faa_i64 returns prior + adds delta" as *u8)
100
101 let r5: i64 = t5_fence_compiles_and_runs()
102 if r5 != 0 { println("T5 fence FAIL" as *u8); return r5 }
103 println("T5 fence PASS __atomic_fence at all 5 memory orders" as *u8)
104
105 let r6: i64 = t6_spinlock_via_cas()
106 if r6 != 0 { println("T6 spinlock FAIL" as *u8); return r6 }
107 println("T6 spinlock PASS CAS-based take/release discipline holds" as *u8)
108
109 println("" as *u8)
110 println("All atomic intrinsics emit real RV64A AMO + lr.d/sc.d (riscv) /" as *u8)
111 println("LOCK CMPXCHG / XADD (x86_64). Single-threaded today; SMP-ready bits." as *u8)
112 return 0
113}