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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
//! [`AllocBitmap`] — the per-segment **O(1) exact double-free guard**: one bit
//! per `MIN_BLOCK`-slot of the segment, recording whether the block starting at
//! that slot is currently FREE (sitting in one of the segment's free lists) or
//! ALLOCATED / not-a-block-start.
//!
//! ## Why a bitmap (Phase 13.4a)
//!
//! The Phase 8 double-free guard walked the class free list on every own-thread
//! free (`free_list_contains`) — O(free-list length). On a churn workload that
//! frees N blocks of one class into one segment the free list grows 0→N, so the
//! walk is **O(N²)** (the bench regression #41: 16 B churn ballooned to ~1.9 ms
//! vs mimalloc's ~11 µs). This bitmap makes the guard **O(1) and exact**: a
//! single bit test/set per free. Unlike a block canary it never false-positives
//! (user data can equal any canary), so it satisfies M2 precisely: a double-free
//! is a no-op, never a self-loop / double-issue / corruption.
//!
//! ## Semantics
//!
//! - Bit `b = off >> MIN_BLOCK_SHIFT` covers the `MIN_BLOCK`-slot at segment
//! offset `off`. Block starts are always `MIN_BLOCK`-aligned (carve aligns the
//! bump to `block_size`, a multiple of `MIN_BLOCK`), so each block maps to a
//! unique bit. The bitmap covers the WHOLE segment (including its metadata
//! region) — the metadata bits are simply never touched (no block starts
//! there), which avoids any payload-start subtraction.
//! - Bit `1` = FREE (in some free list of this segment: `free` / `local_free` /
//! reclaimed). Bit `0` = allocated, or not a block start. Fresh init is all
//! zeros ("everything allocated / not-a-block").
//!
//! ## This file is PURE SAFE DATA + ARITHMETIC
//!
//! Every raw memory touch goes through the [`node`](super::node) seam (exactly
//! like [`PageMap`](super::segment_header::PageMap) /
//! [`BinTable`](super::segment_header::BinTable)). There is NO `unsafe` here.
//!
//! ## No atomics (single-writer)
//!
//! A segment's bitmap is written ONLY by the segment's owner: own-thread frees
//! and the owner-side `reclaim_offset` drain both run on the owner. Cross-thread
//! frees never touch the bitmap — they go through the
//! [`RemoteFreeRing`](super::remote_free_ring::RemoteFreeRing) (offsets only)
//! and the owner sets the bit when it drains. So plain (non-atomic) byte
//! reads/writes are race-free, matching the `bump`-cursor single-writer rule.
use Node;
use SEGMENT;
use ;
/// The per-segment allocation/free bitmap view: one bit per `MIN_BLOCK`-slot of
/// the segment. A thin view over in-segment metadata carved by the bootstrap at
/// [`Layout::alloc_bitmap_off`](super::segment_header::Layout::alloc_bitmap_off);
/// it owns no memory.
pub