#![no_std]
mod definitions;
pub use definitions::*;
pub mod ns;
#[cfg(feature = "unstable_mem")]
mod unstable;
#[cfg(feature = "unstable_mem")]
pub use unstable::*;
#[inline]
pub unsafe fn raw_syscall(
mut a0: usize,
mut a1: usize,
mut a2: usize,
mut a3: usize,
mut a4: usize,
mut a5: usize,
mut a6: usize,
mut a7: usize,
) -> (usize, usize, usize, usize, usize, usize, usize, usize) {
unsafe {
core::arch::asm!(
"ecall",
inlateout("a0") a0,
inlateout("a1") a1,
inlateout("a2") a2,
inlateout("a3") a3,
inlateout("a4") a4,
inlateout("a5") a5,
inlateout("a6") a6,
inlateout("a7") a7,
)
};
(a0, a1, a2, a3, a4, a5, a6, a7)
}
#[inline]
pub unsafe fn syscall(
a0: Syscall,
a1: usize,
a2: usize,
a3: usize,
a4: usize,
a5: usize,
a6: usize,
a7: usize,
) -> Result<(usize, usize, usize, usize, usize, usize, usize, usize), Error> {
let result = unsafe { raw_syscall(a0 as usize, a1, a2, a3, a4, a5, a6, a7) };
if result.0 == 1 {
return Err(result.1.into());
}
Ok((
result.0, result.1, result.2, result.3, result.4, result.5, result.6, result.7,
))
}
pub fn lend_mut(
connection: Connection,
opcode: usize,
data: &mut [u8],
arg1: usize,
arg2: usize,
) -> Result<(usize, usize), Error> {
let result = unsafe {
syscall(
Syscall::SendMessage,
connection.0 as _,
InvokeType::LendMut as _,
opcode,
data.as_ptr() as usize,
data.len(),
arg1,
arg2,
)?
};
Ok((result.1, result.2))
}
pub fn try_lend_mut(
connection: Connection,
opcode: usize,
data: &mut [u8],
arg1: usize,
arg2: usize,
) -> Result<(usize, usize), Error> {
let result = unsafe {
syscall(
Syscall::TrySendMessage,
connection.0 as _,
InvokeType::LendMut as _,
opcode,
data.as_ptr() as usize,
data.len(),
arg1,
arg2,
)?
};
Ok((result.1, result.2))
}
pub fn lend(
connection: Connection,
opcode: usize,
data: &[u8],
arg1: usize,
arg2: usize,
) -> Result<(usize, usize), Error> {
let result = unsafe {
syscall(
Syscall::SendMessage,
connection.0 as _,
InvokeType::Lend as _,
opcode,
data.as_ptr() as usize,
data.len(),
arg1,
arg2,
)?
};
Ok((result.1, result.2))
}
pub fn try_lend(
connection: Connection,
opcode: usize,
data: &[u8],
arg1: usize,
arg2: usize,
) -> Result<(usize, usize), Error> {
let result = unsafe {
syscall(
Syscall::TrySendMessage,
connection.0 as _,
InvokeType::Lend as _,
opcode,
data.as_ptr() as usize,
data.len(),
arg1,
arg2,
)?
};
Ok((result.1, result.2))
}
pub fn scalar(connection: Connection, args: [usize; 5]) -> Result<(), Error> {
unsafe {
syscall(
Syscall::SendMessage,
connection.0 as _,
InvokeType::Scalar as _,
args[0],
args[1],
args[2],
args[3],
args[4],
)?
};
Ok(())
}
pub fn try_scalar(connection: Connection, args: [usize; 5]) -> Result<(), Error> {
unsafe {
syscall(
Syscall::TrySendMessage,
connection.0 as _,
InvokeType::Scalar as _,
args[0],
args[1],
args[2],
args[3],
args[4],
)?
};
Ok(())
}
pub fn blocking_scalar(connection: Connection, args: [usize; 5]) -> Result<[usize; 5], Error> {
let result = unsafe {
syscall(
Syscall::SendMessage,
connection.0 as _,
InvokeType::BlockingScalar as _,
args[0],
args[1],
args[2],
args[3],
args[4],
)?
};
Ok([result.1, result.2, result.3, result.4, result.5])
}
pub fn try_blocking_scalar(connection: Connection, args: [usize; 5]) -> Result<[usize; 5], Error> {
let result = unsafe {
syscall(
Syscall::TrySendMessage,
connection.0 as _,
InvokeType::BlockingScalar as _,
args[0],
args[1],
args[2],
args[3],
args[4],
)?
};
Ok([result.1, result.2, result.3, result.4, result.5])
}
pub fn connect(address: ServerAddress) -> Result<Connection, Error> {
let result = unsafe {
syscall(
Syscall::Connect,
address.0[0] as usize,
address.0[1] as usize,
address.0[2] as usize,
address.0[3] as usize,
0,
0,
0,
)?
};
Ok(Connection(result.1 as u32))
}
pub fn try_connect(address: ServerAddress) -> Result<Option<Connection>, Error> {
let result = unsafe {
syscall(
Syscall::Connect,
address.0[0] as usize,
address.0[1] as usize,
address.0[2] as usize,
address.0[3] as usize,
0,
0,
0,
)
};
match result {
Ok(val) => Ok(Some(Connection(val.1 as u32))),
Err(Error::ServerNotFound) => Ok(None),
Err(e) => Err(e),
}
}
pub unsafe fn disconnect(connection: Connection) -> Result<(), Error> {
unsafe { syscall(Syscall::Disconnect, connection.0 as _, 0, 0, 0, 0, 0, 0)? };
Ok(())
}
pub fn exit(exit_code: u32) -> ! {
let _ = unsafe { syscall(Syscall::TerminateProcess, exit_code as _, 0, 0, 0, 0, 0, 0) };
unreachable!();
}
pub fn do_yield() {
let _ = unsafe { syscall(Syscall::Yield, 0, 0, 0, 0, 0, 0, 0) };
}
pub fn join_thread(thread_id: ThreadId) -> Result<usize, Error> {
let result = unsafe { syscall(Syscall::JoinThread, thread_id.into(), 0, 0, 0, 0, 0, 0)? };
Ok(result.1)
}
pub fn thread_id() -> Result<ThreadId, Error> {
let result = unsafe { syscall(Syscall::GetThreadId, 0, 0, 0, 0, 0, 0, 0)? };
Ok(result.1.into())
}
pub fn adjust_limit(knob: Limits, current: usize, new: usize) -> Result<usize, Error> {
let result = unsafe {
syscall(
Syscall::AdjustProcessLimit,
knob as usize,
current,
new,
0,
0,
0,
0,
)?
};
if result.0 == SyscallResult::Scalar2 as usize && result.1 == knob as usize {
Ok(result.2)
} else if result.0 == SyscallResult::Scalar5 as usize && result.1 == knob as usize {
Ok(result.1)
} else {
Err(Error::InternalError)
}
}