use std::{mem, ptr};
use o3::base::marker::ThreadBound;
use crate::{
Errno, kernel,
thread::{Attrs, Handle},
};
cfg_select! {
target_arch = "x86_64" => {
mod x86;
pub(super) use x86::try_crc32;
}
all(target_arch = "aarch64", target_os = "linux") => {
mod linux;
pub(super) use linux::try_crc32;
}
all(target_arch = "aarch64", target_os = "macos") => {
mod macos;
pub(super) use macos::try_crc32;
}
_ => {
mod scalar;
pub(super) use scalar::try_crc32;
}
}
pub(super) fn entropy<S: kernel::raw::Source + ?Sized, const N: usize>(
bytes: &mut mem::MaybeUninit<[u8; N]>,
) -> Result<&mut [u8; N], Errno> {
const { assert!(N <= 256) };
let result = unsafe { libc::getentropy(bytes.as_mut_ptr().cast(), N) };
unsafe {
kernel::raw::Status::new(result).try_zero::<Errno>(|| kernel::raw::Code::last::<S>().into())
}?;
Ok(unsafe { bytes.assume_init_mut() })
}
pub unsafe trait Task: Sized {
unsafe fn run(context: ptr::NonNull<Self>);
}
pub struct Entry<T: Task> {
context: ptr::NonNull<T>,
}
impl<T: Task> Entry<T> {
pub const unsafe fn new(context: ptr::NonNull<T>) -> Self {
Self { context }
}
pub fn spawn(self, attrs: &Attrs) -> Result<Handle, Errno> {
let mut thread = mem::MaybeUninit::uninit();
unsafe {
kernel::raw::Status::new(libc::pthread_create(
thread.as_mut_ptr(),
attrs.as_ptr(),
Self::run,
self.context.as_ptr().cast(),
))
.try_pthread()
}?;
Ok(Handle(unsafe { thread.assume_init() }, ThreadBound::NEW))
}
extern "C" fn run(context: *mut std::ffi::c_void) -> *mut std::ffi::c_void {
unsafe { T::run(ptr::NonNull::new_unchecked(context.cast())) };
ptr::null_mut()
}
}