1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
//! [`ThreadFreeStack`] -- a stable per-heap identity token for cross-thread
//! free routing (M7).
//!
//! ## History — from Treiber stack to identity token
//!
//! Originally this was an intrusive lock-free Treiber stack: a cross-thread
//! freer pushed the freed block onto the owning heap's stack (overwriting the
//! block's first word with the `next` pointer), and the owner drained it on its
//! next op. That intrusive design carried the §13 hazard (the drainer had only
//! a pointer, not the original `Layout`, so it re-derived the size class from
//! the segment's `page_map` — unreliable for the mixed-class pages a shared
//! bump cursor produces — and mis-linked the free list). It was superseded by
//! the per-segment [`RemoteFreeRing`](crate::alloc_core::remote_free_ring): a
//! non-intrusive MPSC queue of `(offset, class)` entries that never touches the
//! block's bytes and carries the class the freer holds.
//!
//! What remains here is the **stable, heap-unique address** the Treiber head
//! used to be: a `Box<AtomicPtr<u8>>` whose pointer a segment header stamps in
//! `owner_thread_free`. The owning [`Heap`](crate::heap::Heap) compares this
//! address to a segment's stamp to tell own-thread frees (route to the
//! `BinTable`) from cross-thread frees (push `(offset, class)` into the
//! segment's `RemoteFreeRing`). The atomic's *value* is no longer used as a
//! stack — only its *address* matters, as a per-heap identity. The `Box`
//! allocation keeps that address stable even if the `Heap` struct moves (e.g.
//! inside `RefCell<Option<Heap>>`), and it is leaked on `Heap::drop` under
//! `alloc-xthread` so a late cross-thread freer reading the stamp never
//! dereferences freed memory (abandonment-leak soundness).
use AtomicPtr;
/// A stable, heap-unique identity token for cross-thread free routing.
///
/// `Box`-allocated so its address is stable for the lifetime of the owning
/// `Heap`; segment headers store a `*const AtomicPtr<u8>` pointing here in
/// `owner_thread_free`, and the owner uses pointer-identity to distinguish its
/// own segments from another heap's. See the module docs for why this is no
/// longer an intrusive stack.
pub