1use crate::util::constants::*;
2use crate::util::heap::layout::vm_layout::*;
3use crate::util::Address;
4
5pub fn is_address_aligned(addr: Address) -> bool {
7 addr.is_aligned_to(BYTES_IN_ADDRESS)
8}
9
10pub fn page_align_down(address: Address) -> Address {
12 address.align_down(BYTES_IN_PAGE)
13}
14
15pub fn is_page_aligned(address: Address) -> bool {
17 address.is_aligned_to(BYTES_IN_PAGE)
18}
19
20pub const fn chunk_align_up(addr: Address) -> Address {
22 addr.align_up(BYTES_IN_CHUNK)
23}
24
25pub const fn chunk_align_down(addr: Address) -> Address {
27 addr.align_down(BYTES_IN_CHUNK)
28}
29
30pub fn bytes_to_chunks_up(bytes: usize) -> usize {
32 (bytes + BYTES_IN_CHUNK - 1) >> LOG_BYTES_IN_CHUNK
33}
34
35pub fn address_to_chunk_index(addr: Address) -> usize {
37 addr >> LOG_BYTES_IN_CHUNK
38}
39
40pub fn chunk_index_to_address(chunk: usize) -> Address {
42 unsafe { Address::from_usize(chunk << LOG_BYTES_IN_CHUNK) }
43}
44
45pub const fn raw_align_up(val: usize, align: usize) -> usize {
47 val.wrapping_add(align).wrapping_sub(1) & !align.wrapping_sub(1)
49}
50
51pub const fn raw_align_down(val: usize, align: usize) -> usize {
53 val & !align.wrapping_sub(1)
54}
55
56pub const fn raw_is_aligned(val: usize, align: usize) -> bool {
58 val & align.wrapping_sub(1) == 0
59}
60
61pub fn pages_to_bytes(pages: usize) -> usize {
63 pages << LOG_BYTES_IN_PAGE
64}
65
66pub fn bytes_to_pages_up(bytes: usize) -> usize {
68 raw_align_up(bytes, BYTES_IN_PAGE) >> LOG_BYTES_IN_PAGE
69}
70
71pub fn bytes_to_formatted_string(bytes: usize) -> String {
73 const UNITS: [&str; 6] = ["B", "KiB", "MiB", "GiB", "TiB", "PiB"];
74 let mut i = 0;
75 let mut num = bytes;
76 while i < UNITS.len() - 1 {
77 let new_num = num >> 10;
78 if new_num == 0 {
79 return format!("{}{}", num, UNITS[i]);
80 }
81 num = new_num;
82 i += 1;
83 }
84 format!("{}{}", num, UNITS.last().unwrap())
85}
86
87pub const fn rshift_align_up(num: usize, bits: usize) -> usize {
93 (num + ((1 << bits) - 1)) >> bits
94}
95
96#[cfg(test)]
97mod tests {
98 use crate::util::conversions::*;
99 use crate::util::Address;
100
101 #[test]
102 fn test_page_align() {
103 let addr = unsafe { Address::from_usize(0x2345_6789) };
104 assert_eq!(page_align_down(addr), unsafe {
105 Address::from_usize(0x2345_6000)
106 });
107 assert!(!is_page_aligned(addr));
108 assert!(is_page_aligned(page_align_down(addr)));
109 }
110
111 #[test]
112 fn test_chunk_align() {
113 let addr = unsafe { Address::from_usize(0x2345_6789) };
114 assert_eq!(chunk_align_down(addr), unsafe {
115 Address::from_usize(0x2340_0000)
116 });
117 assert_eq!(chunk_align_up(addr), unsafe {
118 Address::from_usize(0x2380_0000)
119 });
120 }
121
122 #[test]
123 fn test_bytes_to_formatted_string() {
124 assert_eq!(bytes_to_formatted_string(0), "0B");
125 assert_eq!(bytes_to_formatted_string(1023), "1023B");
126 assert_eq!(bytes_to_formatted_string(1024), "1KiB");
127 assert_eq!(bytes_to_formatted_string(1025), "1KiB");
128 assert_eq!(bytes_to_formatted_string(1 << 20), "1MiB");
129 assert_eq!(bytes_to_formatted_string(1 << 30), "1GiB");
130 #[cfg(target_pointer_width = "64")]
131 {
132 assert_eq!(bytes_to_formatted_string(1 << 40), "1TiB");
133 assert_eq!(bytes_to_formatted_string(1 << 50), "1PiB");
134 assert_eq!(bytes_to_formatted_string(1 << 60), "1024PiB");
135 assert_eq!(bytes_to_formatted_string(1 << 63), "8192PiB");
136 }
137 }
138}