blob: 8709337bcd98f64432af176fb9caaf47af246291 [file] [log] [blame]
//! The Linux `membarrier` syscall.
//!
//! # Safety
//!
//! This file defines an enum and a bitflags type that represent the same
//! set of values and are kept in sync.
#![allow(unsafe_code)]
use crate::process::Cpuid;
use crate::{backend, io};
pub use backend::process::types::MembarrierCommand;
#[cfg(any(target_os = "android", target_os = "linux"))]
bitflags::bitflags! {
/// A result from [`membarrier_query`].
///
/// These flags correspond to values of [`MembarrierCommand`] which are
/// supported in the OS.
pub struct MembarrierQuery: u32 {
/// `MEMBARRIER_CMD_GLOBAL`
#[doc(alias = "SHARED")]
#[doc(alias = "MEMBARRIER_CMD_SHARED")]
const GLOBAL = MembarrierCommand::Global as _;
/// `MEMBARRIER_CMD_GLOBAL_EXPEDITED`
const GLOBAL_EXPEDITED = MembarrierCommand::GlobalExpedited as _;
/// `MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED`
const REGISTER_GLOBAL_EXPEDITED = MembarrierCommand::RegisterGlobalExpedited as _;
/// `MEMBARRIER_CMD_PRIVATE_EXPEDITED`
const PRIVATE_EXPEDITED = MembarrierCommand::PrivateExpedited as _;
/// `MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED`
const REGISTER_PRIVATE_EXPEDITED = MembarrierCommand::RegisterPrivateExpedited as _;
/// `MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE`
const PRIVATE_EXPEDITED_SYNC_CORE = MembarrierCommand::PrivateExpeditedSyncCore as _;
/// `MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE`
const REGISTER_PRIVATE_EXPEDITED_SYNC_CORE = MembarrierCommand::RegisterPrivateExpeditedSyncCore as _;
/// `MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ` (since Linux 5.10)
const PRIVATE_EXPEDITED_RSEQ = MembarrierCommand::PrivateExpeditedRseq as _;
/// `MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ` (since Linux 5.10)
const REGISTER_PRIVATE_EXPEDITED_RSEQ = MembarrierCommand::RegisterPrivateExpeditedRseq as _;
}
}
#[cfg(any(target_os = "android", target_os = "linux"))]
impl MembarrierQuery {
/// Test whether this query result contains the given command.
#[inline]
pub fn contains_command(self, cmd: MembarrierCommand) -> bool {
// SAFETY: `MembarrierCommand` is an enum that only contains values
// also valid in `MembarrierQuery`.
self.contains(unsafe { Self::from_bits_unchecked(cmd as _) })
}
}
/// `membarrier(MEMBARRIER_CMD_QUERY, 0, 0)`—Query the supported `membarrier`
/// commands.
///
/// This function doesn't return a `Result` because it always succeeds; if
/// the underlying OS doesn't support the `membarrier` syscall, it returns
/// an empty `MembarrierQuery` value.
///
/// # References
/// - [Linux]
///
/// [Linux]: https://man7.org/linux/man-pages/man2/membarrier.2.html
#[inline]
#[doc(alias = "MEMBARRIER_CMD_QUERY")]
pub fn membarrier_query() -> MembarrierQuery {
backend::process::syscalls::membarrier_query()
}
/// `membarrier(cmd, 0, 0)`—Perform a memory barrier.
///
/// # References
/// - [Linux]
///
/// [Linux]: https://man7.org/linux/man-pages/man2/membarrier.2.html
#[inline]
pub fn membarrier(cmd: MembarrierCommand) -> io::Result<()> {
backend::process::syscalls::membarrier(cmd)
}
/// `membarrier(cmd, MEMBARRIER_CMD_FLAG_CPU, cpu)`—Perform a memory barrier
/// with a specific CPU.
///
/// # References
/// - [Linux]
///
/// [Linux]: https://man7.org/linux/man-pages/man2/membarrier.2.html
#[inline]
pub fn membarrier_cpu(cmd: MembarrierCommand, cpu: Cpuid) -> io::Result<()> {
backend::process::syscalls::membarrier_cpu(cmd, cpu)
}