1 //! The Linux `membarrier` syscall.
2
3 use crate::process::Cpuid;
4 use crate::{backend, io};
5
6 pub use backend::process::types::MembarrierCommand;
7
8 #[cfg(linux_kernel)]
9 bitflags::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)]
44 impl MembarrierQuery {
45 /// Test whether this query result contains the given command.
46 #[inline]
contains_command(self, cmd: MembarrierCommand) -> bool47 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")]
membarrier_query() -> MembarrierQuery67 pub 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]
membarrier(cmd: MembarrierCommand) -> io::Result<()>78 pub 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]
membarrier_cpu(cmd: MembarrierCommand, cpu: Cpuid) -> io::Result<()>90 pub fn membarrier_cpu(cmd: MembarrierCommand, cpu: Cpuid) -> io::Result<()> {
91 backend::process::syscalls::membarrier_cpu(cmd, cpu)
92 }
93