Use unsafe blocks in platform module

This commit is contained in:
sourceturner
2026-01-18 21:51:33 +01:00
parent 0f23c03ba4
commit 2d5ac47214
4 changed files with 84 additions and 66 deletions
+20 -16
View File
@@ -1,3 +1,6 @@
// TODO: set this for entire crate when possible
#![deny(unsafe_op_in_unsafe_fn)]
use core::{
alloc::{GlobalAlloc, Layout},
cell::SyncUnsafeCell,
@@ -33,22 +36,22 @@ unsafe impl GlobalAlloc for Allocator {
#[inline]
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
if layout.align() <= align_of::<max_align_t>() {
(*self.get()).lock().malloc(layout.size())
unsafe { (*self.get()).lock().malloc(layout.size()) }
} else {
(*self.get()).lock().memalign(layout.align(), layout.size())
unsafe { (*self.get()).lock().memalign(layout.align(), layout.size()) }
}
}
#[inline]
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
(*self.get()).lock().free(ptr)
unsafe { (*self.get()).lock().free(ptr) }
}
#[inline]
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
let ptr = self.alloc(layout);
if !ptr.is_null() && (*self.get()).lock().calloc_must_clear(ptr) {
write_bytes(ptr, 0, layout.size());
let ptr = unsafe { self.alloc(layout) };
if !ptr.is_null() && unsafe { (*self.get()).lock().calloc_must_clear(ptr) } {
unsafe { write_bytes(ptr, 0, layout.size()) };
}
ptr
}
@@ -56,19 +59,20 @@ unsafe impl GlobalAlloc for Allocator {
#[inline]
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
if layout.align() <= align_of::<max_align_t>() {
(*self.get()).lock().realloc(ptr, new_size)
unsafe { (*self.get()).lock().realloc(ptr, new_size) }
} else {
let new = self.alloc(Layout::from_size_align_unchecked(new_size, layout.align()));
let new =
unsafe { self.alloc(Layout::from_size_align_unchecked(new_size, layout.align())) };
let old_size = layout.size();
let old_align = layout.align();
if !new.is_null() {
let size = cmp::min(old_size, new_size);
copy_nonoverlapping(ptr, new, size);
unsafe { copy_nonoverlapping(ptr, new, size) };
}
drop((old_size, old_align));
(*self.get()).lock().free(ptr);
unsafe { (*self.get()).lock().free(ptr) };
new
}
@@ -76,18 +80,18 @@ unsafe impl GlobalAlloc for Allocator {
}
pub unsafe fn alloc(size: size_t) -> *mut c_void {
(*ALLOCATOR.get()).lock().malloc(size).cast()
unsafe { (*ALLOCATOR.get()).lock().malloc(size) }.cast()
}
pub unsafe fn alloc_align(size: size_t, alignment: size_t) -> *mut c_void {
(*ALLOCATOR.get()).lock().memalign(alignment, size).cast()
unsafe { (*ALLOCATOR.get()).lock().memalign(alignment, size) }.cast()
}
pub unsafe fn realloc(ptr: *mut c_void, size: size_t) -> *mut c_void {
if ptr.is_null() {
(*ALLOCATOR.get()).lock().malloc(size).cast()
unsafe { (*ALLOCATOR.get()).lock().malloc(size) }.cast()
} else {
(*ALLOCATOR.get()).lock().realloc(ptr.cast(), size).cast()
unsafe { (*ALLOCATOR.get()).lock().realloc(ptr.cast(), size) }.cast()
}
}
@@ -95,12 +99,12 @@ pub unsafe fn free(ptr: *mut c_void) {
if ptr.is_null() {
return;
}
(*ALLOCATOR.get()).lock().free(ptr.cast())
unsafe { (*ALLOCATOR.get()).lock().free(ptr.cast()) }
}
pub unsafe fn alloc_usable_size(ptr: *mut c_void) -> size_t {
if ptr.is_null() {
return 0;
}
(*ALLOCATOR.get()).lock().usable_size(ptr.cast())
unsafe { (*ALLOCATOR.get()).lock().usable_size(ptr.cast()) }
}
+12 -7
View File
@@ -1,3 +1,6 @@
// TODO: set this for entire crate when possible
#![deny(unsafe_op_in_unsafe_fn)]
use crate::{
header::{
sys_mman::{self, MAP_FAILED, MREMAP_MAYMOVE},
@@ -115,13 +118,15 @@ pub unsafe fn enable_alloc_after_fork() {
// it will acquire the lock before any other thread,
// protecting it from deadlock,
// due to the child being created with only the calling thread.
if !FORK_PROTECTED {
pthread_atfork(
Some(_acquire_global_lock),
Some(_release_global_lock),
Some(_release_global_lock),
);
FORK_PROTECTED = true;
unsafe {
if !FORK_PROTECTED {
pthread_atfork(
Some(_acquire_global_lock),
Some(_release_global_lock),
Some(_release_global_lock),
);
FORK_PROTECTED = true;
}
}
release_global_lock();
}
+46 -41
View File
@@ -1,3 +1,6 @@
// TODO: set this for entire crate when possible
#![deny(unsafe_op_in_unsafe_fn)]
use core::{arch::asm, num::NonZeroU64, ptr};
use super::{ERRNO, Pal, types::*};
@@ -343,7 +346,7 @@ impl Pal for Sys {
}
unsafe fn dent_reclen_offset(this_dent: &[u8], offset: usize) -> Option<(u16, u64)> {
let dent = this_dent.as_ptr().cast::<dirent>();
Some(((*dent).d_reclen, (*dent).d_off as u64))
Some((unsafe { (*dent).d_reclen }, unsafe { (*dent).d_off } as u64))
}
fn getegid() -> gid_t {
@@ -638,52 +641,54 @@ impl Pal for Sys {
) -> Result<crate::pthread::OsTid> {
let flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD;
let pid;
asm!("
# Call clone syscall
syscall
unsafe {
asm!("
# Call clone syscall
syscall
# Check if child or parent
test rax, rax
jnz 2f
# Check if child or parent
test rax, rax
jnz 2f
# Load registers
pop rax
pop rdi
pop rsi
pop rdx
pop rcx
pop r8
pop r9
# Load registers
pop rax
pop rdi
pop rsi
pop rdx
pop rcx
pop r8
pop r9
# Call entry point
call rax
# Call entry point
call rax
# Exit
mov rax, 60
xor rdi, rdi
syscall
# Exit
mov rax, 60
xor rdi, rdi
syscall
# Invalid instruction on failure to exit
ud2
# Invalid instruction on failure to exit
ud2
# Return PID if parent
2:
",
inout("rax") SYS_CLONE => pid,
inout("rdi") flags => _,
inout("rsi") stack => _,
inout("rdx") 0 => _,
inout("r10") 0 => _,
inout("r8") 0 => _,
//TODO: out("rbx") _,
out("rcx") _,
out("r9") _,
out("r11") _,
out("r12") _,
out("r13") _,
out("r14") _,
out("r15") _,
);
# Return PID if parent
2:
",
inout("rax") SYS_CLONE => pid,
inout("rdi") flags => _,
inout("rsi") stack => _,
inout("rdx") 0 => _,
inout("r10") 0 => _,
inout("r8") 0 => _,
//TODO: out("rbx") _,
out("rcx") _,
out("r9") _,
out("r11") _,
out("r12") _,
out("r13") _,
out("r14") _,
out("r15") _,
);
}
let tid = e_raw(pid)?;
Ok(crate::pthread::OsTid { thread_id: tid })
+6 -2
View File
@@ -1,5 +1,8 @@
//! Platform abstractions and environment.
// TODO: set this for entire crate when possible
#![deny(unsafe_op_in_unsafe_fn)]
use crate::{
error::{Errno, ResultExt},
io::{self, Read, Write},
@@ -305,7 +308,7 @@ unsafe fn auxv_iter<'a>(ptr: *const usize) -> impl Iterator<Item = [usize; 2]> +
#[cold]
pub unsafe fn get_auxvs(ptr: *const usize) -> Box<[[usize; 2]]> {
//traverse the stack and collect argument environment variables
let mut auxvs = auxv_iter(ptr).collect::<Vec<_>>();
let mut auxvs = unsafe { auxv_iter(ptr) }.collect::<Vec<_>>();
auxvs.sort_unstable_by_key(|[kind, _]| *kind);
auxvs.into_boxed_slice()
@@ -313,7 +316,8 @@ pub unsafe fn get_auxvs(ptr: *const usize) -> Box<[[usize; 2]]> {
// TODO: Find an auxv replacement for Redox's execv protocol
#[cold]
pub unsafe fn get_auxv_raw(ptr: *const usize, requested_kind: usize) -> Option<usize> {
auxv_iter(ptr).find_map(|[kind, value]| Some(value).filter(|_| kind == requested_kind))
unsafe { auxv_iter(ptr) }
.find_map(|[kind, value]| Some(value).filter(|_| kind == requested_kind))
}
pub fn get_auxv(auxvs: &[[usize; 2]], key: usize) -> Option<usize> {
auxvs