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