1#[cfg(any(freebsdlike, linux_kernel, target_os = "fuchsia"))]
4use super::types::RawCpuSet;
5use crate::backend::c;
6use crate::backend::conv::ret;
7use crate::io;
8#[cfg(any(freebsdlike, linux_kernel, target_os = "fuchsia"))]
9use crate::pid::Pid;
10#[cfg(not(any(
11 apple,
12 freebsdlike,
13 target_os = "emscripten",
14 target_os = "espidf",
15 target_os = "haiku",
16 target_os = "horizon",
17 target_os = "openbsd",
18 target_os = "redox",
19 target_os = "vita",
20 target_os = "wasi",
21)))]
22use crate::thread::ClockId;
23#[cfg(linux_kernel)]
24use crate::thread::{Cpuid, MembarrierCommand, MembarrierQuery};
25#[cfg(not(target_os = "redox"))]
26use crate::thread::{NanosleepRelativeResult, Timespec};
27#[cfg(all(target_env = "gnu", fix_y2038))]
28use crate::timespec::LibcTimespec;
29#[cfg(not(fix_y2038))]
30use crate::timespec::{as_libc_timespec_mut_ptr, as_libc_timespec_ptr};
31#[cfg(linux_kernel)]
32use crate::utils::option_as_ptr;
33use core::mem::MaybeUninit;
34#[cfg(linux_kernel)]
35use core::sync::atomic::AtomicU32;
36#[cfg(linux_kernel)]
37use {
38 crate::backend::conv::{borrowed_fd, ret_c_int, ret_u32, ret_usize},
39 crate::fd::BorrowedFd,
40 crate::thread::futex,
41 crate::utils::as_mut_ptr,
42};
43
44#[cfg(all(target_env = "gnu", fix_y2038))]
45weak!(fn __clock_nanosleep_time64(c::clockid_t, c::c_int, *const LibcTimespec, *mut LibcTimespec) -> c::c_int);
46#[cfg(all(target_env = "gnu", fix_y2038))]
47weak!(fn __nanosleep64(*const LibcTimespec, *mut LibcTimespec) -> c::c_int);
48
49#[cfg(not(any(
50 apple,
51 target_os = "dragonfly",
52 target_os = "emscripten",
53 target_os = "espidf",
54 target_os = "freebsd", target_os = "haiku",
56 target_os = "horizon",
57 target_os = "openbsd",
58 target_os = "redox",
59 target_os = "vita",
60 target_os = "wasi",
61)))]
62#[inline]
63pub(crate) fn clock_nanosleep_relative(id: ClockId, request: &Timespec) -> NanosleepRelativeResult {
64 #[cfg(fix_y2038)]
67 {
68 #[cfg(target_env = "gnu")]
69 if let Some(libc_clock_nanosleep) = __clock_nanosleep_time64.get() {
70 let flags = 0;
71 let mut remain = MaybeUninit::<LibcTimespec>::uninit();
72
73 unsafe {
74 return match libc_clock_nanosleep(
75 id as c::clockid_t,
76 flags,
77 &request.clone().into(),
78 remain.as_mut_ptr(),
79 ) {
80 0 => NanosleepRelativeResult::Ok,
81 err if err == io::Errno::INTR.0 => {
82 NanosleepRelativeResult::Interrupted(remain.assume_init().into())
83 }
84 err => NanosleepRelativeResult::Err(io::Errno(err)),
85 };
86 }
87 }
88
89 clock_nanosleep_relative_old(id, request)
90 }
91
92 #[cfg(not(fix_y2038))]
94 unsafe {
95 let flags = 0;
96 let mut remain = MaybeUninit::<Timespec>::uninit();
97
98 match c::clock_nanosleep(
99 id as c::clockid_t,
100 flags,
101 as_libc_timespec_ptr(request),
102 as_libc_timespec_mut_ptr(&mut remain),
103 ) {
104 0 => NanosleepRelativeResult::Ok,
105 err if err == io::Errno::INTR.0 => {
106 NanosleepRelativeResult::Interrupted(remain.assume_init())
107 }
108 err => NanosleepRelativeResult::Err(io::Errno(err)),
109 }
110 }
111}
112
113#[cfg(all(
114 fix_y2038,
115 not(any(
116 apple,
117 target_os = "emscripten",
118 target_os = "haiku",
119 target_os = "horizon",
120 target_os = "vita"
121 ))
122))]
123fn clock_nanosleep_relative_old(
124 id: crate::clockid::ClockId,
125 request: &Timespec,
126) -> NanosleepRelativeResult {
127 let tv_sec = match request.tv_sec.try_into() {
128 Ok(tv_sec) => tv_sec,
129 Err(_) => return NanosleepRelativeResult::Err(io::Errno::OVERFLOW),
130 };
131 let tv_nsec = match request.tv_nsec.try_into() {
132 Ok(tv_nsec) => tv_nsec,
133 Err(_) => return NanosleepRelativeResult::Err(io::Errno::INVAL),
134 };
135 let old_request = c::timespec { tv_sec, tv_nsec };
136 let mut old_remain = MaybeUninit::<c::timespec>::uninit();
137 let flags = 0;
138
139 unsafe {
140 match c::clock_nanosleep(
141 id as c::clockid_t,
142 flags,
143 &old_request,
144 old_remain.as_mut_ptr(),
145 ) {
146 0 => NanosleepRelativeResult::Ok,
147 err if err == io::Errno::INTR.0 => {
148 let old_remain = old_remain.assume_init();
149 let remain = Timespec {
150 tv_sec: old_remain.tv_sec.into(),
151 tv_nsec: old_remain.tv_nsec.into(),
152 };
153 NanosleepRelativeResult::Interrupted(remain)
154 }
155 err => NanosleepRelativeResult::Err(io::Errno(err)),
156 }
157 }
158}
159
160#[cfg(not(any(
161 apple,
162 target_os = "dragonfly",
163 target_os = "emscripten",
164 target_os = "espidf",
165 target_os = "freebsd", target_os = "haiku",
167 target_os = "horizon",
168 target_os = "openbsd",
169 target_os = "redox",
170 target_os = "vita",
171 target_os = "wasi",
172)))]
173#[inline]
174pub(crate) fn clock_nanosleep_absolute(id: ClockId, request: &Timespec) -> io::Result<()> {
175 #[cfg(fix_y2038)]
178 {
179 #[cfg(target_env = "gnu")]
180 if let Some(libc_clock_nanosleep) = __clock_nanosleep_time64.get() {
181 let flags = c::TIMER_ABSTIME;
182 unsafe {
183 return match libc_clock_nanosleep(
184 id as c::clockid_t,
185 flags,
186 &request.clone().into(),
187 core::ptr::null_mut(),
188 ) {
189 0 => Ok(()),
190 err => Err(io::Errno(err)),
191 };
192 }
193 }
194
195 clock_nanosleep_absolute_old(id, request)
196 }
197
198 #[cfg(not(fix_y2038))]
200 {
201 let flags = c::TIMER_ABSTIME;
202
203 match unsafe {
204 c::clock_nanosleep(
205 id as c::clockid_t,
206 flags as _,
207 as_libc_timespec_ptr(request),
208 core::ptr::null_mut(),
209 )
210 } {
211 0 => Ok(()),
212 err => Err(io::Errno(err)),
213 }
214 }
215}
216
217#[cfg(all(
218 fix_y2038,
219 not(any(
220 apple,
221 target_os = "emscripten",
222 target_os = "haiku",
223 target_os = "horizon",
224 target_os = "vita"
225 ))
226))]
227fn clock_nanosleep_absolute_old(id: crate::clockid::ClockId, request: &Timespec) -> io::Result<()> {
228 let flags = c::TIMER_ABSTIME;
229
230 let old_request = c::timespec {
231 tv_sec: request.tv_sec.try_into().map_err(|_| io::Errno::OVERFLOW)?,
232 tv_nsec: request.tv_nsec.try_into().map_err(|_| io::Errno::INVAL)?,
233 };
234 match unsafe {
235 c::clock_nanosleep(
236 id as c::clockid_t,
237 flags,
238 &old_request,
239 core::ptr::null_mut(),
240 )
241 } {
242 0 => Ok(()),
243 err => Err(io::Errno(err)),
244 }
245}
246
247#[cfg(not(target_os = "redox"))]
248#[inline]
249pub(crate) fn nanosleep(request: &Timespec) -> NanosleepRelativeResult {
250 #[cfg(fix_y2038)]
253 {
254 #[cfg(target_env = "gnu")]
255 if let Some(libc_nanosleep) = __nanosleep64.get() {
256 let mut remain = MaybeUninit::<LibcTimespec>::uninit();
257 unsafe {
258 return match ret(libc_nanosleep(&request.clone().into(), remain.as_mut_ptr())) {
259 Ok(()) => NanosleepRelativeResult::Ok,
260 Err(io::Errno::INTR) => {
261 NanosleepRelativeResult::Interrupted(remain.assume_init().into())
262 }
263 Err(err) => NanosleepRelativeResult::Err(err),
264 };
265 }
266 }
267
268 nanosleep_old(request)
269 }
270
271 #[cfg(not(fix_y2038))]
273 unsafe {
274 let mut remain = MaybeUninit::<Timespec>::uninit();
275
276 match ret(c::nanosleep(
277 as_libc_timespec_ptr(request),
278 as_libc_timespec_mut_ptr(&mut remain),
279 )) {
280 Ok(()) => NanosleepRelativeResult::Ok,
281 Err(io::Errno::INTR) => NanosleepRelativeResult::Interrupted(remain.assume_init()),
282 Err(err) => NanosleepRelativeResult::Err(err),
283 }
284 }
285}
286
287#[cfg(fix_y2038)]
288fn nanosleep_old(request: &Timespec) -> NanosleepRelativeResult {
289 let tv_sec = match request.tv_sec.try_into() {
290 Ok(tv_sec) => tv_sec,
291 Err(_) => return NanosleepRelativeResult::Err(io::Errno::OVERFLOW),
292 };
293 let tv_nsec = match request.tv_nsec.try_into() {
294 Ok(tv_nsec) => tv_nsec,
295 Err(_) => return NanosleepRelativeResult::Err(io::Errno::INVAL),
296 };
297 let old_request = c::timespec { tv_sec, tv_nsec };
298 let mut old_remain = MaybeUninit::<c::timespec>::uninit();
299
300 unsafe {
301 match ret(c::nanosleep(&old_request, old_remain.as_mut_ptr())) {
302 Ok(()) => NanosleepRelativeResult::Ok,
303 Err(io::Errno::INTR) => {
304 let old_remain = old_remain.assume_init();
305 let remain = Timespec {
306 tv_sec: old_remain.tv_sec.into(),
307 tv_nsec: old_remain.tv_nsec.into(),
308 };
309 NanosleepRelativeResult::Interrupted(remain)
310 }
311 Err(err) => NanosleepRelativeResult::Err(err),
312 }
313 }
314}
315
316#[cfg(linux_kernel)]
317#[inline]
318#[must_use]
319pub(crate) fn gettid() -> Pid {
320 weak_or_syscall! {
324 fn gettid() via SYS_gettid -> c::pid_t
325 }
326
327 unsafe {
328 let tid = gettid();
329 Pid::from_raw_unchecked(tid)
330 }
331}
332
333#[cfg(linux_kernel)]
334#[inline]
335pub(crate) fn setns(fd: BorrowedFd<'_>, nstype: c::c_int) -> io::Result<c::c_int> {
336 weak_or_syscall! {
339 fn setns(fd: c::c_int, nstype: c::c_int) via SYS_setns -> c::c_int
340 }
341
342 unsafe { ret_c_int(setns(borrowed_fd(fd), nstype)) }
343}
344
345#[cfg(linux_kernel)]
346#[inline]
347pub(crate) unsafe fn unshare(flags: crate::thread::UnshareFlags) -> io::Result<()> {
348 ret(c::unshare(flags.bits() as i32))
349}
350
351#[cfg(linux_kernel)]
352#[inline]
353pub(crate) fn capget(
354 header: &mut linux_raw_sys::general::__user_cap_header_struct,
355 data: &mut [MaybeUninit<linux_raw_sys::general::__user_cap_data_struct>],
356) -> io::Result<()> {
357 syscall! {
358 fn capget(
359 hdrp: *mut linux_raw_sys::general::__user_cap_header_struct,
360 data: *mut linux_raw_sys::general::__user_cap_data_struct
361 ) via SYS_capget -> c::c_int
362 }
363
364 unsafe {
365 ret(capget(
366 as_mut_ptr(header),
367 data.as_mut_ptr()
368 .cast::<linux_raw_sys::general::__user_cap_data_struct>(),
369 ))
370 }
371}
372
373#[cfg(linux_kernel)]
374#[inline]
375pub(crate) fn capset(
376 header: &mut linux_raw_sys::general::__user_cap_header_struct,
377 data: &[linux_raw_sys::general::__user_cap_data_struct],
378) -> io::Result<()> {
379 syscall! {
380 fn capset(
381 hdrp: *mut linux_raw_sys::general::__user_cap_header_struct,
382 data: *const linux_raw_sys::general::__user_cap_data_struct
383 ) via SYS_capset -> c::c_int
384 }
385
386 unsafe { ret(capset(as_mut_ptr(header), data.as_ptr())) }
387}
388
389#[cfg(linux_kernel)]
390#[inline]
391pub(crate) fn setuid_thread(uid: crate::ugid::Uid) -> io::Result<()> {
392 syscall! {
393 fn setuid(uid: c::uid_t) via SYS_setuid -> c::c_int
394 }
395
396 unsafe { ret(setuid(uid.as_raw())) }
397}
398
399#[cfg(linux_kernel)]
400#[inline]
401pub(crate) fn setresuid_thread(
402 ruid: Option<crate::ugid::Uid>,
403 euid: Option<crate::ugid::Uid>,
404 suid: Option<crate::ugid::Uid>,
405) -> io::Result<()> {
406 #[cfg(any(target_arch = "x86", target_arch = "arm", target_arch = "sparc"))]
407 const SYS: c::c_long = c::SYS_setresuid32 as c::c_long;
408 #[cfg(not(any(target_arch = "x86", target_arch = "arm", target_arch = "sparc")))]
409 const SYS: c::c_long = c::SYS_setresuid as c::c_long;
410
411 syscall! {
412 fn setresuid(ruid: c::uid_t, euid: c::uid_t, suid: c::uid_t) via SYS -> c::c_int
413 }
414
415 unsafe {
416 ret(setresuid(
417 ruid.map_or(-1_i32 as u32, |x| x.as_raw()),
418 euid.map_or(-1_i32 as u32, |x| x.as_raw()),
419 suid.map_or(-1_i32 as u32, |x| x.as_raw()),
420 ))
421 }
422}
423
424#[cfg(linux_kernel)]
425#[inline]
426pub(crate) fn setgid_thread(gid: crate::ugid::Gid) -> io::Result<()> {
427 syscall! {
428 fn setgid(gid: c::gid_t) via SYS_setgid -> c::c_int
429 }
430
431 unsafe { ret(setgid(gid.as_raw())) }
432}
433
434#[cfg(linux_kernel)]
435#[inline]
436pub(crate) fn setresgid_thread(
437 rgid: Option<crate::ugid::Gid>,
438 egid: Option<crate::ugid::Gid>,
439 sgid: Option<crate::ugid::Gid>,
440) -> io::Result<()> {
441 #[cfg(any(target_arch = "x86", target_arch = "arm", target_arch = "sparc"))]
442 const SYS: c::c_long = c::SYS_setresgid32 as c::c_long;
443 #[cfg(not(any(target_arch = "x86", target_arch = "arm", target_arch = "sparc")))]
444 const SYS: c::c_long = c::SYS_setresgid as c::c_long;
445
446 syscall! {
447 fn setresgid(rgid: c::gid_t, egid: c::gid_t, sgid: c::gid_t) via SYS -> c::c_int
448 }
449
450 unsafe {
451 ret(setresgid(
452 rgid.map_or(-1_i32 as u32, |x| x.as_raw()),
453 egid.map_or(-1_i32 as u32, |x| x.as_raw()),
454 sgid.map_or(-1_i32 as u32, |x| x.as_raw()),
455 ))
456 }
457}
458
459#[cfg(linux_kernel)]
463pub(crate) unsafe fn futex_val2(
464 uaddr: *const AtomicU32,
465 op: super::futex::Operation,
466 flags: futex::Flags,
467 val: u32,
468 val2: u32,
469 uaddr2: *const AtomicU32,
470 val3: u32,
471) -> io::Result<usize> {
472 let timeout = val2 as usize as *const Timespec;
479
480 #[cfg(all(
481 target_pointer_width = "32",
482 not(any(target_arch = "aarch64", target_arch = "x86_64"))
483 ))]
484 {
485 #[allow(non_upper_case_globals)]
487 const SYS_futex_time64: i32 = linux_raw_sys::general::__NR_futex_time64 as i32;
488
489 syscall! {
490 fn futex_time64(
491 uaddr: *const AtomicU32,
492 futex_op: c::c_int,
493 val: u32,
494 timeout: *const Timespec,
495 uaddr2: *const AtomicU32,
496 val3: u32
497 ) via SYS_futex_time64 -> c::ssize_t
498 }
499
500 ret_usize(futex_time64(
501 uaddr,
502 op as i32 | flags.bits() as i32,
503 val,
504 timeout,
505 uaddr2,
506 val3,
507 ))
508 }
509
510 #[cfg(any(
511 target_pointer_width = "64",
512 target_arch = "aarch64",
513 target_arch = "x86_64"
514 ))]
515 {
516 syscall! {
517 fn futex(
518 uaddr: *const AtomicU32,
519 futex_op: c::c_int,
520 val: u32,
521 timeout: *const Timespec,
522 uaddr2: *const AtomicU32,
523 val3: u32
524 ) via SYS_futex -> c::c_long
525 }
526
527 ret_usize(futex(
528 uaddr,
529 op as i32 | flags.bits() as i32,
530 val,
531 timeout.cast(),
532 uaddr2,
533 val3,
534 ) as isize)
535 }
536}
537
538#[cfg(linux_kernel)]
542pub(crate) unsafe fn futex_timeout(
543 uaddr: *const AtomicU32,
544 op: super::futex::Operation,
545 flags: futex::Flags,
546 val: u32,
547 timeout: Option<&Timespec>,
548 uaddr2: *const AtomicU32,
549 val3: u32,
550) -> io::Result<usize> {
551 #[cfg(all(
552 target_pointer_width = "32",
553 not(any(target_arch = "aarch64", target_arch = "x86_64"))
554 ))]
555 {
556 #[allow(non_upper_case_globals)]
558 const SYS_futex_time64: i32 = linux_raw_sys::general::__NR_futex_time64 as i32;
559
560 syscall! {
561 fn futex_time64(
562 uaddr: *const AtomicU32,
563 futex_op: c::c_int,
564 val: u32,
565 timeout: *const Timespec,
566 uaddr2: *const AtomicU32,
567 val3: u32
568 ) via SYS_futex_time64 -> c::ssize_t
569 }
570
571 ret_usize(futex_time64(
572 uaddr,
573 op as i32 | flags.bits() as i32,
574 val,
575 option_as_ptr(timeout),
576 uaddr2,
577 val3,
578 ))
579 .or_else(|err| {
580 if err == io::Errno::NOSYS {
582 futex_old_timespec(uaddr, op, flags, val, timeout, uaddr2, val3)
583 } else {
584 Err(err)
585 }
586 })
587 }
588
589 #[cfg(any(
590 target_pointer_width = "64",
591 target_arch = "aarch64",
592 target_arch = "x86_64"
593 ))]
594 {
595 syscall! {
596 fn futex(
597 uaddr: *const AtomicU32,
598 futex_op: c::c_int,
599 val: u32,
600 timeout: *const Timespec,
601 uaddr2: *const AtomicU32,
602 val3: u32
603 ) via SYS_futex -> c::c_long
604 }
605
606 ret_usize(futex(
607 uaddr,
608 op as i32 | flags.bits() as i32,
609 val,
610 option_as_ptr(timeout).cast(),
611 uaddr2,
612 val3,
613 ) as isize)
614 }
615}
616
617#[cfg(linux_kernel)]
621#[cfg(all(
622 target_pointer_width = "32",
623 not(any(target_arch = "aarch64", target_arch = "x86_64"))
624))]
625unsafe fn futex_old_timespec(
626 uaddr: *const AtomicU32,
627 op: super::futex::Operation,
628 flags: futex::Flags,
629 val: u32,
630 timeout: Option<&Timespec>,
631 uaddr2: *const AtomicU32,
632 val3: u32,
633) -> io::Result<usize> {
634 syscall! {
635 fn futex(
636 uaddr: *const AtomicU32,
637 futex_op: c::c_int,
638 val: u32,
639 timeout: *const linux_raw_sys::general::__kernel_old_timespec,
640 uaddr2: *const AtomicU32,
641 val3: u32
642 ) via SYS_futex -> c::c_long
643 }
644
645 let old_timeout = if let Some(timeout) = timeout {
646 Some(linux_raw_sys::general::__kernel_old_timespec {
647 tv_sec: timeout.tv_sec.try_into().map_err(|_| io::Errno::INVAL)?,
648 tv_nsec: timeout.tv_nsec.try_into().map_err(|_| io::Errno::INVAL)?,
649 })
650 } else {
651 None
652 };
653 ret_usize(futex(
654 uaddr,
655 op as i32 | flags.bits() as i32,
656 val,
657 option_as_ptr(old_timeout.as_ref()),
658 uaddr2,
659 val3,
660 ) as isize)
661}
662
663#[cfg(linux_kernel)]
664pub(crate) fn futex_waitv(
665 waiters: &[futex::Wait],
666 flags: futex::WaitvFlags,
667 timeout: Option<&Timespec>,
668 clockid: ClockId,
669) -> io::Result<usize> {
670 use futex::Wait as FutexWait;
671 use linux_raw_sys::general::__kernel_clockid_t as clockid_t;
672 syscall! {
673 fn futex_waitv(
674 waiters: *const FutexWait,
675 nr_futexes: c::c_uint,
676 flags: c::c_uint,
677 timeout: *const Timespec,
678 clockid: clockid_t
679 ) via SYS_futex_waitv -> c::c_int
680 }
681
682 let nr_futexes: c::c_uint = waiters.len().try_into().map_err(|_| io::Errno::INVAL)?;
683
684 unsafe {
685 ret_c_int(futex_waitv(
686 waiters.as_ptr(),
687 nr_futexes,
688 flags.bits(),
689 option_as_ptr(timeout).cast(),
690 clockid as _,
691 ))
692 .map(|n| n as usize)
693 }
694}
695
696#[cfg(linux_kernel)]
697#[inline]
698pub(crate) fn setgroups_thread(groups: &[crate::ugid::Gid]) -> io::Result<()> {
699 syscall! {
700 fn setgroups(size: c::size_t, list: *const c::gid_t) via SYS_setgroups -> c::c_int
701 }
702 ret(unsafe { setgroups(groups.len(), groups.as_ptr().cast()) })
703}
704
705#[cfg(any(linux_kernel, target_os = "dragonfly"))]
706#[inline]
707pub(crate) fn sched_getcpu() -> usize {
708 let r = unsafe { c::sched_getcpu() };
709 debug_assert!(r >= 0);
710 r as usize
711}
712
713#[cfg(any(freebsdlike, linux_kernel, target_os = "fuchsia"))]
714#[inline]
715pub(crate) fn sched_getaffinity(pid: Option<Pid>, cpuset: &mut RawCpuSet) -> io::Result<()> {
716 unsafe {
717 ret(c::sched_getaffinity(
718 Pid::as_raw(pid) as _,
719 core::mem::size_of::<RawCpuSet>(),
720 cpuset,
721 ))
722 }
723}
724
725#[cfg(any(freebsdlike, linux_kernel, target_os = "fuchsia"))]
726#[inline]
727pub(crate) fn sched_setaffinity(pid: Option<Pid>, cpuset: &RawCpuSet) -> io::Result<()> {
728 unsafe {
729 ret(c::sched_setaffinity(
730 Pid::as_raw(pid) as _,
731 core::mem::size_of::<RawCpuSet>(),
732 cpuset,
733 ))
734 }
735}
736
737#[inline]
738pub(crate) fn sched_yield() {
739 unsafe {
740 let _ = c::sched_yield();
741 }
742}
743
744#[cfg(linux_kernel)]
747syscall! {
748 fn membarrier_all(
749 cmd: c::c_int,
750 flags: c::c_uint
751 ) via SYS_membarrier -> c::c_int
752}
753
754#[cfg(linux_kernel)]
755pub(crate) fn membarrier_query() -> MembarrierQuery {
756 const MEMBARRIER_CMD_QUERY: u32 = 0;
761 unsafe {
762 match ret_u32(membarrier_all(MEMBARRIER_CMD_QUERY as i32, 0)) {
763 Ok(query) => MembarrierQuery::from_bits_retain(query),
764 Err(_) => MembarrierQuery::empty(),
765 }
766 }
767}
768
769#[cfg(linux_kernel)]
770pub(crate) fn membarrier(cmd: MembarrierCommand) -> io::Result<()> {
771 unsafe { ret(membarrier_all(cmd as i32, 0)) }
772}
773
774#[cfg(linux_kernel)]
775pub(crate) fn membarrier_cpu(cmd: MembarrierCommand, cpu: Cpuid) -> io::Result<()> {
776 const MEMBARRIER_CMD_FLAG_CPU: u32 = 1;
777
778 syscall! {
779 fn membarrier_cpu(
780 cmd: c::c_int,
781 flags: c::c_uint,
782 cpu_id: c::c_int
783 ) via SYS_membarrier -> c::c_int
784 }
785
786 unsafe {
787 ret(membarrier_cpu(
788 cmd as i32,
789 MEMBARRIER_CMD_FLAG_CPU,
790 bitcast!(cpu.as_raw()),
791 ))
792 }
793}