rustix/process/
membarrier.rs

1//! The Linux `membarrier` syscall.
2
3use crate::process::Cpuid;
4use crate::{backend, io};
5
6pub use backend::process::types::MembarrierCommand;
7
8#[cfg(linux_kernel)]
9bitflags::bitflags! {
10    /// A result from [`membarrier_query`].
11    ///
12    /// These flags correspond to values of [`MembarrierCommand`] which are
13    /// supported in the OS.
14    #[repr(transparent)]
15    #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
16    pub struct MembarrierQuery: u32 {
17        /// `MEMBARRIER_CMD_GLOBAL` (also known as `MEMBARRIER_CMD_SHARED`)
18        #[doc(alias = "SHARED")]
19        #[doc(alias = "MEMBARRIER_CMD_SHARED")]
20        const GLOBAL = MembarrierCommand::Global as _;
21        /// `MEMBARRIER_CMD_GLOBAL_EXPEDITED`
22        const GLOBAL_EXPEDITED = MembarrierCommand::GlobalExpedited as _;
23        /// `MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED`
24        const REGISTER_GLOBAL_EXPEDITED = MembarrierCommand::RegisterGlobalExpedited as _;
25        /// `MEMBARRIER_CMD_PRIVATE_EXPEDITED`
26        const PRIVATE_EXPEDITED = MembarrierCommand::PrivateExpedited as _;
27        /// `MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED`
28        const REGISTER_PRIVATE_EXPEDITED = MembarrierCommand::RegisterPrivateExpedited as _;
29        /// `MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE`
30        const PRIVATE_EXPEDITED_SYNC_CORE = MembarrierCommand::PrivateExpeditedSyncCore as _;
31        /// `MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE`
32        const REGISTER_PRIVATE_EXPEDITED_SYNC_CORE = MembarrierCommand::RegisterPrivateExpeditedSyncCore as _;
33        /// `MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ` (since Linux 5.10)
34        const PRIVATE_EXPEDITED_RSEQ = MembarrierCommand::PrivateExpeditedRseq as _;
35        /// `MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ` (since Linux 5.10)
36        const REGISTER_PRIVATE_EXPEDITED_RSEQ = MembarrierCommand::RegisterPrivateExpeditedRseq as _;
37
38        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
39        const _ = !0;
40    }
41}
42
43#[cfg(linux_kernel)]
44impl MembarrierQuery {
45    /// Test whether this query result contains the given command.
46    #[inline]
47    pub fn contains_command(self, cmd: MembarrierCommand) -> bool {
48        // `MembarrierCommand` is an enum that only contains values also valid
49        // in `MembarrierQuery`.
50        self.contains(Self::from_bits_retain(cmd as _))
51    }
52}
53
54/// `membarrier(MEMBARRIER_CMD_QUERY, 0, 0)`—Query the supported `membarrier`
55/// commands.
56///
57/// This function doesn't return a `Result` because it always succeeds; if the
58/// underlying OS doesn't support the `membarrier` syscall, it returns an empty
59/// `MembarrierQuery` value.
60///
61/// # References
62///  - [Linux]
63///
64/// [Linux]: https://man7.org/linux/man-pages/man2/membarrier.2.html
65#[inline]
66#[doc(alias = "MEMBARRIER_CMD_QUERY")]
67pub fn membarrier_query() -> MembarrierQuery {
68    backend::process::syscalls::membarrier_query()
69}
70
71/// `membarrier(cmd, 0, 0)`—Perform a memory barrier.
72///
73/// # References
74///  - [Linux]
75///
76/// [Linux]: https://man7.org/linux/man-pages/man2/membarrier.2.html
77#[inline]
78pub fn membarrier(cmd: MembarrierCommand) -> io::Result<()> {
79    backend::process::syscalls::membarrier(cmd)
80}
81
82/// `membarrier(cmd, MEMBARRIER_CMD_FLAG_CPU, cpu)`—Perform a memory barrier
83/// with a specific CPU.
84///
85/// # References
86///  - [Linux]
87///
88/// [Linux]: https://man7.org/linux/man-pages/man2/membarrier.2.html
89#[inline]
90pub fn membarrier_cpu(cmd: MembarrierCommand, cpu: Cpuid) -> io::Result<()> {
91    backend::process::syscalls::membarrier_cpu(cmd, cpu)
92}