Pin/Unpin Protocol¶
Understanding the pin/unpin lifecycle for critical sections.
State Machine¶
Overview¶
The pin/unpin protocol marks critical sections where threads access lock-free data structures. Pinning prevents reclamation of objects from the current epoch.
Pin Operation¶
When you call pin():
- Load global epoch: Read the current global epoch counter
- Clear neutralization: Reset the neutralization flag
- Store epoch: Write epoch to thread's epoch slot
- Set pinned flag: Mark thread as pinned
Unpin Operation¶
When you call unpin():
- Clear pinned flag: Mark thread as no longer pinned
- Check neutralization: Read the neutralization flag
- Return result: Either
UnpinnedorNeutralizedstate
Critical Section Example¶
The following example demonstrates pin/unpin patterns and neutralization handling:
Example source not mirrored
The examples/pin_unpin.nim source was part of the standalone
nim-debra repo and is not included in this frozen mirror. View it at
the upstream link below, or see the live
SMR guide for the current lockfree/smr/nebr API.
:material-file-code: View full source
What You Can Do While Pinned¶
- Read shared memory from lock-free structures
- Perform CAS operations to modify shared state
- Retire objects that have been removed
- Access multiple structures in same critical section
What You Cannot Do While Pinned¶
Avoid these while pinned:
- Blocking operations: Don't hold locks, wait on condition variables
- Long computations: Keep critical sections short
- I/O operations: Don't do file/network I/O while pinned
- Sleeping: Don't call sleep or delay functions
Why? While a thread is pinned, objects retired by other threads cannot be reclaimed. Long critical sections delay reclamation and cause memory to accumulate in limbo bags.
Typestate Guarantees¶
The typestate system enforces:
- Cannot retire unpinned: Must be in
Pinnedstate to retire objects - Cannot double-pin: Once pinned, cannot pin again without unpinning
- Must acknowledge neutralization: Cannot pin after neutralization without acknowledging
These are compile-time guarantees - if it compiles, the protocol is correct.
Performance Considerations¶
Pin/unpin overhead:
- Pin: ~10-20ns (1 atomic load, 1 atomic store, 2 relaxed stores)
- Unpin: ~5-10ns (1 relaxed store, 1 atomic load)
This is negligible compared to lock-free operation costs.
Next Steps¶
- Learn about retiring objects
- Understand neutralization
- See integration examples