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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
//! OS primitive layer (mirrors upstream `src/prim/*`, plan §6). One backend per
//! platform, selected at compile time; under miri a registry-backed [`mock`]
//! stands in so the layers above stay testable where FFI cannot run (gate G4).
//!
//! This module is one of the few allowed `unsafe` (plan §6 policy): every block
//! carries its SAFETY invariant, and everything above talks to the safe-ish
//! surface in [`crate::os`].
use windows as sys;
use unix as sys;
// Wasm is neither `windows` nor `unix`, so it needs its own arm: one linear
// memory that only grows, no page protection, no clock, one thread.
use wasm as sys;
use mock as sys;
// A target with no OS at all — a microcontroller, where memory is a region the
// linker reserved (P1 of `docs/plans/small-metal.md`). This is the fifth arm
// P0 found missing: `riscv32imac-unknown-none-elf` is none of the four above,
// so before this existed no `sys` was named at all and every call through the
// seam failed together.
//
// ALWAYS COMPILED, so it is type-checked and unit-tested on the host;
// SELECTED only where no arm above matches, so no host build changes.
use fixed as sys;
use c_void;
/// OS error code (`GetLastError` on Windows, `errno` on unix, synthetic in mock).
pub type PrimError = u32;
/// Static memory-subsystem facts, queried once at startup (`_mi_prim_mem_init`).
/// Whether [`free`] actually returns memory to the host.
///
/// True everywhere except wasm: `munmap` and `VirtualFree(MEM_RELEASE)` both
/// release the whole mapping (only PARTIAL free differs between them — that is
/// [`MemConfig::has_partial_free`], a different property). On wasm linear
/// memory can only grow, so [`free`] is a no-op and a mapping handed to it
/// would otherwise be unreachable forever. [`crate::os::free`] keys on this to
/// hand such blocks to [`crate::arena::adopt_os_block`] instead, which is the
/// allocator's ONLY recycling layer on such a platform — the segment cache
/// this role is sometimes attributed to does not exist (upstream mimalloc v2
/// deleted it when arenas replaced it, and this remake followed).
///
/// A `const`, not a `MemConfig` field, so the adoption path folds away
/// entirely on every platform whose free works.
pub const FREE_RETURNS_MEMORY: bool = !cfg!;
/// Result of a successful [`alloc`].
/// Query static memory configuration.
/// Reserve (and optionally commit) `size` bytes aligned to `try_alignment`.
///
/// `size` must be page-multiple and > 0; `try_alignment` a power of two.
/// `allow_large` permits (but never requires) large-page backing.
///
/// # Safety
/// Returned memory is unmanaged: caller owns the range and must eventually
/// [`free`] it with the same base and size.
pub unsafe
/// Release a mapping obtained from [`alloc`].
///
/// # Safety
/// `ptr`/`size` must denote exactly one prior [`alloc`] result (whole mapping —
/// partial free only where `MemConfig::has_partial_free`), not yet freed.
pub unsafe
/// Commit a page-aligned range inside a reservation. Returns whether the
/// committed range is known-zero.
///
/// # Safety
/// Range must lie inside a live [`alloc`] mapping, page-aligned.
pub unsafe
/// Decommit a page-aligned range. Returns whether a later [`commit`] is
/// required before touching it again (Windows: yes; unix `MADV_DONTNEED`: no).
///
/// # Safety
/// Range must lie inside a live [`alloc`] mapping, page-aligned; contents lost.
pub unsafe
/// Tell the OS the range's contents are dead but keep it committed
/// (`MEM_RESET` / `MADV_FREE`). Contents afterwards are undefined.
///
/// # Safety
/// Range must lie inside a live, committed mapping, page-aligned.
pub unsafe
/// Toggle no-access protection on a page-aligned range (guard pages, M8).
///
/// # Safety
/// Range must lie inside a live, committed mapping; caller must not touch a
/// protected range until unprotected.
pub unsafe
/// Number of NUMA nodes (≥ 1). M1 returns the real count on Windows, 1 on
/// unix (sysfs parsing lands with arenas in M6).
/// Cheap unique id of the calling thread (the heap-ownership key from M4).
/// Monotonic clock in nanoseconds (purge delays, stats).
/// Platform-native TLS destructor signature. On x86-64/aarch64 the `"system"`
/// and `"C"` ABIs coincide; the alias exists so each backend hands its OS the
/// exact type it expects.
pub type TlsDtor = unsafe extern "system" fn;
/// Platform-native TLS destructor signature (pthread form).
pub type TlsDtor = unsafe extern "C" fn;
/// A dynamically-created TLS slot whose destructor runs at thread exit with
/// the slot's value, if non-null (`FlsAlloc` / `pthread_key_create`). This is
/// the hook `mi_thread_done` hangs off in M4.
;
// SAFETY: a TLS slot handle is an index into per-thread storage; sharing the
// handle across threads is the entire point (each thread sees its own value).
unsafe
// SAFETY: as above — get/set only touch calling-thread state.
unsafe
/// Round `n` up to a multiple of power-of-two `align`.
pub const