mirror of
https://github.com/XunilGroup/XunilOS.git
synced 2026-04-25 11:49:03 +02:00
Add a usermode address space which can be switched to, make
FRAME_ALLOCATOR global, make XunilFrameAllocator not hold Limine entries so it can be used without lifetimes, implement the process struct, add user heap by giving back heap_start from ELF and adding sbrk syscall, align ELF loading in userspace_stub, implement lots of libc functions in libxunil, remove x86_64 dependency from libxunil, add malloc and all required heap functions to libxunil and more syscall numbers, add a util file to libxunil, add build scripts for libxunil and doomgeneric
This commit is contained in:
59
user/libxunil/Cargo.lock
generated
59
user/libxunil/Cargo.lock
generated
@@ -2,52 +2,33 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "bit_field"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
|
||||
|
||||
[[package]]
|
||||
name = "const_fn"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "413d67b29ef1021b4d60f4aa1e925ca031751e213832b4b1d588fae623c05c60"
|
||||
|
||||
[[package]]
|
||||
name = "libxunil"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"x86_64",
|
||||
"spin",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.22"
|
||||
name = "lock_api"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
||||
|
||||
[[package]]
|
||||
name = "volatile"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "442887c63f2c839b346c192d047a7c87e73d0689c9157b00b53dcc27dd5ea793"
|
||||
|
||||
[[package]]
|
||||
name = "x86_64"
|
||||
version = "0.15.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7841fa0098ceb15c567d93d3fae292c49e10a7662b4936d5f6a9728594555ba"
|
||||
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
|
||||
dependencies = [
|
||||
"bit_field",
|
||||
"bitflags",
|
||||
"const_fn",
|
||||
"rustversion",
|
||||
"volatile",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
]
|
||||
|
||||
@@ -11,8 +11,8 @@ crate-type = ["staticlib"]
|
||||
panic = "abort"
|
||||
opt-level = "s"
|
||||
|
||||
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
||||
x86_64 = "0.15.4"
|
||||
[dependencies]
|
||||
spin = "0.10.0"
|
||||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
use core::ptr::null_mut;
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn fopen(path: *const u8, mode: *const u8) -> *mut u8 {
|
||||
null_mut()
|
||||
0x10 as *mut u8
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
|
||||
94
user/libxunil/src/heap.rs
Normal file
94
user/libxunil/src/heap.rs
Normal file
@@ -0,0 +1,94 @@
|
||||
use spin::mutex::Mutex;
|
||||
|
||||
use crate::util::align_up;
|
||||
|
||||
pub const HEAP_START: usize = 0x_4444_4444_0000;
|
||||
pub const HEAP_SIZE: usize = 256 * 1024 * 1024; // 256 MiB
|
||||
|
||||
pub struct LinkedNode {
|
||||
pub size: usize,
|
||||
pub next: Option<&'static mut LinkedNode>,
|
||||
}
|
||||
|
||||
impl LinkedNode {
|
||||
pub const fn new(size: usize) -> LinkedNode {
|
||||
LinkedNode { size, next: None }
|
||||
}
|
||||
|
||||
pub fn start_addr(&self) -> usize {
|
||||
self as *const Self as usize
|
||||
}
|
||||
|
||||
pub fn end_addr(&self) -> usize {
|
||||
self.start_addr() + self.size
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LinkedListAllocator {
|
||||
head: LinkedNode,
|
||||
}
|
||||
|
||||
impl LinkedListAllocator {
|
||||
pub const fn new() -> LinkedListAllocator {
|
||||
Self {
|
||||
head: LinkedNode::new(0),
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn add_free_memory_region(&mut self, start: usize, size: usize) {
|
||||
assert_eq!(align_up(start, core::mem::align_of::<LinkedNode>()), start); // Check if we are up at least 1 LinkedNode size
|
||||
assert!(size >= core::mem::size_of::<LinkedNode>()); // check if we have enough space for a LinkedNode
|
||||
|
||||
let mut linked_node = LinkedNode::new(size);
|
||||
linked_node.next = self.head.next.take();
|
||||
|
||||
let linked_node_ptr = start as *mut LinkedNode; // Treat the start memory region as a LinkedNode type
|
||||
unsafe {
|
||||
linked_node_ptr.write(linked_node); // write the data, very risky
|
||||
self.head.next = Some(&mut *linked_node_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find_region(
|
||||
&mut self,
|
||||
size: usize,
|
||||
align: usize,
|
||||
) -> Option<(&'static mut LinkedNode, usize)> {
|
||||
let mut current = &mut self.head;
|
||||
|
||||
while let Some(ref mut region) = current.next {
|
||||
if let Ok(alloc_start) = Self::alloc_from_region(®ion, size, align) {
|
||||
let next = region.next.take();
|
||||
let ret = Some((current.next.take().unwrap(), alloc_start));
|
||||
current.next = next;
|
||||
|
||||
return ret;
|
||||
} else {
|
||||
current = current.next.as_mut().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn alloc_from_region(region: &LinkedNode, size: usize, align: usize) -> Result<usize, ()> {
|
||||
let alloc_start = align_up(region.start_addr() + core::mem::size_of::<usize>(), align);
|
||||
let alloc_end = (alloc_start - core::mem::size_of::<usize>())
|
||||
.checked_add(size)
|
||||
.ok_or(())?; // check for overflows
|
||||
|
||||
if alloc_end > region.end_addr() {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
let excess_size = region.end_addr() - alloc_end;
|
||||
if excess_size > 0 && excess_size < core::mem::size_of::<LinkedNode>() {
|
||||
// if the remaining space is not enough for another LinkedNode, skip this region.
|
||||
return Err(());
|
||||
}
|
||||
|
||||
Ok(alloc_start)
|
||||
}
|
||||
}
|
||||
|
||||
pub static ALLOCATOR: Mutex<LinkedListAllocator> = Mutex::new(LinkedListAllocator::new());
|
||||
@@ -1,25 +1,27 @@
|
||||
#![no_std]
|
||||
#![feature(c_variadic)]
|
||||
|
||||
use core::ptr::null;
|
||||
use core::ptr::{null, null_mut};
|
||||
|
||||
use crate::syscall::syscall3;
|
||||
use crate::{
|
||||
mem::{malloc, memcpy, memset},
|
||||
syscall::{EXIT, WRITE, syscall3},
|
||||
};
|
||||
|
||||
pub mod file;
|
||||
pub mod heap;
|
||||
pub mod mem;
|
||||
pub mod syscall;
|
||||
|
||||
const SYS_EXIT: usize = 1;
|
||||
const SYS_WRITE: usize = 60;
|
||||
pub mod util;
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn write(fd: i64, buf: *const u8, count: usize) -> isize {
|
||||
unsafe { syscall3(SYS_WRITE, fd as usize, buf as usize, count) }
|
||||
unsafe { syscall3(WRITE, fd as usize, buf as usize, count) }
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn exit(code: i64) -> ! {
|
||||
unsafe { syscall3(SYS_EXIT, code as usize, 0, 0) };
|
||||
unsafe { syscall3(EXIT, code as usize, 0, 0) };
|
||||
loop {}
|
||||
}
|
||||
|
||||
@@ -53,7 +55,7 @@ extern "C" fn abs(n: i64) -> i64 {
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn printf(format: *const u8, args: ...) {
|
||||
unsafe { syscall3(SYS_WRITE, 1, format as usize, strlen(format)) };
|
||||
unsafe { syscall3(WRITE, 1, format as usize, strlen(format)) };
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
@@ -61,6 +63,10 @@ extern "C" fn atoi(mut c: *const u8) -> i64 {
|
||||
let mut value: i64 = 0;
|
||||
let mut sign: i64 = 1;
|
||||
unsafe {
|
||||
while (*c).is_ascii_whitespace() {
|
||||
c = c.add(1);
|
||||
}
|
||||
|
||||
if (*c) == b'+' || (*c) == b'-' {
|
||||
if *c == b'-' {
|
||||
sign = -1;
|
||||
@@ -77,9 +83,83 @@ extern "C" fn atoi(mut c: *const u8) -> i64 {
|
||||
value * sign
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn pow10_i32(exp: i32) -> f64 {
|
||||
let mut e = exp;
|
||||
let mut scale: f64 = 1.0;
|
||||
|
||||
if e > 0 {
|
||||
while e > 0 {
|
||||
scale *= 10.0;
|
||||
e -= 1;
|
||||
}
|
||||
} else if e < 0 {
|
||||
while e < 0 {
|
||||
scale *= 0.1;
|
||||
e += 1;
|
||||
}
|
||||
}
|
||||
|
||||
scale
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn atof(mut c: *const u8) -> f64 {
|
||||
0.0
|
||||
let mut sign: f64 = 1.0;
|
||||
unsafe {
|
||||
while (*c).is_ascii_whitespace() {
|
||||
c = c.add(1);
|
||||
}
|
||||
|
||||
if (*c) == b'+' || (*c) == b'-' {
|
||||
if *c == b'-' {
|
||||
sign = -1.0;
|
||||
}
|
||||
c = c.add(1);
|
||||
}
|
||||
|
||||
let mut int_part: i64 = 0;
|
||||
while (*c).is_ascii_digit() {
|
||||
int_part = int_part * 10 + ((*c) - b'0') as i64;
|
||||
c = c.add(1);
|
||||
}
|
||||
|
||||
let mut result: f64 = int_part as f64;
|
||||
|
||||
if *c == b'.' {
|
||||
c = c.add(1);
|
||||
let mut factor = 0.1;
|
||||
while (*c).is_ascii_digit() {
|
||||
result += ((*c) - b'0') as f64 * factor;
|
||||
factor *= 0.1;
|
||||
c = c.add(1);
|
||||
}
|
||||
}
|
||||
|
||||
if *c == b'e' || *c == b'E' {
|
||||
c = c.add(1);
|
||||
|
||||
let mut exp_sign = 1;
|
||||
let mut exp_value = 0;
|
||||
|
||||
if (*c) == b'+' || (*c) == b'-' {
|
||||
if *c == b'-' {
|
||||
exp_sign = -1;
|
||||
}
|
||||
c = c.add(1);
|
||||
}
|
||||
|
||||
while (*c).is_ascii_digit() {
|
||||
exp_value *= 10;
|
||||
exp_value += ((*c) - b'0') as i64;
|
||||
c = c.add(1);
|
||||
}
|
||||
|
||||
result *= pow10_i32((exp_sign * exp_value) as i32);
|
||||
}
|
||||
|
||||
sign * result
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compare_str(str_1: *const u8, str_2: *const u8, case: bool, n: usize) -> i32 {
|
||||
@@ -129,22 +209,91 @@ unsafe extern "C" fn strncmp(str_1: *const u8, str_2: *const u8, n: i32) -> i32
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn strncopy(s: *const u8, n: i32) -> *const u8 {
|
||||
null()
|
||||
unsafe extern "C" fn strncpy(dest: *mut u8, source: *const u8, n: usize) -> *mut u8 {
|
||||
let mut i = 0usize;
|
||||
unsafe {
|
||||
while i < n {
|
||||
let b = *source.add(i);
|
||||
*dest.add(i) = b;
|
||||
i += 1;
|
||||
|
||||
if b == 0 {
|
||||
while i < n {
|
||||
*dest.add(i) = 0;
|
||||
i += 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dest
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn strdup(s: *const u8) -> *const u8 {
|
||||
null()
|
||||
unsafe extern "C" fn strdup(s: *const u8) -> *mut u8 {
|
||||
let len = strlen(s);
|
||||
let memory = malloc((len + 1) as u64);
|
||||
if memory.is_null() {
|
||||
return null_mut();
|
||||
}
|
||||
memcpy(memory, s, len + 1);
|
||||
memory
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn strstr(s: *const u8) -> *const u8 {
|
||||
unsafe extern "C" fn strstr(haystack: *const u8, needle: *const u8) -> *const u8 {
|
||||
if haystack.is_null() || needle.is_null() {
|
||||
return null();
|
||||
}
|
||||
|
||||
let mut h = haystack;
|
||||
|
||||
unsafe {
|
||||
if *needle == 0 {
|
||||
return haystack;
|
||||
}
|
||||
|
||||
while *h != 0 {
|
||||
if *h == *needle {
|
||||
let mut h2 = h;
|
||||
let mut n2 = needle;
|
||||
|
||||
while *n2 != 0 && *h2 != 0 && *h2 == *n2 {
|
||||
h2 = h2.add(1);
|
||||
n2 = n2.add(1);
|
||||
}
|
||||
|
||||
if *n2 == 0 {
|
||||
return h;
|
||||
}
|
||||
}
|
||||
|
||||
h = h.add(1);
|
||||
}
|
||||
}
|
||||
|
||||
null()
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn strchr(s: *const u8, ch: u8) -> *const u8 {
|
||||
if s.is_null() {
|
||||
return null();
|
||||
}
|
||||
|
||||
let mut i = 0usize;
|
||||
|
||||
unsafe {
|
||||
while *s.add(i) != 0 {
|
||||
if *s.add(i) == ch {
|
||||
return s.add(i);
|
||||
}
|
||||
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
null()
|
||||
}
|
||||
|
||||
@@ -157,7 +306,7 @@ unsafe extern "C" fn strrchr(s: *const u8, ch: u8) -> *const u8 {
|
||||
while unsafe { *s.add(n) } != 0 {
|
||||
n += 1;
|
||||
}
|
||||
unsafe { s.add(n + 1) }
|
||||
return unsafe { s.add(n + 1) };
|
||||
} else {
|
||||
while unsafe { *s.add(n) } != 0 {
|
||||
let cur_ch = unsafe { s.add(n) };
|
||||
|
||||
@@ -1,27 +1,117 @@
|
||||
use core::ptr::null_mut;
|
||||
|
||||
use crate::{
|
||||
heap::ALLOCATOR,
|
||||
syscall::{BRK, syscall1},
|
||||
};
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn calloc(nitems: u64, size: u64) -> *mut u8 {
|
||||
null_mut()
|
||||
pub extern "C" fn sbrk(increment: i64) -> i64 {
|
||||
unsafe { syscall1(BRK, increment as usize) as i64 }
|
||||
}
|
||||
|
||||
const MAX_SIZE: u64 = 18446744073709551615;
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn calloc(count: u64, size: u64) -> *mut u8 {
|
||||
if count != 0 && size > MAX_SIZE / count {
|
||||
return null_mut();
|
||||
}
|
||||
|
||||
let mut total = count * size;
|
||||
|
||||
if total == 0 {
|
||||
total = 1;
|
||||
}
|
||||
|
||||
let ptr = malloc(total);
|
||||
|
||||
if ptr.is_null() {
|
||||
return null_mut();
|
||||
}
|
||||
|
||||
memset(ptr, 0, total as usize);
|
||||
|
||||
ptr
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn free(ptr: *mut u8) {}
|
||||
pub extern "C" fn free(ptr: *mut u8) {
|
||||
if ptr.is_null() {
|
||||
return;
|
||||
}
|
||||
unsafe {
|
||||
let size = *(((ptr as usize) - core::mem::size_of::<usize>()) as *const usize);
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn malloc(size: u64) -> *mut u8 {
|
||||
null_mut()
|
||||
let mut allocator = ALLOCATOR.lock();
|
||||
allocator
|
||||
.add_free_memory_region(ptr as usize - core::mem::size_of::<usize>(), size as usize);
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn memcpy(dest_str: *mut u8, src_str: *const u8, n: u64) {}
|
||||
pub extern "C" fn malloc(size: u64) -> *mut u8 {
|
||||
let mut allocator = ALLOCATOR.lock();
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn memset(str: *mut u8, c: i64, n: u64) -> *mut u8 {
|
||||
null_mut()
|
||||
if let Some(region) = allocator.find_region(size as usize, 16) {
|
||||
return region.1 as *mut u8;
|
||||
} else {
|
||||
let start_addr: i64 = sbrk(size as i64);
|
||||
if start_addr == -1 {
|
||||
return null_mut();
|
||||
}
|
||||
|
||||
unsafe { allocator.add_free_memory_region(start_addr as usize, size as usize) };
|
||||
drop(allocator);
|
||||
malloc(size)
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn realloc(ptr: *mut u8, size: u64) -> *mut u8 {
|
||||
null_mut()
|
||||
pub extern "C" fn memcpy(dest_str: *mut u8, src_str: *const u8, n: usize) -> *mut u8 {
|
||||
unsafe { core::ptr::copy(src_str, dest_str, n) };
|
||||
|
||||
dest_str
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn memset(str: *mut u8, c: i64, n: usize) -> *mut u8 {
|
||||
unsafe {
|
||||
core::ptr::write_bytes(str, c as u8, n);
|
||||
}
|
||||
|
||||
str
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn realloc(ptr: *mut u8, size: usize) -> *mut u8 {
|
||||
unsafe {
|
||||
if size == 0 {
|
||||
free(ptr);
|
||||
return null_mut();
|
||||
}
|
||||
|
||||
let header = ((ptr as usize) - core::mem::size_of::<usize>()) as *mut usize;
|
||||
let old_size = *header;
|
||||
|
||||
if old_size == size {
|
||||
return ptr;
|
||||
} else if size < old_size {
|
||||
let mut allocator = ALLOCATOR.lock();
|
||||
let difference = old_size.abs_diff(size);
|
||||
let start = (ptr as usize) + size;
|
||||
*header = size;
|
||||
allocator.add_free_memory_region(start as usize, difference as usize);
|
||||
return ptr;
|
||||
} else {
|
||||
let new_ptr = malloc(size as u64);
|
||||
if new_ptr.is_null() {
|
||||
return null_mut();
|
||||
}
|
||||
|
||||
core::ptr::copy_nonoverlapping(ptr, new_ptr, old_size);
|
||||
free(ptr);
|
||||
return new_ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,25 @@
|
||||
pub const READ: usize = 0;
|
||||
pub const WRITE: usize = 1;
|
||||
pub const OPEN: usize = 2;
|
||||
pub const CLOSE: usize = 3;
|
||||
pub const STAT: usize = 4;
|
||||
pub const LSEEK: usize = 8;
|
||||
pub const MMAP: usize = 9;
|
||||
pub const MUNMAP: usize = 9;
|
||||
pub const BRK: usize = 12;
|
||||
pub const GETPID: usize = 39;
|
||||
pub const FORK: usize = 57;
|
||||
pub const EXECVE: usize = 59;
|
||||
pub const EXIT: usize = 60;
|
||||
pub const WAIT4: usize = 61;
|
||||
pub const KILL: usize = 62;
|
||||
pub const CHDIR: usize = 80;
|
||||
pub const MKDIR: usize = 83;
|
||||
pub const UNLINK: usize = 87;
|
||||
pub const GETDENTS64: usize = 217;
|
||||
pub const CLOCK_GETTIME: usize = 228;
|
||||
pub const EXIT_GROUP: usize = 231;
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn syscall0(num: usize) -> isize {
|
||||
let ret: isize;
|
||||
@@ -13,6 +35,22 @@ pub unsafe fn syscall0(num: usize) -> isize {
|
||||
ret
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn syscall1(num: usize, arg0: usize) -> isize {
|
||||
let ret: isize;
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
"int 0x80",
|
||||
in("rax") num,
|
||||
in("rdi") arg0,
|
||||
lateout("rax") ret,
|
||||
options(nostack)
|
||||
);
|
||||
}
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn syscall3(num: usize, arg0: usize, arg1: usize, arg2: usize) -> isize {
|
||||
let ret: isize;
|
||||
|
||||
20
user/libxunil/src/util.rs
Normal file
20
user/libxunil/src/util.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
#[inline]
|
||||
pub const fn align_down(addr: usize, align: usize) -> usize {
|
||||
assert!(align.is_power_of_two(), "`align` must be a power of two");
|
||||
addr & !(align - 1)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn align_up(addr: usize, align: usize) -> usize {
|
||||
assert!(align.is_power_of_two(), "`align` must be a power of two");
|
||||
let align_mask = align - 1;
|
||||
if addr & align_mask == 0 {
|
||||
addr
|
||||
} else {
|
||||
if let Some(aligned) = (addr | align_mask).checked_add(1) {
|
||||
aligned
|
||||
} else {
|
||||
panic!("attempt to add with overflow")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user