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