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