starnix_types/
futex_address.rs1use starnix_uapi::errors::{Errno, error};
9use starnix_uapi::restricted_aspace::RESTRICTED_ASPACE_RANGE;
10use starnix_uapi::user_address::UserAddress;
11use std::fmt;
12use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
13use zx::sys::zx_vaddr_t;
14
15#[derive(
16 Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, IntoBytes, KnownLayout, FromBytes, Immutable,
17)]
18#[repr(transparent)]
19pub struct FutexAddress(zx_vaddr_t);
20
21impl FutexAddress {
22 pub fn ptr(&self) -> zx_vaddr_t {
23 self.0
24 }
25}
26
27impl TryFrom<usize> for FutexAddress {
28 type Error = Errno;
29
30 fn try_from(value: usize) -> Result<Self, Errno> {
31 if value % 4 != 0 {
33 return error!(EINVAL);
34 }
35 if !RESTRICTED_ASPACE_RANGE.contains(&value) {
37 return error!(EFAULT);
38 }
39 Ok(FutexAddress(value))
40 }
41}
42
43impl TryFrom<UserAddress> for FutexAddress {
44 type Error = Errno;
45
46 fn try_from(value: UserAddress) -> Result<Self, Errno> {
47 value.ptr().try_into()
48 }
49}
50
51impl Into<UserAddress> for FutexAddress {
52 fn into(self) -> UserAddress {
53 UserAddress::const_from(self.ptr() as u64)
54 }
55}
56
57impl fmt::Display for FutexAddress {
58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 write!(f, "{:#x}", self.0)
60 }
61}
62
63impl fmt::Debug for FutexAddress {
64 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65 f.debug_tuple("FutexAddress").field(&format_args!("{:#x}", self.0)).finish()
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72 use starnix_uapi::restricted_aspace::RESTRICTED_ASPACE_HIGHEST_ADDRESS;
73
74 #[::fuchsia::test]
75 fn test_misaligned_address() {
76 let result = FutexAddress::try_from(3);
77 assert!(result.is_err());
78 }
79
80 #[::fuchsia::test]
81 fn test_normal_mode_address() {
82 let result = FutexAddress::try_from(RESTRICTED_ASPACE_HIGHEST_ADDRESS);
83 assert!(result.is_err());
84 }
85
86 #[::fuchsia::test]
87 fn test_maximal_address() {
88 let result = FutexAddress::try_from(usize::max_value());
89 assert!(result.is_err());
90 }
91
92 #[::fuchsia::test]
93 fn test_regular_restricted_address() {
94 let result = FutexAddress::try_from(2 * 1 << 20);
96 assert!(result.is_ok());
97 assert_eq!(result.unwrap().ptr(), 2 * 1 << 20);
98 }
99}