Controller-aware wrappers around :atomics.
Each atomic operation is itself atomic (as the name implies), but
compositions of atomics aren't. For example, read; modify; write
via :atomics.get/2 + :atomics.put/3 is racy across processes.
Lockstep wraps each call as a sync point so the scheduler can
interleave between the get and the put, surfacing such races.
When called outside a Lockstep test (no controller in process dictionary), the wrapper falls through to the underlying atomic call without yielding -- so the same code runs identically in production and under controlled scheduling.
Summary
Functions
Sync point + :atomics.add/3.
Sync point + :atomics.add_get/3.
Sync point + :atomics.exchange/3.
Sync point + :atomics.get/2.
Sync point + :atomics.info/1.
Sync point + :atomics.new/2.
Sync point + :atomics.put/3.
Sync point + :atomics.sub/3.
Sync point + :atomics.sub_get/3.
Functions
Sync point + :atomics.add/3.
Sync point + :atomics.add_get/3.
Sync point + :atomics.compare_exchange/4.
Sync point + :atomics.exchange/3.
Sync point + :atomics.get/2.
Sync point + :atomics.info/1.
Sync point + :atomics.new/2.
Sync point + :atomics.put/3.
Sync point + :atomics.sub/3.
Sync point + :atomics.sub_get/3.