Merge pull request 'feature/nikocs/smaller_init_system' (#6) from feature/nikocs/smaller_init_system into develop
Reviewed-on: #6
This commit is contained in:
commit
4cdc657d10
17 changed files with 279 additions and 22 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["liblbos"]
|
members = ["liblbos"]
|
||||||
exclude = ["turntable", "makeddi", "ddi", "example"]
|
exclude = ["blood", "turntable", "makeddi", "ddi", "example"]
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "lbos"
|
name = "lbos"
|
||||||
|
|
|
||||||
2
blood/.gitignore
vendored
Normal file
2
blood/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
/target
|
||||||
|
/.idea
|
||||||
14
blood/Cargo.lock
generated
Normal file
14
blood/Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "blood"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"liblbos",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "liblbos"
|
||||||
|
version = "0.1.1"
|
||||||
25
blood/Cargo.toml
Normal file
25
blood/Cargo.toml
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
[package]
|
||||||
|
name = "blood"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
liblbos = { path = "../liblbos" }
|
||||||
|
|
||||||
|
[profile.dev]
|
||||||
|
panic = "abort"
|
||||||
|
opt-level = "s"
|
||||||
|
debug-assertions = false
|
||||||
|
overflow-checks = false
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
panic = "abort"
|
||||||
|
opt-level = "z"
|
||||||
|
debug-assertions = false
|
||||||
|
overflow-checks = false
|
||||||
|
lto = true
|
||||||
|
codegen-units = 1
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["arch_riscv32"]
|
||||||
|
arch_riscv32 = ["liblbos/arch_riscv32"]
|
||||||
16
blood/build.rs
Normal file
16
blood/build.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
fn main() {
|
||||||
|
let arch = std::env::var("LBOS_ARCH").unwrap_or("riscv32".to_string());
|
||||||
|
println!("cargo:rerun-if-env-changed=LBOS_ARCH");
|
||||||
|
println!("cargo:rustc-cfg=feature=\"arch_{}\"", arch);
|
||||||
|
|
||||||
|
println!("cargo:rerun-if-changed=src/arch/{}/asm", arch);
|
||||||
|
|
||||||
|
// specify the linker.ld script
|
||||||
|
println!("cargo:rustc-link-arg=-Tsrc/arch/{arch}/asm/linker.ld");
|
||||||
|
|
||||||
|
// output relocation info
|
||||||
|
println!("cargo:rustc-link-arg=--emit-relocs");
|
||||||
|
|
||||||
|
// don't page align sections
|
||||||
|
println!("cargo:rustc-link-arg=-n");
|
||||||
|
}
|
||||||
2
blood/src/arch/mod.rs
Normal file
2
blood/src/arch/mod.rs
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
#[cfg(feature = "arch_riscv32")]
|
||||||
|
mod riscv32;
|
||||||
34
blood/src/arch/riscv32/asm/linker.ld
Normal file
34
blood/src/arch/riscv32/asm/linker.ld
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
OUTPUT_FORMAT( "elf32-littleriscv" )
|
||||||
|
OUTPUT_ARCH( "riscv" )
|
||||||
|
|
||||||
|
ENTRY( _start )
|
||||||
|
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
program (wxa) : ORIGIN = 0x0, LENGTH = 20480
|
||||||
|
}
|
||||||
|
|
||||||
|
PHDRS
|
||||||
|
{
|
||||||
|
prg PT_LOAD ;
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
.text : {
|
||||||
|
. = ALIGN(512);
|
||||||
|
*(.text .text.*)
|
||||||
|
} >program AT>program :prg
|
||||||
|
|
||||||
|
.rodata : {
|
||||||
|
*(.rodata .rodata.*)
|
||||||
|
} >program AT>program :prg
|
||||||
|
|
||||||
|
.data : {
|
||||||
|
*(.sdata .sdata.*) *(.data .data.*)
|
||||||
|
} >program AT>program :prg
|
||||||
|
|
||||||
|
.bss : {
|
||||||
|
*(.sbss .sbss.*)
|
||||||
|
*(.bss .bss.*)
|
||||||
|
} >program AT>program :prg
|
||||||
|
}
|
||||||
10
blood/src/arch/riscv32/mod.rs
Normal file
10
blood/src/arch/riscv32/mod.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
use crate::main;
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
extern "C" fn _start() -> isize {
|
||||||
|
unsafe {
|
||||||
|
main();
|
||||||
|
}
|
||||||
|
|
||||||
|
0
|
||||||
|
}
|
||||||
83
blood/src/main.rs
Normal file
83
blood/src/main.rs
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use liblbos::fs::{DirectoryReader, FileSystem};
|
||||||
|
|
||||||
|
#[panic_handler]
|
||||||
|
fn panic(info: &core::panic::PanicInfo) -> ! {
|
||||||
|
liblbos::syscalls::write_terminal(b"abort\n");
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
mod arch;
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
extern "C" fn main() {
|
||||||
|
loop {
|
||||||
|
const TURNTBL: &str = "TURNTBL.DDI";
|
||||||
|
let mut fs = FileSystem::empty();
|
||||||
|
if liblbos::ktask::ktask_fsopen(&mut fs) != 0 {
|
||||||
|
liblbos::syscalls::write_terminal(b"failed to open fs\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let mut dir = DirectoryReader::empty();
|
||||||
|
if liblbos::ktask::ktask_fsopendir(&fs, &mut dir, b"/") != 0 {
|
||||||
|
liblbos::syscalls::write_terminal(b"failed to open dir\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let mut record = liblbos::fs::Record {
|
||||||
|
name: [0; 12],
|
||||||
|
record_type: 0,
|
||||||
|
target: 0,
|
||||||
|
total_size_bytes: 0,
|
||||||
|
};
|
||||||
|
fn namecmp(record: &liblbos::fs::Record, name: &[u8]) -> bool {
|
||||||
|
for (i, &x) in record.name.iter().enumerate() {
|
||||||
|
if x == 0 {
|
||||||
|
return &record.name[..i] == name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
while !namecmp(&record, TURNTBL.as_bytes()) {
|
||||||
|
if liblbos::ktask::ktask_fsreaddir(&fs, &mut dir, &mut record) != 0 {
|
||||||
|
liblbos::syscalls::write_terminal(b"failed to read dir\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if record.record_type == 0 {
|
||||||
|
liblbos::syscalls::write_terminal(b"unexpected eod\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// found turntable, load it
|
||||||
|
let mut reader = liblbos::fs::FileReader::empty();
|
||||||
|
if liblbos::ktask::ktask_fsopenfile(&fs, &record, &mut reader) != 0 {
|
||||||
|
liblbos::syscalls::write_terminal(b"failed to open file\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let size = record.total_size_bytes as usize;
|
||||||
|
let buf = liblbos::syscalls::alloc_blocks(size.div_ceil(512));
|
||||||
|
if liblbos::ktask::ktask_fsreadfile(&fs, &mut reader, unsafe { core::slice::from_raw_parts_mut(buf as *mut _, size) }) != 0 {
|
||||||
|
liblbos::syscalls::write_terminal(b"failed to read file\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut task_setup = liblbos::TaskSetup {
|
||||||
|
epc: 0,
|
||||||
|
stack_block_count: 2,
|
||||||
|
ddi_first_addr: 0,
|
||||||
|
ddi_size: 0,
|
||||||
|
environment: 0,
|
||||||
|
wait_for_task_exit: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if liblbos::ktask::ktask_loadddifile(buf, size, &mut task_setup as *mut _ as usize) != 0 {
|
||||||
|
liblbos::syscalls::write_terminal(b"failed to load ddi\n");
|
||||||
|
liblbos::syscalls::free_blocks(buf, size.div_ceil(512));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
liblbos::syscalls::free_blocks(buf, size.div_ceil(512));
|
||||||
|
|
||||||
|
liblbos::syscalls::create_task(task_setup);
|
||||||
|
|
||||||
|
liblbos::syscalls::wait_until_alone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,6 +8,7 @@ mkdir -p mount
|
||||||
mount "${storage_device}" mount
|
mount "${storage_device}" mount
|
||||||
|
|
||||||
echo "COPYING..."
|
echo "COPYING..."
|
||||||
|
cp -v blood/target/riscv32imac-unknown-none-elf/release/BLOOD.DDI mount
|
||||||
cp -v turntable/target/riscv32imac-unknown-none-elf/release/TURNTBL.DDI mount
|
cp -v turntable/target/riscv32imac-unknown-none-elf/release/TURNTBL.DDI mount
|
||||||
cp -v example/target/riscv32imac-unknown-none-elf/release/EXAMPLE.DDI mount
|
cp -v example/target/riscv32imac-unknown-none-elf/release/EXAMPLE.DDI mount
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@ mod arch;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct TaskSetup {
|
pub struct TaskSetup {
|
||||||
pub epc: usize,
|
pub epc: usize,
|
||||||
|
pub stack_block_count: usize,
|
||||||
|
/// MUST BE NON-ZERO
|
||||||
pub ddi_first_addr: usize,
|
pub ddi_first_addr: usize,
|
||||||
pub ddi_size: usize,
|
pub ddi_size: usize,
|
||||||
pub environment: usize,
|
pub environment: usize,
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,8 @@ pub enum SysCall {
|
||||||
/// if there is no device providing a gpu, this will not do anything
|
/// if there is no device providing a gpu, this will not do anything
|
||||||
FlushFramebufferRect = 18,
|
FlushFramebufferRect = 18,
|
||||||
|
|
||||||
|
/// doens't return until all other tasks besides the current task and the ktask have exited
|
||||||
|
WaitUntilAlone = 333,
|
||||||
/// initializes kernel, ONLY CALL ONCE! IN FACT, YOU PROBABLY NEVER NEED TO CALL THIS
|
/// initializes kernel, ONLY CALL ONCE! IN FACT, YOU PROBABLY NEVER NEED TO CALL THIS
|
||||||
InitKernel = 666
|
InitKernel = 666
|
||||||
}
|
}
|
||||||
|
|
@ -110,6 +112,7 @@ pub fn usize2sc(u: usize) -> SysCall {
|
||||||
16 => SysCall::EnableFramebufferConsole,
|
16 => SysCall::EnableFramebufferConsole,
|
||||||
17 => SysCall::FramebufferPointer,
|
17 => SysCall::FramebufferPointer,
|
||||||
18 => SysCall::FlushFramebufferRect,
|
18 => SysCall::FlushFramebufferRect,
|
||||||
|
333 => SysCall::WaitUntilAlone,
|
||||||
666 => SysCall::InitKernel,
|
666 => SysCall::InitKernel,
|
||||||
_ => SysCall::NoAction,
|
_ => SysCall::NoAction,
|
||||||
}
|
}
|
||||||
|
|
@ -199,6 +202,10 @@ pub fn flush_framebuffer_rect(x: usize, y: usize, w: usize, h: usize) {
|
||||||
syscall(SysCall::FlushFramebufferRect, x, y, w, h, 0, 0);
|
syscall(SysCall::FlushFramebufferRect, x, y, w, h, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn wait_until_alone() {
|
||||||
|
syscall(SysCall::WaitUntilAlone, 0, 0, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn init_kernel() {
|
pub fn init_kernel() {
|
||||||
syscall(SysCall::InitKernel, 0, 0, 0, 0, 0, 0);
|
syscall(SysCall::InitKernel, 0, 0, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -81,6 +81,7 @@ extern "C" fn _virt_init() -> ! {
|
||||||
|
|
||||||
create_task(TaskSetup {
|
create_task(TaskSetup {
|
||||||
epc: ktask as usize,
|
epc: ktask as usize,
|
||||||
|
stack_block_count: 2,
|
||||||
ddi_first_addr: 0,
|
ddi_first_addr: 0,
|
||||||
ddi_size: 0,
|
ddi_size: 0,
|
||||||
environment: 0,
|
environment: 0,
|
||||||
|
|
|
||||||
15
src/main.rs
15
src/main.rs
|
|
@ -32,7 +32,7 @@ pub extern "C" fn ktask() -> ! {
|
||||||
syscalls::init_kernel();
|
syscalls::init_kernel();
|
||||||
print(b"kernel ready!\n");
|
print(b"kernel ready!\n");
|
||||||
|
|
||||||
// load TURNTBL.DDI
|
// load BLOOD.DDI
|
||||||
|
|
||||||
{
|
{
|
||||||
fn fserr() {
|
fn fserr() {
|
||||||
|
|
@ -62,13 +62,13 @@ pub extern "C" fn ktask() -> ! {
|
||||||
record_name == name
|
record_name == name
|
||||||
}
|
}
|
||||||
|
|
||||||
while !namecmp(&record, b"TURNTBL.DDI") {
|
while !namecmp(&record, b"BLOOD.DDI") {
|
||||||
if !fs::read_one_record(
|
if !fs::read_one_record(
|
||||||
unsafe { &*(&fs as *const _ as *const _) },
|
unsafe { &*(&fs as *const _ as *const _) },
|
||||||
unsafe { &mut *(&mut dir as *mut _ as *mut _) },
|
unsafe { &mut *(&mut dir as *mut _ as *mut _) },
|
||||||
unsafe { &mut *(&mut record as *mut _ as *mut _) }
|
unsafe { &mut *(&mut record as *mut _ as *mut _) }
|
||||||
) {
|
) {
|
||||||
print(b"TURNTBL.DDI NOT FOUND ):");
|
print(b"BLOOD.DDI NOT FOUND ):");
|
||||||
print(b"\n");
|
print(b"\n");
|
||||||
rough_panic(['t', 't', 'b']);
|
rough_panic(['t', 't', 'b']);
|
||||||
}
|
}
|
||||||
|
|
@ -89,23 +89,28 @@ pub extern "C" fn ktask() -> ! {
|
||||||
unsafe { &mut *(&mut reader as *mut _ as *mut _) },
|
unsafe { &mut *(&mut reader as *mut _ as *mut _) },
|
||||||
unsafe { core::slice::from_raw_parts_mut(buf as *mut _, size) }
|
unsafe { core::slice::from_raw_parts_mut(buf as *mut _, size) }
|
||||||
) != 0 {
|
) != 0 {
|
||||||
print(b"TURNTBL.DDI READ ERROR ):");
|
print(b"BLOOD.DDI READ ERROR ):");
|
||||||
print(b"\n");
|
print(b"\n");
|
||||||
rough_panic(['f', 'r', 'e']);
|
rough_panic(['f', 'r', 'e']);
|
||||||
}
|
}
|
||||||
|
|
||||||
// load the ddi
|
// load the ddi
|
||||||
let file_contents = unsafe { core::slice::from_raw_parts(buf as *const _, size) };
|
let file_contents = unsafe { core::slice::from_raw_parts(buf as *const _, size) };
|
||||||
|
let file_size = size;
|
||||||
if let Ok((entrypoint, first_addr, size)) = ddi::load_ddi(&file_contents) {
|
if let Ok((entrypoint, first_addr, size)) = ddi::load_ddi(&file_contents) {
|
||||||
|
// free the buffer
|
||||||
|
syscalls::free_blocks(buf, file_size.div_ceil(512));
|
||||||
|
|
||||||
create_task(TaskSetup {
|
create_task(TaskSetup {
|
||||||
epc: entrypoint,
|
epc: entrypoint,
|
||||||
|
stack_block_count: 1,
|
||||||
ddi_first_addr: first_addr,
|
ddi_first_addr: first_addr,
|
||||||
ddi_size: size,
|
ddi_size: size,
|
||||||
environment: 0,
|
environment: 0,
|
||||||
wait_for_task_exit: false,
|
wait_for_task_exit: false,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
print(b"TURNTBL.DDI INVALID DDI ):");
|
print(b"BLOOD.DDI INVALID DDI ):");
|
||||||
print(b"\n");
|
print(b"\n");
|
||||||
rough_panic(['t', 't', 'b']);
|
rough_panic(['t', 't', 'b']);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ impl MemoryManager {
|
||||||
uart.putstr("heap_start: ");
|
uart.putstr("heap_start: ");
|
||||||
uart.put_bytes(&u32_hex(_heap_start as u32));
|
uart.put_bytes(&u32_hex(_heap_start as u32));
|
||||||
uart.putstr("totalmem: ");
|
uart.putstr("totalmem: ");
|
||||||
uart.put_bytes(&u32_hex(_heap_size as u32));
|
uart.put_bytes(&u32_hex(_heap_size as u32 / BLOCK_SIZE as u32));
|
||||||
uart.putstr("\n");
|
uart.putstr("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,9 @@ pub enum TaskWait {
|
||||||
HardBlockDevOperation = 1 << 0,
|
HardBlockDevOperation = 1 << 0,
|
||||||
WaitForNotification = 1 << 1,
|
WaitForNotification = 1 << 1,
|
||||||
WaitForTaskExit = 1 << 2,
|
WaitForTaskExit = 1 << 2,
|
||||||
|
WaitUntilAlone = 1 << 7,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const STACK_SIZE_IN_BLOCKS: usize = 8;
|
|
||||||
|
|
||||||
pub const MAX_TASKS: usize = 8;
|
pub const MAX_TASKS: usize = 8;
|
||||||
|
|
||||||
pub static TC: Spinlock<TrafficControl> = Spinlock::new(TrafficControl::empty());
|
pub static TC: Spinlock<TrafficControl> = Spinlock::new(TrafficControl::empty());
|
||||||
|
|
@ -69,13 +68,15 @@ pub fn handle_syscall(
|
||||||
SysCall::CreateTask => {
|
SysCall::CreateTask => {
|
||||||
let add = a1 as *mut TaskSetup;
|
let add = a1 as *mut TaskSetup;
|
||||||
|
|
||||||
|
let stack_size_in_blocks = unsafe { (*add).stack_block_count };
|
||||||
|
|
||||||
tc.init_mem_if_not();
|
tc.init_mem_if_not();
|
||||||
let sp = unsafe {
|
let sp = unsafe {
|
||||||
tc.memory_manager
|
tc.memory_manager
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap_unchecked()
|
.unwrap_unchecked()
|
||||||
.alloc_n_blocks(STACK_SIZE_IN_BLOCKS)
|
.alloc_n_blocks(stack_size_in_blocks)
|
||||||
} + (BLOCK_SIZE * STACK_SIZE_IN_BLOCKS);
|
} + (BLOCK_SIZE * stack_size_in_blocks);
|
||||||
|
|
||||||
#[cfg(feature = "arch_virt")]
|
#[cfg(feature = "arch_virt")]
|
||||||
let t = Some(Task {
|
let t = Some(Task {
|
||||||
|
|
@ -83,6 +84,7 @@ pub fn handle_syscall(
|
||||||
environment: unsafe { (*add).environment },
|
environment: unsafe { (*add).environment },
|
||||||
want_exit: false,
|
want_exit: false,
|
||||||
sp,
|
sp,
|
||||||
|
stack_size_in_blocks,
|
||||||
wait: 0,
|
wait: 0,
|
||||||
incoming_notifications: [const { None }; MAX_TASKS],
|
incoming_notifications: [const { None }; MAX_TASKS],
|
||||||
ackwait: [0; MAX_TASKS],
|
ackwait: [0; MAX_TASKS],
|
||||||
|
|
@ -90,7 +92,7 @@ pub fn handle_syscall(
|
||||||
ddi_mem_start: unsafe {
|
ddi_mem_start: unsafe {
|
||||||
(*add).ddi_first_addr
|
(*add).ddi_first_addr
|
||||||
},
|
},
|
||||||
ddi_mem_blocks_count: unsafe { (*add).ddi_size / BLOCK_SIZE },
|
ddi_mem_blocks_count: unsafe { (*add).ddi_size.div_ceil(BLOCK_SIZE) },
|
||||||
trap_frame: arch::virt::tasks::setup_task(sp),
|
trap_frame: arch::virt::tasks::setup_task(sp),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -371,6 +373,13 @@ pub fn handle_syscall(
|
||||||
crate::dev::framebuffer_push(&mut tc, x, y, w, h);
|
crate::dev::framebuffer_push(&mut tc, x, y, w, h);
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
SysCall::WaitUntilAlone => {
|
||||||
|
let ci = tc.current;
|
||||||
|
let mut task = tc.tasks[ci].as_mut().unwrap();
|
||||||
|
task.wait |= TaskWait::WaitForTaskExit as u32;
|
||||||
|
suspend = true;
|
||||||
|
0
|
||||||
|
}
|
||||||
},
|
},
|
||||||
suspend,
|
suspend,
|
||||||
)
|
)
|
||||||
|
|
@ -380,7 +389,12 @@ pub fn context_switch<'a>(tc: &'a mut TrafficControl, current: Task) -> Option<&
|
||||||
let ci = tc.current;
|
let ci = tc.current;
|
||||||
tc.tasks[ci] = Some(current);
|
tc.tasks[ci] = Some(current);
|
||||||
|
|
||||||
|
let mut remaining_tasks = 0;
|
||||||
|
|
||||||
for i in 0..tc.tasks.len() {
|
for i in 0..tc.tasks.len() {
|
||||||
|
if tc.tasks[i].is_some() {
|
||||||
|
remaining_tasks += 1;
|
||||||
|
}
|
||||||
let want_exit = tc.tasks[i]
|
let want_exit = tc.tasks[i]
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|task| task.want_exit)
|
.map(|task| task.want_exit)
|
||||||
|
|
@ -390,12 +404,13 @@ pub fn context_switch<'a>(tc: &'a mut TrafficControl, current: Task) -> Option<&
|
||||||
let sp = tc.tasks[i].as_ref().map(|v| v.sp).unwrap_or(0);
|
let sp = tc.tasks[i].as_ref().map(|v| v.sp).unwrap_or(0);
|
||||||
let ddi_start_block = tc.tasks[i].as_ref().map(|v| v.ddi_mem_start).unwrap_or(0);
|
let ddi_start_block = tc.tasks[i].as_ref().map(|v| v.ddi_mem_start).unwrap_or(0);
|
||||||
let ddi_blocks_count = tc.tasks[i].as_ref().map(|v| v.ddi_mem_blocks_count).unwrap_or(0);
|
let ddi_blocks_count = tc.tasks[i].as_ref().map(|v| v.ddi_mem_blocks_count).unwrap_or(0);
|
||||||
|
let stack_size_in_blocks = tc.tasks[i].as_ref().map(|v| v.stack_size_in_blocks).unwrap_or(0);
|
||||||
if sp != 0 {
|
if sp != 0 {
|
||||||
unsafe {
|
unsafe {
|
||||||
tc.memory_manager
|
tc.memory_manager
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap_unchecked()
|
.unwrap_unchecked()
|
||||||
.free_n_blocks(sp - (BLOCK_SIZE * STACK_SIZE_IN_BLOCKS), STACK_SIZE_IN_BLOCKS)
|
.free_n_blocks(sp - (BLOCK_SIZE * stack_size_in_blocks), stack_size_in_blocks)
|
||||||
};
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
tc.memory_manager.as_mut().unwrap_unchecked()
|
tc.memory_manager.as_mut().unwrap_unchecked()
|
||||||
|
|
@ -414,6 +429,17 @@ pub fn context_switch<'a>(tc: &'a mut TrafficControl, current: Task) -> Option<&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if remaining_tasks <= 2, then we need to wake up WaitUntilAlone tasks
|
||||||
|
if remaining_tasks <= 2 {
|
||||||
|
for task in &mut tc.tasks {
|
||||||
|
if let Some(task) = task {
|
||||||
|
if task.wait & TaskWait::WaitForTaskExit as u32 != 0 {
|
||||||
|
task.wait &= !(TaskWait::WaitForTaskExit as u32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut next_task = tc.current + 1;
|
let mut next_task = tc.current + 1;
|
||||||
if next_task >= MAX_TASKS {
|
if next_task >= MAX_TASKS {
|
||||||
next_task = 0;
|
next_task = 0;
|
||||||
|
|
@ -421,6 +447,19 @@ pub fn context_switch<'a>(tc: &'a mut TrafficControl, current: Task) -> Option<&
|
||||||
|
|
||||||
for _ in 0..(MAX_TASKS + 1) {
|
for _ in 0..(MAX_TASKS + 1) {
|
||||||
if let Some(task) = tc.tasks[next_task].as_ref() {
|
if let Some(task) = tc.tasks[next_task].as_ref() {
|
||||||
|
// check stack pointer and if it's oob
|
||||||
|
#[cfg(feature = "arch_virt")]
|
||||||
|
{
|
||||||
|
if task.sp != 0 {
|
||||||
|
if task.trap_frame.regs[2] < task.sp - (task.stack_size_in_blocks * BLOCK_SIZE) {
|
||||||
|
let uart = serial_port();
|
||||||
|
if let Some(uart) = uart {
|
||||||
|
uart.putstr("stack overflow\n");
|
||||||
|
}
|
||||||
|
rough_panic([';', '-', ';'])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if task.wait == 0 && {
|
if task.wait == 0 && {
|
||||||
let mut waiting = false;
|
let mut waiting = false;
|
||||||
for v in &task.ackwait {
|
for v in &task.ackwait {
|
||||||
|
|
@ -464,6 +503,7 @@ pub struct Task {
|
||||||
pub want_exit: bool,
|
pub want_exit: bool,
|
||||||
/// THE ORIGINAL STACK POINTER THAT THE TASK STARTED WITH
|
/// THE ORIGINAL STACK POINTER THAT THE TASK STARTED WITH
|
||||||
pub sp: usize,
|
pub sp: usize,
|
||||||
|
pub stack_size_in_blocks: usize,
|
||||||
pub wait: u32,
|
pub wait: u32,
|
||||||
pub incoming_notifications: [Option<usize>; MAX_TASKS],
|
pub incoming_notifications: [Option<usize>; MAX_TASKS],
|
||||||
pub ackwait: [u8; MAX_TASKS], // 3 = they have not yet received the notification, 1 = they have received the notification, 0 = we know they received the notification, or don't care
|
pub ackwait: [u8; MAX_TASKS], // 3 = they have not yet received the notification, 1 = they have received the notification, 0 = we know they received the notification, or don't care
|
||||||
|
|
|
||||||
|
|
@ -187,13 +187,16 @@ fn attempt_run_file(env: &Environment<'_>, name: &str) {
|
||||||
current_directory_path: CURRENT_DIR_PATH.load(Ordering::Relaxed) as usize,
|
current_directory_path: CURRENT_DIR_PATH.load(Ordering::Relaxed) as usize,
|
||||||
current_directory_path_len: CURRENT_DIR_PATH_LEN.load(Ordering::Relaxed),
|
current_directory_path_len: CURRENT_DIR_PATH_LEN.load(Ordering::Relaxed),
|
||||||
};
|
};
|
||||||
|
// fixme: turntable task needs to exit, but it owns the environment memory.
|
||||||
|
// fixme: we need to somehow pass the environment to the task, and have it free the memory
|
||||||
|
|
||||||
let mut task_setup = liblbos::TaskSetup {
|
let mut task_setup = liblbos::TaskSetup {
|
||||||
epc: 0,
|
epc: 0,
|
||||||
|
stack_block_count: 8,
|
||||||
ddi_first_addr: 0,
|
ddi_first_addr: 0,
|
||||||
ddi_size: 0,
|
ddi_size: 0,
|
||||||
environment: &e as *const _ as usize,
|
environment: 0,
|
||||||
wait_for_task_exit: true,
|
wait_for_task_exit: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
if liblbos::ktask::ktask_loadddifile(buf, size, &mut task_setup as *mut _ as usize) != 0 {
|
if liblbos::ktask::ktask_loadddifile(buf, size, &mut task_setup as *mut _ as usize) != 0 {
|
||||||
|
|
@ -206,11 +209,11 @@ fn attempt_run_file(env: &Environment<'_>, name: &str) {
|
||||||
|
|
||||||
liblbos::syscalls::create_task(task_setup);
|
liblbos::syscalls::create_task(task_setup);
|
||||||
|
|
||||||
// yeah we're extending its lifetime
|
if CURRENT_DIR_PATH.load(Ordering::Relaxed) as usize != 0 {
|
||||||
#[allow(clippy::drop_non_drop)]
|
// free
|
||||||
drop(e);
|
liblbos::syscalls::free_blocks(CURRENT_DIR_PATH.load(Ordering::Relaxed) as usize, CURRENT_DIR_PATH_LEN.load(Ordering::Relaxed).div_ceil(512));
|
||||||
|
}
|
||||||
println("\ntask exited\n");
|
liblbos::syscalls::exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(cmd: &str, environment: &mut Environment<'_>) {
|
fn execute(cmd: &str, environment: &mut Environment<'_>) {
|
||||||
|
|
@ -233,6 +236,10 @@ fn execute(cmd: &str, environment: &mut Environment<'_>) {
|
||||||
if NO_EXIT.load(Ordering::Relaxed) {
|
if NO_EXIT.load(Ordering::Relaxed) {
|
||||||
println("cannot exit as task 1");
|
println("cannot exit as task 1");
|
||||||
} else {
|
} else {
|
||||||
|
if CURRENT_DIR_PATH.load(Ordering::Relaxed) as usize != 0 {
|
||||||
|
// free
|
||||||
|
liblbos::syscalls::free_blocks(CURRENT_DIR_PATH.load(Ordering::Relaxed) as usize, CURRENT_DIR_PATH_LEN.load(Ordering::Relaxed).div_ceil(512));
|
||||||
|
}
|
||||||
liblbos::syscalls::exit();
|
liblbos::syscalls::exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -260,8 +267,7 @@ fn hex(mut n: u8) -> [u8; 2] {
|
||||||
mod arch;
|
mod arch;
|
||||||
mod terminal;
|
mod terminal;
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
fn main_wrapper() {
|
||||||
extern "C" fn main() {
|
|
||||||
let tid = liblbos::syscalls::current_task();
|
let tid = liblbos::syscalls::current_task();
|
||||||
NO_EXIT.store(tid == 1, Ordering::Relaxed);
|
NO_EXIT.store(tid == 1, Ordering::Relaxed);
|
||||||
|
|
||||||
|
|
@ -341,3 +347,12 @@ extern "C" fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
extern "C" fn main() {
|
||||||
|
main_wrapper();
|
||||||
|
if CURRENT_DIR_PATH.load(Ordering::Relaxed) as usize != 0 {
|
||||||
|
// free
|
||||||
|
liblbos::syscalls::free_blocks(CURRENT_DIR_PATH.load(Ordering::Relaxed) as usize, CURRENT_DIR_PATH_LEN.load(Ordering::Relaxed).div_ceil(512));
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue