Compare commits
3 Commits
14585c005c
...
d1b5720abd
Author | SHA1 | Date |
---|---|---|
|
d1b5720abd | |
|
71c6003905 | |
|
9da38d608a |
|
@ -1,3 +1,7 @@
|
||||||
|
use core::cell::UnsafeCell;
|
||||||
|
use core::ops::Deref;
|
||||||
|
use core::ops::DerefMut;
|
||||||
|
|
||||||
use crate::{cap::Capability, syscall, zion::ZError};
|
use crate::{cap::Capability, syscall, zion::ZError};
|
||||||
|
|
||||||
pub struct Semaphore {
|
pub struct Semaphore {
|
||||||
|
@ -17,3 +21,52 @@ impl Semaphore {
|
||||||
syscall::semaphone_signal(&self.cap)
|
syscall::semaphone_signal(&self.cap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Mutex<T> {
|
||||||
|
cap: Capability,
|
||||||
|
data: UnsafeCell<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<T> Sync for Mutex<T> where T: Send {}
|
||||||
|
|
||||||
|
pub struct MutexGuard<'a, T> {
|
||||||
|
mutex: &'a Mutex<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<T> Send for MutexGuard<'_, T> where T: Send {}
|
||||||
|
unsafe impl<T> Sync for MutexGuard<'_, T> where T: Sync {}
|
||||||
|
|
||||||
|
impl<T> Deref for MutexGuard<'_, T> {
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
unsafe { &*self.mutex.data.get() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> DerefMut for MutexGuard<'_, T> {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
unsafe { &mut *self.mutex.data.get() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Mutex<T> {
|
||||||
|
pub fn new(data: T) -> Mutex<T> {
|
||||||
|
Mutex {
|
||||||
|
cap: syscall::mutex_create().unwrap(),
|
||||||
|
data: UnsafeCell::new(data),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lock(&self) -> MutexGuard<T> {
|
||||||
|
syscall::mutex_lock(&self.cap).unwrap();
|
||||||
|
|
||||||
|
MutexGuard { mutex: self }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Drop for MutexGuard<'_, T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
syscall::mutex_release(&self.mutex.cap).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -412,6 +412,36 @@ pub fn reply_port_recv(
|
||||||
Ok((num_bytes, num_caps))
|
Ok((num_bytes, num_caps))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn mutex_create() -> Result<Capability, ZError> {
|
||||||
|
let mut mutex_cap: z_cap_t = 0;
|
||||||
|
syscall(
|
||||||
|
zion::kZionMutexCreate,
|
||||||
|
&zion::ZMutexCreateReq {
|
||||||
|
mutex_cap: &mut mutex_cap,
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(Capability::take(mutex_cap))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mutex_lock(mutex_cap: &Capability) -> Result<(), ZError> {
|
||||||
|
syscall(
|
||||||
|
zion::kZionMutexLock,
|
||||||
|
&zion::ZMutexLockReq {
|
||||||
|
mutex_cap: mutex_cap.raw(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mutex_release(mutex_cap: &Capability) -> Result<(), ZError> {
|
||||||
|
syscall(
|
||||||
|
zion::kZionMutexRelease,
|
||||||
|
&zion::ZMutexReleaseReq {
|
||||||
|
mutex_cap: mutex_cap.raw(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn semaphore_create() -> Result<Capability, ZError> {
|
pub fn semaphore_create() -> Result<Capability, ZError> {
|
||||||
let mut sem_cap: z_cap_t = 0;
|
let mut sem_cap: z_cap_t = 0;
|
||||||
syscall(
|
syscall(
|
||||||
|
|
|
@ -42,3 +42,43 @@ impl Thread {
|
||||||
syscall::thread_wait(&self.cap)
|
syscall::thread_wait(&self.cap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct JoinHandle {
|
||||||
|
cap: Capability,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl JoinHandle {
|
||||||
|
pub fn join(&self) -> Result<(), zion::ZError> {
|
||||||
|
syscall::thread_wait(&self.cap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn entry_point(func: *mut c_void) -> ! {
|
||||||
|
unsafe {
|
||||||
|
Box::from_raw(func as *mut Box<dyn FnOnce()>)();
|
||||||
|
}
|
||||||
|
|
||||||
|
syscall::thread_exit()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn spawn<F>(f: F) -> JoinHandle
|
||||||
|
where
|
||||||
|
F: FnOnce() + Send + 'static,
|
||||||
|
{
|
||||||
|
// This is very tricky.
|
||||||
|
// If we have been passed a closure that doesn't capture
|
||||||
|
// anything it will be 0 size and creating a Box of it
|
||||||
|
// will create a pointer with address 0x1.
|
||||||
|
// So we create this "main" closure that captures f to get around this.
|
||||||
|
// Also somehow having the explicit type annotation here is important.
|
||||||
|
let main: Box<dyn FnOnce()> = Box::new(move || {
|
||||||
|
f();
|
||||||
|
});
|
||||||
|
let raw_main = Box::into_raw(Box::new(main));
|
||||||
|
let proc_cap = Capability::take_copy(unsafe { crate::init::SELF_PROC_CAP }).unwrap();
|
||||||
|
let cap = syscall::thread_create(&proc_cap).unwrap();
|
||||||
|
syscall::thread_start(&cap, entry_point as u64, raw_main as u64, 0).unwrap();
|
||||||
|
|
||||||
|
JoinHandle { cap }
|
||||||
|
}
|
||||||
|
|
|
@ -1,12 +1,7 @@
|
||||||
use core::cell::RefCell;
|
|
||||||
|
|
||||||
use alloc::boxed::Box;
|
|
||||||
use alloc::rc::Rc;
|
|
||||||
use alloc::string::ToString;
|
use alloc::string::ToString;
|
||||||
use mammoth::cap::Capability;
|
use mammoth::cap::Capability;
|
||||||
use mammoth::port::PortServer;
|
use mammoth::port::PortServer;
|
||||||
use mammoth::thread::Thread;
|
use mammoth::thread;
|
||||||
use mammoth::zion::ZError;
|
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -198,67 +193,34 @@ pub trait KeyboardHandler {
|
||||||
fn handle_char(&mut self, c: char);
|
fn handle_char(&mut self, c: char);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct KeyboardListener {
|
pub fn spawn_keyboard_listener<T>(mut handler: T) -> thread::JoinHandle
|
||||||
listen_port: PortServer,
|
where
|
||||||
listen_thread: Option<Box<Thread>>,
|
T: KeyboardHandler + Send + 'static,
|
||||||
handler: Rc<RefCell<dyn KeyboardHandler>>,
|
{
|
||||||
}
|
let listen_port = PortServer::new().unwrap();
|
||||||
|
|
||||||
impl KeyboardListener {
|
|
||||||
pub fn new(handler: Rc<RefCell<dyn KeyboardHandler>>) -> Result<Box<Self>, ZError> {
|
|
||||||
let mut listnr = Box::new(Self {
|
|
||||||
listen_port: PortServer::new()?,
|
|
||||||
listen_thread: None,
|
|
||||||
handler,
|
|
||||||
});
|
|
||||||
|
|
||||||
let voyageur_endpoint = yellowstone_yunq::from_init_endpoint()
|
let voyageur_endpoint = yellowstone_yunq::from_init_endpoint()
|
||||||
.get_endpoint(&yellowstone_yunq::GetEndpointRequest {
|
.get_endpoint(&yellowstone_yunq::GetEndpointRequest {
|
||||||
endpoint_name: "voyageurs".to_string(),
|
endpoint_name: "voyageurs".to_string(),
|
||||||
})?
|
})
|
||||||
|
.unwrap()
|
||||||
.endpoint;
|
.endpoint;
|
||||||
|
|
||||||
let mut voyageur_client = crate::VoyageursClient::new(Capability::take(voyageur_endpoint));
|
let mut voyageur_client = crate::VoyageursClient::new(Capability::take(voyageur_endpoint));
|
||||||
|
|
||||||
voyageur_client.register_keyboard_listener(&crate::KeyboardListener {
|
voyageur_client
|
||||||
port_capability: listnr.listen_port.create_client_cap()?,
|
.register_keyboard_listener(&crate::KeyboardListener {
|
||||||
})?;
|
port_capability: listen_port.create_client_cap().unwrap(),
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let thread_entry = |self_raw| {
|
let listen_thread = move || loop {
|
||||||
let listener = unsafe {
|
let scancode = listen_port.recv_u16().expect("Failed to recieve scancode");
|
||||||
(self_raw as *mut KeyboardListener)
|
|
||||||
.as_mut()
|
|
||||||
.expect("Failed to convert to keyboard listener")
|
|
||||||
};
|
|
||||||
listener.listen_loop();
|
|
||||||
};
|
|
||||||
|
|
||||||
listnr.listen_thread = Some(Thread::spawn(
|
|
||||||
thread_entry,
|
|
||||||
&*listnr as *const Self as *const core::ffi::c_void,
|
|
||||||
)?);
|
|
||||||
|
|
||||||
Ok(listnr)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn listen_loop(&mut self) {
|
|
||||||
loop {
|
|
||||||
let scancode = self
|
|
||||||
.listen_port
|
|
||||||
.recv_u16()
|
|
||||||
.expect("Failed to recieve scancode");
|
|
||||||
|
|
||||||
let keycode = Keycode::from_scancode(scancode);
|
let keycode = Keycode::from_scancode(scancode);
|
||||||
let modifiers = Modifiers::from_scancode(scancode);
|
let modifiers = Modifiers::from_scancode(scancode);
|
||||||
|
|
||||||
self.handler
|
handler.handle_char(into_char(keycode, modifiers))
|
||||||
.as_ref()
|
};
|
||||||
.borrow_mut()
|
|
||||||
.handle_char(into_char(keycode, modifiers))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn join(&self) -> Result<(), ZError> {
|
thread::spawn(listen_thread)
|
||||||
self.listen_thread.as_ref().unwrap().join()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,8 @@ mod framebuffer;
|
||||||
mod psf;
|
mod psf;
|
||||||
mod terminal;
|
mod terminal;
|
||||||
|
|
||||||
use core::cell::RefCell;
|
|
||||||
|
|
||||||
use alloc::rc::Rc;
|
|
||||||
use mammoth::{debug, define_entry, zion::z_err_t};
|
use mammoth::{debug, define_entry, zion::z_err_t};
|
||||||
use voyageurs::listener::KeyboardListener;
|
use voyageurs::listener;
|
||||||
|
|
||||||
define_entry!();
|
define_entry!();
|
||||||
|
|
||||||
|
@ -39,9 +36,9 @@ extern "C" fn main() -> z_err_t {
|
||||||
|
|
||||||
let psf = psf::Psf::new("/default8x16.psfu").expect("Failed to open font file.");
|
let psf = psf::Psf::new("/default8x16.psfu").expect("Failed to open font file.");
|
||||||
let console = console::Console::new(framebuffer, psf);
|
let console = console::Console::new(framebuffer, psf);
|
||||||
let terminal = Rc::new(RefCell::new(terminal::Terminal::new(console)));
|
let terminal = terminal::Terminal::new(console);
|
||||||
|
|
||||||
let kb_listener = KeyboardListener::new(terminal).expect("Failed to create keyboard listener");
|
let kb_listener = listener::spawn_keyboard_listener(terminal);
|
||||||
|
|
||||||
kb_listener
|
kb_listener
|
||||||
.join()
|
.join()
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
|
use alloc::boxed::Box;
|
||||||
use alloc::string::ToString;
|
use alloc::string::ToString;
|
||||||
use mammoth::debug;
|
use mammoth::debug;
|
||||||
use mammoth::define_entry;
|
use mammoth::define_entry;
|
||||||
|
@ -12,6 +13,10 @@ use yellowstone_yunq::GetEndpointRequest;
|
||||||
|
|
||||||
define_entry!();
|
define_entry!();
|
||||||
|
|
||||||
|
pub fn testthread() {
|
||||||
|
debug!("Testing 1, 8 ,9");
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn main() -> z_err_t {
|
pub extern "C" fn main() -> z_err_t {
|
||||||
debug!("Testing!");
|
debug!("Testing!");
|
||||||
|
@ -28,11 +33,24 @@ pub extern "C" fn main() -> z_err_t {
|
||||||
|
|
||||||
debug!("Got endpoint w/ cap: {:#x}", endpoint.endpoint);
|
debug!("Got endpoint w/ cap: {:#x}", endpoint.endpoint);
|
||||||
|
|
||||||
|
let a = Box::new(1);
|
||||||
|
let b = Box::new(1);
|
||||||
|
debug!("Addrs: {:p} {:p}", a, b);
|
||||||
|
|
||||||
let e: thread::ThreadEntry = |_| {
|
let e: thread::ThreadEntry = |_| {
|
||||||
debug!("Testing 1 2 3");
|
debug!("Testing 1 2 3");
|
||||||
};
|
};
|
||||||
let t = thread::Thread::spawn(e, core::ptr::null()).expect("Failed to spawn thread");
|
let t = thread::Thread::spawn(e, core::ptr::null()).expect("Failed to spawn thread");
|
||||||
|
t.join().expect("Failed to wait.");
|
||||||
|
|
||||||
|
let x = Box::new(|| 1);
|
||||||
|
debug!("Addr: {:p}", x);
|
||||||
|
debug!("Addr: {:p}", &x);
|
||||||
|
|
||||||
|
let t = thread::spawn(testthread);
|
||||||
|
t.join().expect("Failed to wait.");
|
||||||
|
|
||||||
|
let t = thread::spawn(|| debug!("Testing 4, 5, 6"));
|
||||||
t.join().expect("Failed to wait.");
|
t.join().expect("Failed to wait.");
|
||||||
|
|
||||||
0
|
0
|
||||||
|
|
Loading…
Reference in New Issue