feat(userspace): terminal server + shell desktop; US keymap w/ shift; libkos allocator multi-page fix; panics print
This commit is contained in:
@@ -39,22 +39,21 @@ impl KosAllocator {
|
||||
}
|
||||
|
||||
impl AllocatorInner {
|
||||
fn request_page(&mut self) -> *mut u8 {
|
||||
if self.page_count >= MAX_PAGES {
|
||||
/// `n` pages in one piece, so an allocation larger than a page fits.
|
||||
fn request_pages(&mut self, n: usize) -> *mut u8 {
|
||||
if self.page_count + n > MAX_PAGES {
|
||||
return ptr::null_mut();
|
||||
}
|
||||
|
||||
let count = match types::bounded::PageCount::new(1) {
|
||||
Some(c) => c,
|
||||
None => return ptr::null_mut(),
|
||||
let Some(count) = u16::try_from(n).ok().and_then(types::bounded::PageCount::new) else {
|
||||
return ptr::null_mut();
|
||||
};
|
||||
let va = match crate::syscall::request_pages(count) {
|
||||
Some(va) => va,
|
||||
None => return ptr::null_mut(),
|
||||
let Some(va) = crate::syscall::request_pages(count) else {
|
||||
return ptr::null_mut();
|
||||
};
|
||||
|
||||
self.pages[self.page_count] = va.raw();
|
||||
self.page_count += 1;
|
||||
if let Some(slot) = self.pages.get_mut(self.page_count) {
|
||||
*slot = va.raw();
|
||||
}
|
||||
self.page_count += n;
|
||||
va.raw() as *mut u8
|
||||
}
|
||||
|
||||
@@ -125,14 +124,13 @@ unsafe impl GlobalAlloc for KosAllocator {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
let pages_needed = (size + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
for _ in 0..pages_needed {
|
||||
let page = inner.request_page();
|
||||
if page.is_null() {
|
||||
return ptr::null_mut();
|
||||
}
|
||||
inner.add_to_free_list(page, PAGE_SIZE);
|
||||
// Alignment can cost up to `align` bytes of the block.
|
||||
let pages_needed = (size + align + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
let block = inner.request_pages(pages_needed);
|
||||
if block.is_null() {
|
||||
return ptr::null_mut();
|
||||
}
|
||||
inner.add_to_free_list(block, pages_needed * PAGE_SIZE);
|
||||
|
||||
inner.alloc_from_free_list(size, align)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ pub mod io;
|
||||
mod rt;
|
||||
pub mod spawn;
|
||||
pub mod start;
|
||||
pub mod terminal;
|
||||
pub mod syscall;
|
||||
|
||||
#[cfg(target_os = "none")]
|
||||
|
||||
@@ -18,6 +18,7 @@ _start:
|
||||
|
||||
#[cfg(target_os = "none")]
|
||||
#[panic_handler]
|
||||
fn panic(_: &core::panic::PanicInfo) -> ! {
|
||||
fn panic(info: &core::panic::PanicInfo) -> ! {
|
||||
crate::println!("panic: {}", info);
|
||||
crate::syscall::exit();
|
||||
}
|
||||
|
||||
29
crates/libkos/src/terminal.rs
Normal file
29
crates/libkos/src/terminal.rs
Normal file
@@ -0,0 +1,29 @@
|
||||
//! The terminal (`types::terminal`). Output is the log protocol, so a
|
||||
//! process prints to a terminal by making it its log (`start::set_log`).
|
||||
|
||||
use crate::syscall;
|
||||
use types::bounded::CapSlot;
|
||||
|
||||
/// Reads a typed line into `buf`, newline included if it fits; how much.
|
||||
pub fn read_line(terminal: CapSlot, buf: &mut [u8]) -> usize {
|
||||
let mut n = 0;
|
||||
while n < buf.len() {
|
||||
let Ok(words) = syscall::request(terminal, [types::terminal::READ, 0, 0, 0]) else {
|
||||
break;
|
||||
};
|
||||
let Some((bytes, len)) = types::log::text_of(words) else {
|
||||
break;
|
||||
};
|
||||
let take = len.min(buf.len() - n);
|
||||
buf[n..n + take].copy_from_slice(&bytes[..take]);
|
||||
n += take;
|
||||
if bytes[..len].last() == Some(&b'\n') || len == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
n
|
||||
}
|
||||
|
||||
pub fn clear(terminal: CapSlot) {
|
||||
let _ = syscall::request(terminal, [types::terminal::CLEAR, 0, 0, 0]);
|
||||
}
|
||||
Reference in New Issue
Block a user