import t, c import stdio import testcheck import atom # G6: verify the atom module's inline-asm atomic operations. # Compiled with TPC to validate atom behavior in this area. def test_atomic_test_and_set(): testcheck.section("Test 1: __atomic_test_and_set") flag: uint8 = 0 result: bool = atom.__atomic_test_and_set(&flag, atom.ATOMIC_ACQUIRE) # test_and_set returns the old value: flag=0 returns 0 and sets flag=1 testcheck.check(result == bool(0), "first set returns old value 0", "expect 0") testcheck.check(flag == 1, "flag is 1 after set", "expect 1") # Second set returns 1 because the old value is now 1. result2: bool = atom.__atomic_test_and_set(&flag, atom.ATOMIC_ACQUIRE) testcheck.check(result2 == bool(1), "second set returns old value 1", "expect 1") def test_atomic_clear(): testcheck.section("Test 2: __atomic_clear") flag: uint8 = 1 atom.__atomic_clear(&flag, atom.ATOMIC_RELEASE) testcheck.check(flag == 0, "flag is 0 after clear", "expect 0") def test_atomic_thread_fence(): testcheck.section("Test 3: __atomic_thread_fence") # Only checks that the call does not crash. atom.__atomic_thread_fence(atom.ATOMIC_SEQ_CST) testcheck.ok("mfence executed OK") def test_atomic_lock_free(): testcheck.section("Test 4: __atomic_is_lock_free") flag: uint8 = 0 result: bool = atom.__atomic_is_lock_free(1, &flag) testcheck.check(result == bool(1), "1-byte is lock free", "expect 1") def test_atomic_spinlock(): testcheck.section("Test 5: spinlock pattern (test_and_set + clear)") lock: uint8 = 0 # Acquire the lock while atom.__atomic_test_and_set(&lock, atom.ATOMIC_ACQUIRE) == bool(1): pass testcheck.check(lock == 1, "lock acquired", "expect lock=1") # Release the lock atom.__atomic_clear(&lock, atom.ATOMIC_RELEASE) testcheck.check(lock == 0, "lock released", "expect lock=0") def main() -> int: testcheck.begin("G6: atom module (inline asm atomic operations)") test_atomic_test_and_set() test_atomic_clear() test_atomic_thread_fence() test_atomic_lock_free() test_atomic_spinlock() return testcheck.end()