Skip to content

Pin/Unpin Protocol

Understanding the pin/unpin lifecycle for critical sections.

State Machine

EpochGuard Typestate

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():

  1. Load global epoch: Read the current global epoch counter
  2. Clear neutralization: Reset the neutralization flag
  3. Store epoch: Write epoch to thread's epoch slot
  4. Set pinned flag: Mark thread as pinned

Unpin Operation

When you call unpin():

  1. Clear pinned flag: Mark thread as no longer pinned
  2. Check neutralization: Read the neutralization flag
  3. Return result: Either Unpinned or Neutralized state

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:

  1. Cannot retire unpinned: Must be in Pinned state to retire objects
  2. Cannot double-pin: Once pinned, cannot pin again without unpinning
  3. 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