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(bits: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}
93