Skip to content

Commit

Permalink
feat: stabilize kernel interface
Browse files Browse the repository at this point in the history
In case, that POSIX provides similiar system calls, HermitOS
uses variants of these system calls. These similiarties should
increase the readability of the interface.
  • Loading branch information
stlankes authored and mkroening committed May 6, 2024
1 parent 377f440 commit 0e17161
Show file tree
Hide file tree
Showing 9 changed files with 168 additions and 78 deletions.
7 changes: 7 additions & 0 deletions src/errno.rs
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,13 @@ pub(crate) static ERRNO: core::cell::UnsafeCell<i32> = core::cell::UnsafeCell::n
#[cfg(not(feature = "nostd"))]
#[no_mangle]
pub extern "C" fn sys_get_errno() -> i32 {
sys_errno()
}

/// Get the error number from the thread local storage
#[cfg(not(feature = "nostd"))]
#[no_mangle]
pub extern "C" fn sys_errno() -> i32 {
cfg_if::cfg_if! {
if #[cfg(any(feature = "common-os", target_arch = "riscv64"))] {
0
Expand Down
4 changes: 2 additions & 2 deletions src/scheduler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use alloc::vec::Vec;
use core::cell::RefCell;
use core::future::{self, Future};
use core::ptr;
use core::sync::atomic::{AtomicU32, Ordering};
use core::sync::atomic::{AtomicI32, AtomicU32, Ordering};
use core::task::ready;
use core::task::Poll::Ready;

Expand Down Expand Up @@ -873,7 +873,7 @@ impl PerCoreScheduler {
}

fn get_tid() -> TaskId {
static TID_COUNTER: AtomicU32 = AtomicU32::new(0);
static TID_COUNTER: AtomicI32 = AtomicI32::new(0);
let guard = TASKS.lock();

loop {
Expand Down
6 changes: 3 additions & 3 deletions src/scheduler/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,14 @@ pub(crate) enum TaskStatus {

/// Unique identifier for a task (i.e. `pid`).
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
pub struct TaskId(u32);
pub struct TaskId(i32);

impl TaskId {
pub const fn into(self) -> u32 {
pub const fn into(self) -> i32 {
self.0
}

pub const fn from(x: u32) -> Self {
pub const fn from(x: i32) -> Self {
TaskId(x)
}
}
Expand Down
84 changes: 78 additions & 6 deletions src/syscalls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#[cfg(all(target_os = "none", not(feature = "common-os")))]
use core::alloc::{GlobalAlloc, Layout};
use core::ffi::CStr;
use core::ffi::{c_char, CStr};
use core::marker::PhantomData;

#[cfg(feature = "newlib")]
Expand Down Expand Up @@ -80,6 +80,54 @@ pub(crate) fn init() {
/// Returning a null pointer indicates that either memory is exhausted or
/// `size` and `align` do not meet this allocator's size or alignment constraints.
///
#[cfg(all(target_os = "none", not(feature = "common-os")))]
#[hermit_macro::system]
pub extern "C" fn sys_alloc(size: usize, align: usize) -> *mut u8 {
let layout_res = Layout::from_size_align(size, align);
if layout_res.is_err() || size == 0 {
warn!(
"__sys_alloc called with size {:#x}, align {:#x} is an invalid layout!",
size, align
);
return core::ptr::null_mut();
}
let layout = layout_res.unwrap();
let ptr = unsafe { ALLOCATOR.alloc(layout) };

trace!(
"__sys_alloc: allocate memory at {:p} (size {:#x}, align {:#x})",
ptr,
size,
align
);

ptr
}

#[cfg(all(target_os = "none", not(feature = "common-os")))]
#[hermit_macro::system]
pub extern "C" fn sys_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
let layout_res = Layout::from_size_align(size, align);
if layout_res.is_err() || size == 0 {
warn!(
"__sys_alloc_zeroed called with size {:#x}, align {:#x} is an invalid layout!",
size, align
);
return core::ptr::null_mut();
}
let layout = layout_res.unwrap();
let ptr = unsafe { ALLOCATOR.alloc_zeroed(layout) };

trace!(
"__sys_alloc_zeroed: allocate memory at {:p} (size {:#x}, align {:#x})",
ptr,
size,
align
);

ptr
}

#[cfg(all(target_os = "none", not(feature = "common-os")))]
#[hermit_macro::system]
pub extern "C" fn sys_malloc(size: usize, align: usize) -> *mut u8 {
Expand Down Expand Up @@ -169,6 +217,30 @@ pub unsafe extern "C" fn sys_realloc(
///
/// # Errors
/// May panic if debug assertions are enabled and invalid parameters `size` or `align` where passed.
#[cfg(all(target_os = "none", not(feature = "common-os")))]
#[hermit_macro::system]
pub unsafe extern "C" fn sys_dealloc(ptr: *mut u8, size: usize, align: usize) {
unsafe {
let layout_res = Layout::from_size_align(size, align);
if layout_res.is_err() || size == 0 {
warn!(
"__sys_dealloc called with size {:#x}, align {:#x} is an invalid layout!",
size, align
);
debug_assert!(layout_res.is_err(), "__sys_dealloc error: Invalid layout");
debug_assert_ne!(size, 0, "__sys_dealloc error: size cannot be 0");
} else {
trace!(
"sys_free: deallocate memory at {:p} (size {:#x})",
ptr,
size
);
}
let layout = layout_res.unwrap();
ALLOCATOR.dealloc(ptr, layout);
}
}

#[cfg(all(target_os = "none", not(feature = "common-os")))]
#[hermit_macro::system]
pub unsafe extern "C" fn sys_free(ptr: *mut u8, size: usize, align: usize) {
Expand Down Expand Up @@ -238,7 +310,7 @@ pub unsafe extern "C" fn sys_mkdir(name: *const u8, mode: u32) -> i32 {
}

#[hermit_macro::system]
pub unsafe extern "C" fn sys_rmdir(name: *const u8) -> i32 {
pub unsafe extern "C" fn sys_rmdir(name: *const c_char) -> i32 {
let name = unsafe { CStr::from_ptr(name as _) }.to_str().unwrap();

fs::FILESYSTEM
Expand All @@ -249,7 +321,7 @@ pub unsafe extern "C" fn sys_rmdir(name: *const u8) -> i32 {
}

#[hermit_macro::system]
pub unsafe extern "C" fn sys_stat(name: *const u8, stat: *mut FileAttr) -> i32 {
pub unsafe extern "C" fn sys_stat(name: *const c_char, stat: *mut FileAttr) -> i32 {
let name = unsafe { CStr::from_ptr(name as _) }.to_str().unwrap();

match fs::FILESYSTEM.get().unwrap().stat(name) {
Expand All @@ -262,7 +334,7 @@ pub unsafe extern "C" fn sys_stat(name: *const u8, stat: *mut FileAttr) -> i32 {
}

#[hermit_macro::system]
pub unsafe extern "C" fn sys_lstat(name: *const u8, stat: *mut FileAttr) -> i32 {
pub unsafe extern "C" fn sys_lstat(name: *const c_char, stat: *mut FileAttr) -> i32 {
let name = unsafe { CStr::from_ptr(name as _) }.to_str().unwrap();

match fs::FILESYSTEM.get().unwrap().lstat(name) {
Expand All @@ -288,7 +360,7 @@ pub unsafe extern "C" fn sys_fstat(fd: FileDescriptor, stat: *mut FileAttr) -> i
}

#[hermit_macro::system]
pub unsafe extern "C" fn sys_opendir(name: *const u8) -> FileDescriptor {
pub unsafe extern "C" fn sys_opendir(name: *const c_char) -> FileDescriptor {
if let Ok(name) = unsafe { CStr::from_ptr(name as _) }.to_str() {
crate::fs::opendir(name).unwrap_or_else(|e| -num::ToPrimitive::to_i32(&e).unwrap())
} else {
Expand All @@ -297,7 +369,7 @@ pub unsafe extern "C" fn sys_opendir(name: *const u8) -> FileDescriptor {
}

#[hermit_macro::system]
pub unsafe extern "C" fn sys_open(name: *const u8, flags: i32, mode: u32) -> FileDescriptor {
pub unsafe extern "C" fn sys_open(name: *const c_char, flags: i32, mode: u32) -> FileDescriptor {
let flags = if let Some(flags) = OpenOption::from_bits(flags) {
flags
} else {
Expand Down
51 changes: 34 additions & 17 deletions src/syscalls/semaphore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ use alloc::boxed::Box;

use crate::errno::*;
use crate::synch::semaphore::Semaphore;
use crate::time::timespec;

#[allow(non_camel_case_types)]
pub type sem_t = *const Semaphore;

/// Create a new, unnamed semaphore.
///
Expand All @@ -10,8 +14,8 @@ use crate::synch::semaphore::Semaphore;
/// Stores the raw memory location of the new semaphore in parameter `sem`.
/// Returns `0` on success, `-EINVAL` if `sem` is null.
#[hermit_macro::system]
pub unsafe extern "C" fn sys_sem_init(sem: *mut *mut Semaphore, value: u32) -> i32 {
if sem.is_null() {
pub unsafe extern "C" fn sys_sem_init(sem: *mut sem_t, pshared: i32, value: u32) -> i32 {
if sem.is_null() || pshared != 0 {
return -EINVAL;
}

Expand All @@ -29,7 +33,7 @@ pub unsafe extern "C" fn sys_sem_init(sem: *mut *mut Semaphore, value: u32) -> i
///
/// Returns `0` on success, `-EINVAL` if `sem` is null.
#[hermit_macro::system]
pub unsafe extern "C" fn sys_sem_destroy(sem: *mut Semaphore) -> i32 {
pub unsafe extern "C" fn sys_sem_destroy(sem: *mut sem_t) -> i32 {
if sem.is_null() {
return -EINVAL;
}
Expand All @@ -50,13 +54,13 @@ pub unsafe extern "C" fn sys_sem_destroy(sem: *mut Semaphore) -> i32 {
///
/// Returns `0` on success, or `-EINVAL` if `sem` is null.
#[hermit_macro::system]
pub unsafe extern "C" fn sys_sem_post(sem: *const Semaphore) -> i32 {
pub unsafe extern "C" fn sys_sem_post(sem: *mut sem_t) -> i32 {
if sem.is_null() {
return -EINVAL;
}

// Get a reference to the given semaphore and release it.
let semaphore = unsafe { &*sem };
let semaphore = unsafe { &**sem };
semaphore.release();
0
}
Expand All @@ -68,47 +72,60 @@ pub unsafe extern "C" fn sys_sem_post(sem: *const Semaphore) -> i32 {
///
/// Returns `0` on lock acquire, `-EINVAL` if `sem` is null, or `-ECANCELED` if the decrement fails.
#[hermit_macro::system]
pub unsafe extern "C" fn sys_sem_trywait(sem: *const Semaphore) -> i32 {
pub unsafe extern "C" fn sys_sem_trywait(sem: *mut sem_t) -> i32 {
if sem.is_null() {
return -EINVAL;
}

// Get a reference to the given semaphore and acquire it in a non-blocking fashion.
let semaphore = unsafe { &*sem };
let semaphore = unsafe { &**sem };
if semaphore.try_acquire() {
0
} else {
-ECANCELED
}
}

unsafe fn sem_timedwait(sem: *const Semaphore, ms: u32) -> i32 {
unsafe fn sem_timedwait(sem: *mut sem_t, ms: u32) -> i32 {
if sem.is_null() {
return -EINVAL;
}

let delay = if ms > 0 { Some(u64::from(ms)) } else { None };

// Get a reference to the given semaphore and wait until we have acquired it or the wakeup time has elapsed.
let semaphore = unsafe { &*sem };
let semaphore = unsafe { &**sem };
if semaphore.acquire(delay) {
0
} else {
-ETIME
}
}

/// Try to acquire a lock on a semaphore, blocking for a given amount of milliseconds.
/// Try to acquire a lock on a semaphore.
///
/// Blocks until semaphore is acquired or until wake-up time has elapsed.
/// Blocks until semaphore is acquired or until specified time passed
///
/// Returns `0` on lock acquire, `-EINVAL` if sem is null, or `-ETIME` on timeout.
#[hermit_macro::system]
pub unsafe extern "C" fn sys_sem_timedwait(sem: *const Semaphore, ms: u32) -> i32 {
unsafe { sem_timedwait(sem, ms) }
}
pub unsafe extern "C" fn sys_sem_timedwait(sem: *mut sem_t, ts: *const timespec) -> i32 {
if ts.is_null() {
unsafe { sem_timedwait(sem, 0) }
} else {
let mut current_ts: timespec = Default::default();

#[hermit_macro::system]
pub unsafe extern "C" fn sys_sem_cancelablewait(sem: *const Semaphore, ms: u32) -> i32 {
unsafe { sem_timedwait(sem, ms) }
unsafe {
crate::sys_clock_gettime(crate::CLOCK_REALTIME, &mut current_ts as *mut _);

let ts = &*ts;
let ms: i64 = (ts.tv_sec - current_ts.tv_sec) * 1000
+ (ts.tv_nsec as i64 - current_ts.tv_nsec as i64) / 1000000;

if ms > 0 {
sem_timedwait(sem, ms.try_into().unwrap())
} else {
0
}
}
}
}
Loading

0 comments on commit 0e17161

Please sign in to comment.