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:
csd4ni3l
2026-04-05 20:12:59 +02:00
parent 1e899e2f97
commit ae3915147a
26 changed files with 785 additions and 219 deletions

View File

@@ -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;
}
}
}