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};
|
||||
|
||||
pub struct Semaphore {
|
||||
|
@ -17,3 +21,52 @@ impl Semaphore {
|
|||
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))
|
||||
}
|
||||
|
||||
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> {
|
||||
let mut sem_cap: z_cap_t = 0;
|
||||
syscall(
|
||||
|
|
|
@ -42,3 +42,43 @@ impl Thread {
|
|||
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 mammoth::cap::Capability;
|
||||
use mammoth::port::PortServer;
|
||||
use mammoth::thread::Thread;
|
||||
use mammoth::zion::ZError;
|
||||
use mammoth::thread;
|
||||
|
||||
#[repr(u8)]
|
||||
#[allow(dead_code)]
|
||||
|
@ -198,67 +193,34 @@ pub trait KeyboardHandler {
|
|||
fn handle_char(&mut self, c: char);
|
||||
}
|
||||
|
||||
pub struct KeyboardListener {
|
||||
listen_port: PortServer,
|
||||
listen_thread: Option<Box<Thread>>,
|
||||
handler: Rc<RefCell<dyn KeyboardHandler>>,
|
||||
}
|
||||
|
||||
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,
|
||||
});
|
||||
|
||||
pub fn spawn_keyboard_listener<T>(mut handler: T) -> thread::JoinHandle
|
||||
where
|
||||
T: KeyboardHandler + Send + 'static,
|
||||
{
|
||||
let listen_port = PortServer::new().unwrap();
|
||||
let voyageur_endpoint = yellowstone_yunq::from_init_endpoint()
|
||||
.get_endpoint(&yellowstone_yunq::GetEndpointRequest {
|
||||
endpoint_name: "voyageurs".to_string(),
|
||||
})?
|
||||
})
|
||||
.unwrap()
|
||||
.endpoint;
|
||||
|
||||
let mut voyageur_client = crate::VoyageursClient::new(Capability::take(voyageur_endpoint));
|
||||
|
||||
voyageur_client.register_keyboard_listener(&crate::KeyboardListener {
|
||||
port_capability: listnr.listen_port.create_client_cap()?,
|
||||
})?;
|
||||
voyageur_client
|
||||
.register_keyboard_listener(&crate::KeyboardListener {
|
||||
port_capability: listen_port.create_client_cap().unwrap(),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let thread_entry = |self_raw| {
|
||||
let listener = unsafe {
|
||||
(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 listen_thread = move || loop {
|
||||
let scancode = listen_port.recv_u16().expect("Failed to recieve scancode");
|
||||
|
||||
let keycode = Keycode::from_scancode(scancode);
|
||||
let modifiers = Modifiers::from_scancode(scancode);
|
||||
|
||||
self.handler
|
||||
.as_ref()
|
||||
.borrow_mut()
|
||||
.handle_char(into_char(keycode, modifiers))
|
||||
}
|
||||
}
|
||||
handler.handle_char(into_char(keycode, modifiers))
|
||||
};
|
||||
|
||||
pub fn join(&self) -> Result<(), ZError> {
|
||||
self.listen_thread.as_ref().unwrap().join()
|
||||
}
|
||||
thread::spawn(listen_thread)
|
||||
}
|
||||
|
|
|
@ -8,11 +8,8 @@ mod framebuffer;
|
|||
mod psf;
|
||||
mod terminal;
|
||||
|
||||
use core::cell::RefCell;
|
||||
|
||||
use alloc::rc::Rc;
|
||||
use mammoth::{debug, define_entry, zion::z_err_t};
|
||||
use voyageurs::listener::KeyboardListener;
|
||||
use voyageurs::listener;
|
||||
|
||||
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 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
|
||||
.join()
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::ToString;
|
||||
use mammoth::debug;
|
||||
use mammoth::define_entry;
|
||||
|
@ -12,6 +13,10 @@ use yellowstone_yunq::GetEndpointRequest;
|
|||
|
||||
define_entry!();
|
||||
|
||||
pub fn testthread() {
|
||||
debug!("Testing 1, 8 ,9");
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn main() -> z_err_t {
|
||||
debug!("Testing!");
|
||||
|
@ -28,11 +33,24 @@ pub extern "C" fn main() -> z_err_t {
|
|||
|
||||
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 = |_| {
|
||||
debug!("Testing 1 2 3");
|
||||
};
|
||||
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.");
|
||||
|
||||
0
|
||||
|
|
Loading…
Reference in New Issue