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
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
/***************************************************************************
*
* osal-rs
* Copyright (C) 2026 Antonio Salsi <passy.linux@zresa.it>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <https://www.gnu.org/licenses/>.
*
***************************************************************************/
//! macOS/libSystem-specific FFI items: opaque type sizes, constant values
//! and functions Linux does not provide. Glob re-exported by the parent
//! [`ffi`](super) module, which holds everything shared with Linux.
//!
//! Only Apple Silicon (`aarch64-apple-darwin`) is supported. Values come
//! from the macOS SDK headers (`<sys/_pthread/_pthread_types.h>`,
//! `<sys/signal.h>`, `<time.h>`, `<sys/errno.h>`, `<unistd.h>`).
use ;
use ;
compile_error!;
/// Size (in bytes) of `pthread_attr_t`: an 8-byte `__sig` signature
/// followed by `__PTHREAD_ATTR_SIZE__` (56) opaque bytes.
pub const PTHREAD_ATTR_T_SIZE: usize = 64;
/// Size (in bytes) of `pthread_mutex_t`: `__sig` + `__PTHREAD_MUTEX_SIZE__`
/// (56) opaque bytes. An initialized mutex always has a non-zero `__sig`.
pub const PTHREAD_MUTEX_T_SIZE: usize = 64;
/// Size (in bytes) of `pthread_mutexattr_t`: `__sig` +
/// `__PTHREAD_MUTEXATTR_SIZE__` (8) opaque bytes.
pub const PTHREAD_MUTEXATTR_T_SIZE: usize = 16;
/// Size (in bytes) of `pthread_cond_t`: `__sig` + `__PTHREAD_COND_SIZE__`
/// (40) opaque bytes.
pub const PTHREAD_COND_T_SIZE: usize = 48;
/// Size (in bytes) of `pthread_condattr_t`: `__sig` +
/// `__PTHREAD_CONDATTR_SIZE__` (8) opaque bytes.
pub const PTHREAD_CONDATTR_T_SIZE: usize = 16;
/// Signal set (`sigset_t`): a plain `__uint32_t` on macOS. Only its
/// address is handed to `sig*set`/`sigsuspend`.
pub
/// Mirrors macOS's user-space `struct sigaction` (`<sys/signal.h>`).
pub
/// `sigaction` flag: restart system calls interrupted by the handler
/// (`<sys/signal.h>`).
pub const SA_RESTART: c_int = 0x0002;
/// Minimum stack size (in bytes) for a thread (`PTHREAD_STACK_MIN`,
/// `<limits.h>`). macOS also requires the stack size to be a multiple of
/// the page size (16 KiB on Apple Silicon).
pub const PTHREAD_STACK_MIN: usize = 16384;
/// One-time initialization control (`pthread_once_t`): unlike glibc's plain
/// `int`, macOS uses a `__sig` signature followed by
/// `__PTHREAD_ONCE_SIZE__` (8) opaque bytes.
pub
/// Initial value for a [`pthread_once_t`] (`PTHREAD_ONCE_INIT`):
/// `{_PTHREAD_ONCE_SIG_init, {0}}`.
pub const PTHREAD_ONCE_INIT: pthread_once_t = pthread_once_t ;
/// Scheduling policy: real-time first-in-first-out (`<sched.h>`).
pub const SCHED_FIFO: c_int = 4;
/// Scheduling-inheritance attribute: use the policy/priority set on the
/// `pthread_attr_t` itself instead of inheriting the creating thread's.
pub const PTHREAD_EXPLICIT_SCHED: c_int = 2;
/// Mirrors macOS's `struct sched_param` (`<sys/_pthread/_pthread_types.h>`),
/// which pads `sched_priority` with 4 opaque bytes (8 bytes total, versus
/// glibc's 4).
///
/// `sched_get_priority_min`/`max(SCHED_FIFO)` report 15..=47, but macOS
/// accepts other values too (verified: 1 and 99 both create the thread),
/// and grants `SCHED_FIFO` to unprivileged processes.
pub
/// `sysconf(3)` parameter name for the page size (`<unistd.h>`).
pub const _SC_PAGESIZE: c_int = 29;
/// Clock identifier for `clock_gettime(2)`: time since an unspecified
/// starting point that never jumps backward or with wall-clock adjustments
/// (`<time.h>`, `_CLOCK_MONOTONIC`).
pub const CLOCK_MONOTONIC: c_int = 6;
/// `errno` value for a timed-out wait (`<sys/errno.h>`).
pub const ETIMEDOUT: c_int = 60;
/// `pthread_sigmask(3)` operation: add the signals in `set` to the
/// caller's blocked mask.
pub const SIG_BLOCK: c_int = 1;
/// `pthread_sigmask(3)` operation: replace the caller's blocked mask with
/// `set`.
pub const SIG_SETMASK: c_int = 3;
/// Mutex type: the owning thread may lock it again without deadlocking,
/// as long as it unlocks it the same number of times (`<pthread.h>`).
pub const PTHREAD_MUTEX_RECURSIVE: c_int = 2;
/// User-defined signal 1 (`<sys/signal.h>`). macOS has no real-time
/// signals (`SIGRTMIN`), so thread suspend uses this instead.
pub const SIGUSR1: c_int = 30;
/// User-defined signal 2 (`<sys/signal.h>`). macOS has no real-time
/// signals (`SIGRTMIN`), so thread resume uses this instead.
pub const SIGUSR2: c_int = 31;
/// Mach port name (`mach_port_t`, `<mach/port.h>`): a 32-bit integer.
type mach_port_t = c_uint;
/// Mach call status (`kern_return_t`); [`KERN_SUCCESS`] is 0.
type kern_return_t = c_int;
/// Successful [`kern_return_t`] (`<mach/kern_return.h>`).
const KERN_SUCCESS: kern_return_t = 0;
/// `host_statistics64` flavor returning a `vm_statistics64` (`<mach/host_info.h>`).
const HOST_VM_INFO64: c_int = 4;
/// Size, in 32-bit words, of the buffer handed to `host_statistics64`.
///
/// Deliberately not pinned to `HOST_VM_INFO64_COUNT`: `vm_statistics64`
/// grows with macOS releases (62 words in the SDK on GitHub's runners, 104
/// in the macOS 27 SDK), so any exact value would be wrong on some SDK.
/// The kernel accepts a larger buffer, fills only the fields it knows and
/// lowers `count` accordingly (verified: 256 in, 104 out); `free_count` is
/// always the first word. The layout test checks this is at least the
/// SDK's `HOST_VM_INFO64_COUNT`.
pub const VM_STATISTICS64_WORDS: c_uint = 128;
/// Opaque storage for `vm_statistics64_data_t` (`<mach/vm_statistics.h>`).
/// Only its first word, `free_count` (free pages), is read.
unsafe extern "C"
/// No-op on macOS: it has no `pthread_condattr_setclock`, so the monotonic
/// clock is honoured at wait time instead, by
/// [`cond_timedwait_monotonic`] turning the deadline into a relative timeout.
///
/// # Safety
///
/// Trivially safe; `unsafe` only to match the Linux signature.
pub unsafe
/// Atomically unlocks `mutex` and blocks on `cond` until it is signaled or
/// the monotonic `deadline` (from [`monotonic_deadline`](super::monotonic_deadline))
/// passes, then re-locks `mutex`. Returns [`ETIMEDOUT`] once the deadline
/// has passed; may also return spuriously, so callers re-check in a loop.
///
/// The time left is recomputed from `CLOCK_MONOTONIC` on every call, so a
/// caller looping over spurious wake-ups never waits past `deadline`.
///
/// # Safety
///
/// `cond` must have been initialized by
/// [`cond_init_monotonic`](super::cond_init_monotonic) and `mutex` must be
/// locked by the calling thread.
pub unsafe
/// Signal sent to a thread to ask it to suspend itself. macOS has no
/// real-time signals, so the backend reserves [`SIGUSR1`] for this.
pub
/// Signal sent to a suspended thread to wake it back up. macOS has no
/// real-time signals, so the backend reserves [`SIGUSR2`] for this.
pub
/// Names the calling thread (`<= 63` chars + NUL).
///
/// # Safety
///
/// `name` must point to a NUL-terminated string.
pub unsafe
/// Number of physical memory pages currently free (`free_count` of
/// `host_statistics64(HOST_VM_INFO64)`, what `vm_stat` reports as
/// "Pages free"), or a value `<= 0` if it cannot be determined. macOS has
/// no `sysconf(_SC_AVPHYS_PAGES)`.
pub