Expand description
Segments and spans — where a pointer’s identity comes from.
A segment is a 4 MiB region mapped at a 4 MiB-aligned address. It is cut into 64 spans of 64 KiB; span 0 holds the segment header and the other 63 serve allocations, one size class each.
That geometry is the whole reason there are no per-allocation
headers. Masking a pointer with !(SEGMENT_BYTES - 1) gives the
segment, the offset gives the span index, and the span’s metadata
gives the class — so dealloc recovers everything it needs from the
address itself. glibc has to store a size beside every chunk because
C’s free is not told one; we are, and even when we were not, the
address would answer.
Reference: mimalloc’s segment/page split (segment.c), and Go’s
mheap arena indexing. The divergence from both is that a segment
here is owned by exactly one shard for its whole life — kevy pins a
shard per core, so ownership never has to be negotiated.
Re-exports§
Structs§
- Segment
- The header at the base of every segment.
Constants§
- FIRST_
DATA_ SPAN - Span index 0 is the header; allocation spans start at 1.
- FOREIGN_
SIZE_ OFFSET - Where [
push_foreign] stores the requested size inside a free slot, clear of the link that occupies the first word. - SEGMENT_
BYTES - Bytes per segment. Power of two: the mask is the lookup.
- SPANS_
PER_ SEGMENT - Spans in a segment, including the header span.
Functions§
- foreign_
requested ⚠ - Read back the requested size a foreign free recorded.
- segment_
of ⚠ - Recover the segment owning
ptr. - slot_
index_ of - The slot index within its span holding
ptr, for a given class. - span_
index_ of - The span index within a segment holding
ptr. - splice_
foreign ⚠ - Push a slot onto a segment’s foreign-free stack.
- take_
foreign - Take the whole foreign-free list, leaving it empty. Only the owning
shard may call this — that exclusivity is what makes the structure
ABA-free (see [
push_foreign]).