use crate::{ClockId, SignalAction, SignalNo, Stat, SyscallId, TimeSpec};
use bitflags::*;
use native::*;
#[inline]
pub fn write(fd: usize, buffer: &[u8]) -> isize {
unsafe { syscall3(SyscallId::WRITE, fd, buffer.as_ptr() as _, buffer.len()) }
}
#[inline]
pub fn read(fd: usize, buffer: &[u8]) -> isize {
unsafe { syscall3(SyscallId::READ, fd, buffer.as_ptr() as _, buffer.len()) }
}
bitflags! {
pub struct OpenFlags: u32 {
const RDONLY = 0;
const WRONLY = 1 << 0;
const RDWR = 1 << 1;
const CREATE = 1 << 9;
const TRUNC = 1 << 10;
}
}
#[inline]
pub fn open(path: &str, flags: OpenFlags) -> isize {
unsafe {
syscall2(
SyscallId::OPENAT,
path.as_ptr() as usize,
flags.bits as usize,
)
}
}
#[inline]
pub fn close(fd: usize) -> isize {
unsafe { syscall1(SyscallId::CLOSE, fd) }
}
pub fn link(oldpath: &str, newpath: &str) -> isize {
unsafe {
syscall5(
SyscallId::LINKAT,
-100isize as usize, oldpath.as_ptr() as usize,
-100isize as usize, newpath.as_ptr() as usize,
0,
)
}
}
pub fn unlink(path: &str) -> isize {
unsafe {
syscall3(
SyscallId::UNLINKAT,
-100isize as usize, path.as_ptr() as usize,
0,
)
}
}
pub fn fstat(fd: usize, st: &mut Stat) -> isize {
unsafe { syscall2(SyscallId::FSTAT, fd, st as *const _ as usize) }
}
pub fn fb_info(width_out: *mut u32, height_out: *mut u32) -> isize {
unsafe { syscall2(SyscallId::FB_INFO, width_out as usize, height_out as usize) }
}
pub fn fb_flush(buf: *const u8, len: usize) -> isize {
unsafe { syscall2(SyscallId::FB_FLUSH, buf as usize, len) }
}
pub fn console_getchar_nonblocking() -> isize {
unsafe { syscall0(SyscallId::CONSOLE_GETCHAR_NONBLOCKING) }
}
#[inline]
pub fn exit(exit_code: i32) -> isize {
unsafe { syscall1(SyscallId::EXIT, exit_code as _) }
}
#[inline]
pub fn sched_yield() -> isize {
unsafe { syscall0(SyscallId::SCHED_YIELD) }
}
#[inline]
pub fn clock_gettime(clockid: ClockId, tp: *mut TimeSpec) -> isize {
unsafe { syscall2(SyscallId::CLOCK_GETTIME, clockid.0, tp as _) }
}
pub fn fork() -> isize {
unsafe { syscall0(SyscallId::CLONE) }
}
pub fn exec(path: &str) -> isize {
unsafe { syscall2(SyscallId::EXECVE, path.as_ptr() as usize, path.len()) }
}
pub fn wait(exit_code_ptr: *mut i32) -> isize {
loop {
match unsafe { syscall2(SyscallId::WAIT4, usize::MAX, exit_code_ptr as usize) } {
-2 => {
sched_yield();
}
exit_pid => return exit_pid,
}
}
}
pub fn waitpid(pid: isize, exit_code_ptr: *mut i32) -> isize {
loop {
match unsafe { syscall2(SyscallId::WAIT4, pid as usize, exit_code_ptr as usize) } {
-2 => {
sched_yield();
}
exit_pid => return exit_pid,
}
}
}
pub fn getpid() -> isize {
unsafe { syscall0(SyscallId::GETPID) }
}
pub fn spawn(path: &str) -> isize {
unsafe { syscall2(SyscallId::SPAWN, path.as_ptr() as usize, path.len()) }
}
pub fn set_priority(prio: isize) -> isize {
unsafe { syscall1(SyscallId::SETPRIORITY, prio as usize) }
}
#[inline]
pub fn kill(pid: isize, signum: SignalNo) -> isize {
unsafe { syscall2(SyscallId::KILL, pid as _, signum as _) }
}
pub fn sbrk(size: i32) -> isize {
unsafe { syscall1(SyscallId::BRK, size as _) }
}
#[inline]
pub fn sigaction(
signum: SignalNo,
action: *const SignalAction,
old_action: *const SignalAction,
) -> isize {
unsafe {
syscall3(
SyscallId::RT_SIGACTION,
signum as _,
action as _,
old_action as _,
)
}
}
#[inline]
pub fn sigprocmask(mask: usize) -> isize {
unsafe { syscall1(SyscallId::RT_SIGPROCMASK, mask) }
}
#[inline]
pub fn sigreturn() -> isize {
unsafe { syscall0(SyscallId::RT_SIGRETURN) }
}
#[inline]
pub fn thread_create(entry: usize, arg: usize) -> isize {
unsafe { syscall2(SyscallId::THREAD_CREATE, entry, arg) }
}
#[inline]
pub fn gettid() -> isize {
unsafe { syscall0(SyscallId::GETTID) }
}
#[inline]
pub fn waittid(tid: usize) -> isize {
loop {
match unsafe { syscall1(SyscallId::WAITID, tid) } {
-2 => {
sched_yield();
}
exit_code => return exit_code,
}
}
}
#[inline]
pub fn semaphore_create(res_count: usize) -> isize {
unsafe { syscall1(SyscallId::SEMAPHORE_CREATE, res_count) }
}
#[inline]
pub fn semaphore_up(sem_id: usize) -> isize {
unsafe { syscall1(SyscallId::SEMAPHORE_UP, sem_id) }
}
#[inline]
pub fn semaphore_down(sem_id: usize) -> isize {
unsafe { syscall1(SyscallId::SEMAPHORE_DOWN, sem_id) }
}
#[inline]
pub fn mutex_create(blocking: bool) -> isize {
unsafe { syscall1(SyscallId::MUTEX_CREATE, blocking as _) }
}
#[inline]
pub fn mutex_lock(mutex_id: usize) -> isize {
unsafe { syscall1(SyscallId::MUTEX_LOCK, mutex_id) }
}
#[inline]
pub fn mutex_unlock(mutex_id: usize) -> isize {
unsafe { syscall1(SyscallId::MUTEX_UNLOCK, mutex_id) }
}
#[inline]
pub fn condvar_create() -> isize {
unsafe { syscall1(SyscallId::CONDVAR_CREATE, 0) }
}
#[inline]
pub fn condvar_signal(condvar_id: usize) -> isize {
unsafe { syscall1(SyscallId::CONDVAR_SIGNAL, condvar_id) }
}
#[inline]
pub fn condvar_wait(condvar_id: usize, mutex_id: usize) -> isize {
unsafe { syscall2(SyscallId::CONDVAR_WAIT, condvar_id, mutex_id) }
}
#[inline]
pub fn enable_deadlock_detect(is_enable: bool) -> isize {
unsafe { syscall1(SyscallId::ENABLE_DEADLOCK_DETECT, is_enable as usize) }
}
#[inline]
pub fn trace(trace_request: usize, id: usize, data: usize) -> isize {
unsafe { syscall3(SyscallId::TRACE, trace_request, id, data) }
}
#[inline]
pub fn mmap(start: usize, len: usize, prot: usize) -> isize {
unsafe { syscall6(SyscallId::MMAP, start, len, prot, 0, 0, 0) }
}
#[inline]
pub fn munmap(start: usize, len: usize) -> isize {
unsafe { syscall2(SyscallId::MUNMAP, start, len) }
}
#[inline]
pub fn pipe(pipe_fd: &mut [usize]) -> isize {
unsafe { syscall1(SyscallId::PIPE2, pipe_fd.as_mut_ptr() as _) }
}
#[cfg(target_arch = "riscv64")]
pub mod native {
use crate::SyscallId;
use core::arch::asm;
#[inline(always)]
pub unsafe fn syscall0(id: SyscallId) -> isize {
let ret: isize;
unsafe {
asm!("ecall",
in("a7") id.0,
out("a0") ret,
);
}
ret
}
#[inline(always)]
pub unsafe fn syscall1(id: SyscallId, a0: usize) -> isize {
let ret: isize;
unsafe {
asm!("ecall",
inlateout("a0") a0 => ret,
in("a7") id.0,
);
}
ret
}
#[inline(always)]
pub unsafe fn syscall2(id: SyscallId, a0: usize, a1: usize) -> isize {
let ret: isize;
unsafe {
asm!("ecall",
in("a7") id.0,
inlateout("a0") a0 => ret,
in("a1") a1,
);
}
ret
}
#[inline(always)]
pub unsafe fn syscall3(id: SyscallId, a0: usize, a1: usize, a2: usize) -> isize {
let ret: isize;
unsafe {
asm!("ecall",
in("a7") id.0,
inlateout("a0") a0 => ret,
in("a1") a1,
in("a2") a2,
);
}
ret
}
#[inline(always)]
pub unsafe fn syscall4(id: SyscallId, a0: usize, a1: usize, a2: usize, a3: usize) -> isize {
let ret: isize;
unsafe {
asm!("ecall",
in("a7") id.0,
inlateout("a0") a0 => ret,
in("a1") a1,
in("a2") a2,
in("a3") a3,
);
}
ret
}
#[inline(always)]
pub unsafe fn syscall5(
id: SyscallId,
a0: usize,
a1: usize,
a2: usize,
a3: usize,
a4: usize,
) -> isize {
let ret: isize;
unsafe {
asm!("ecall",
in("a7") id.0,
inlateout("a0") a0 => ret,
in("a1") a1,
in("a2") a2,
in("a3") a3,
in("a4") a4,
);
}
ret
}
#[inline(always)]
pub unsafe fn syscall6(
id: SyscallId,
a0: usize,
a1: usize,
a2: usize,
a3: usize,
a4: usize,
a5: usize,
) -> isize {
let ret: isize;
unsafe {
asm!("ecall",
in("a7") id.0,
inlateout("a0") a0 => ret,
in("a1") a1,
in("a2") a2,
in("a3") a3,
in("a4") a4,
in("a5") a5,
);
}
ret
}
}
#[cfg(not(target_arch = "riscv64"))]
pub mod native {
use crate::SyscallId;
#[inline(always)]
pub unsafe fn syscall0(_id: SyscallId) -> isize {
unimplemented!("syscall is only supported on riscv64")
}
#[inline(always)]
pub unsafe fn syscall1(_id: SyscallId, _a0: usize) -> isize {
unimplemented!("syscall is only supported on riscv64")
}
#[inline(always)]
pub unsafe fn syscall2(_id: SyscallId, _a0: usize, _a1: usize) -> isize {
unimplemented!("syscall is only supported on riscv64")
}
#[inline(always)]
pub unsafe fn syscall3(_id: SyscallId, _a0: usize, _a1: usize, _a2: usize) -> isize {
unimplemented!("syscall is only supported on riscv64")
}
#[inline(always)]
pub unsafe fn syscall4(
_id: SyscallId,
_a0: usize,
_a1: usize,
_a2: usize,
_a3: usize,
) -> isize {
unimplemented!("syscall is only supported on riscv64")
}
#[inline(always)]
pub unsafe fn syscall5(
_id: SyscallId,
_a0: usize,
_a1: usize,
_a2: usize,
_a3: usize,
_a4: usize,
) -> isize {
unimplemented!("syscall is only supported on riscv64")
}
#[inline(always)]
pub unsafe fn syscall6(
_id: SyscallId,
_a0: usize,
_a1: usize,
_a2: usize,
_a3: usize,
_a4: usize,
_a5: usize,
) -> isize {
unimplemented!("syscall is only supported on riscv64")
}
}