mirror of
https://github.com/rcore-os/rCore-Tutorial-v3.git
synced 2024-11-22 09:26:26 +04:00
Handle backspace for k210/qemu platform && Add lots of user tests.
This commit is contained in:
parent
9165e64d1b
commit
244c0ee84d
@ -48,6 +48,7 @@ impl StackFrameAllocator {
|
|||||||
pub fn init(&mut self, l: PhysPageNum, r: PhysPageNum) {
|
pub fn init(&mut self, l: PhysPageNum, r: PhysPageNum) {
|
||||||
self.current = l.0;
|
self.current = l.0;
|
||||||
self.end = r.0;
|
self.end = r.0;
|
||||||
|
println!("last {} Physical Frames.", self.end - self.current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl FrameAllocator for StackFrameAllocator {
|
impl FrameAllocator for StackFrameAllocator {
|
||||||
|
@ -47,10 +47,6 @@ impl MemorySet {
|
|||||||
areas: Vec::new(),
|
areas: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[allow(unused)]
|
|
||||||
pub fn dealloc_all_frames(&mut self) {
|
|
||||||
*self = Self::new_bare();
|
|
||||||
}
|
|
||||||
pub fn token(&self) -> usize {
|
pub fn token(&self) -> usize {
|
||||||
self.page_table.token()
|
self.page_table.token()
|
||||||
}
|
}
|
||||||
@ -217,7 +213,8 @@ impl MemorySet {
|
|||||||
self.page_table.translate(vpn)
|
self.page_table.translate(vpn)
|
||||||
}
|
}
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
*self = Self::new_bare();
|
//*self = Self::new_bare();
|
||||||
|
self.areas.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ use crate::task::{
|
|||||||
current_user_token,
|
current_user_token,
|
||||||
add_task,
|
add_task,
|
||||||
};
|
};
|
||||||
use crate::timer::get_time;
|
use crate::timer::get_time_ms;
|
||||||
use crate::mm::{
|
use crate::mm::{
|
||||||
translated_str,
|
translated_str,
|
||||||
translated_refmut,
|
translated_refmut,
|
||||||
@ -14,18 +14,7 @@ use crate::loader::get_app_data_by_name;
|
|||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
|
|
||||||
pub fn sys_exit(exit_code: i32) -> ! {
|
pub fn sys_exit(exit_code: i32) -> ! {
|
||||||
// save exit code
|
exit_current_and_run_next(exit_code);
|
||||||
let task = current_task().unwrap();
|
|
||||||
|
|
||||||
// ---- hold current PCB lock
|
|
||||||
task.acquire_inner_lock().exit_code = exit_code;
|
|
||||||
// ---- release current PCB lock
|
|
||||||
|
|
||||||
// this function will not return
|
|
||||||
// drop task manually to maintain rc correctly
|
|
||||||
drop(task);
|
|
||||||
|
|
||||||
exit_current_and_run_next();
|
|
||||||
panic!("Unreachable in sys_exit!");
|
panic!("Unreachable in sys_exit!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,7 +24,7 @@ pub fn sys_yield() -> isize {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn sys_get_time() -> isize {
|
pub fn sys_get_time() -> isize {
|
||||||
get_time() as isize
|
get_time_ms() as isize
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sys_getpid() -> isize {
|
pub fn sys_getpid() -> isize {
|
||||||
@ -68,11 +57,21 @@ pub fn sys_exec(path: *const u8) -> isize {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If there is not a child process whose pid is same as given, return -1.
|
||||||
|
/// Else if there is a child process but it is still running, return -2.
|
||||||
pub fn sys_waitpid(pid: isize, exit_code_ptr: *mut i32) -> isize {
|
pub fn sys_waitpid(pid: isize, exit_code_ptr: *mut i32) -> isize {
|
||||||
let task = current_task().unwrap();
|
let task = current_task().unwrap();
|
||||||
// find a child process
|
// find a child process
|
||||||
|
|
||||||
// ---- hold current PCB lock
|
// ---- hold current PCB lock
|
||||||
let mut inner = task.acquire_inner_lock();
|
let mut inner = task.acquire_inner_lock();
|
||||||
|
if inner.children
|
||||||
|
.iter()
|
||||||
|
.find(|p| {pid == -1 || pid as usize == p.getpid()})
|
||||||
|
.is_none() {
|
||||||
|
return -1;
|
||||||
|
// ---- release current PCB lock
|
||||||
|
}
|
||||||
let pair = inner.children
|
let pair = inner.children
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
@ -92,7 +91,7 @@ pub fn sys_waitpid(pid: isize, exit_code_ptr: *mut i32) -> isize {
|
|||||||
*translated_refmut(inner.memory_set.token(), exit_code_ptr) = exit_code;
|
*translated_refmut(inner.memory_set.token(), exit_code_ptr) = exit_code;
|
||||||
found_pid as isize
|
found_pid as isize
|
||||||
} else {
|
} else {
|
||||||
-1
|
-2
|
||||||
}
|
}
|
||||||
// ---- release current PCB lock automatically
|
// ---- release current PCB lock automatically
|
||||||
}
|
}
|
@ -42,14 +42,17 @@ pub fn suspend_current_and_run_next() {
|
|||||||
schedule(task_cx_ptr);
|
schedule(task_cx_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exit_current_and_run_next() {
|
pub fn exit_current_and_run_next(exit_code: i32) {
|
||||||
// take from Processor
|
// take from Processor
|
||||||
let task = take_current_task().unwrap();
|
let task = take_current_task().unwrap();
|
||||||
// **** hold current PCB lock
|
// **** hold current PCB lock
|
||||||
let mut inner = task.acquire_inner_lock();
|
let mut inner = task.acquire_inner_lock();
|
||||||
// Change status to Zombie
|
// Change status to Zombie
|
||||||
inner.task_status = TaskStatus::Zombie;
|
inner.task_status = TaskStatus::Zombie;
|
||||||
|
// Record exit code
|
||||||
|
inner.exit_code = exit_code;
|
||||||
// move any child to its parent
|
// move any child to its parent
|
||||||
|
// TODO: do not move to its parent but under initproc
|
||||||
|
|
||||||
// ++++++ hold parent PCB lock here
|
// ++++++ hold parent PCB lock here
|
||||||
{
|
{
|
||||||
|
@ -3,11 +3,16 @@ use crate::sbi::set_timer;
|
|||||||
use crate::config::CPU_FREQ;
|
use crate::config::CPU_FREQ;
|
||||||
|
|
||||||
const TICKS_PER_SEC: usize = 100;
|
const TICKS_PER_SEC: usize = 100;
|
||||||
|
const MSEC_PER_SEC: usize = 1000;
|
||||||
|
|
||||||
pub fn get_time() -> usize {
|
pub fn get_time() -> usize {
|
||||||
time::read()
|
time::read()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_time_ms() -> usize {
|
||||||
|
time::read() / (CPU_FREQ / MSEC_PER_SEC)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_next_trigger() {
|
pub fn set_next_trigger() {
|
||||||
set_timer(get_time() + CPU_FREQ / TICKS_PER_SEC);
|
set_timer(get_time() + CPU_FREQ / TICKS_PER_SEC);
|
||||||
}
|
}
|
@ -67,13 +67,24 @@ pub fn trap_handler() -> ! {
|
|||||||
cx.x[10] = result as usize;
|
cx.x[10] = result as usize;
|
||||||
}
|
}
|
||||||
Trap::Exception(Exception::StoreFault) |
|
Trap::Exception(Exception::StoreFault) |
|
||||||
Trap::Exception(Exception::StorePageFault) => {
|
Trap::Exception(Exception::StorePageFault) |
|
||||||
println!("[kernel] PageFault in application, bad addr = {:#x}, bad instruction = {:#x}, core dumped.", stval, current_trap_cx().sepc);
|
Trap::Exception(Exception::InstructionFault) |
|
||||||
exit_current_and_run_next();
|
Trap::Exception(Exception::InstructionPageFault) |
|
||||||
|
Trap::Exception(Exception::LoadFault) |
|
||||||
|
Trap::Exception(Exception::LoadPageFault) => {
|
||||||
|
println!(
|
||||||
|
"[kernel] {:?} in application, bad addr = {:#x}, bad instruction = {:#x}, core dumped.",
|
||||||
|
scause.cause(),
|
||||||
|
stval,
|
||||||
|
current_trap_cx().sepc,
|
||||||
|
);
|
||||||
|
// page fault exit code
|
||||||
|
exit_current_and_run_next(-2);
|
||||||
}
|
}
|
||||||
Trap::Exception(Exception::IllegalInstruction) => {
|
Trap::Exception(Exception::IllegalInstruction) => {
|
||||||
println!("[kernel] IllegalInstruction in application, core dumped.");
|
println!("[kernel] IllegalInstruction in application, core dumped.");
|
||||||
exit_current_and_run_next();
|
// illegal instruction exit code
|
||||||
|
exit_current_and_run_next(-3);
|
||||||
}
|
}
|
||||||
Trap::Interrupt(Interrupt::SupervisorTimer) => {
|
Trap::Interrupt(Interrupt::SupervisorTimer) => {
|
||||||
set_next_trigger();
|
set_next_trigger();
|
||||||
|
29
user/src/bin/exit.rs
Normal file
29
user/src/bin/exit.rs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate user_lib;
|
||||||
|
use user_lib::{fork, yield_, waitpid, exit, wait};
|
||||||
|
|
||||||
|
const MAGIC: i32 = -0x10384;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn main() -> i32 {
|
||||||
|
println!("I am the parent. Forking the child...");
|
||||||
|
let pid = fork();
|
||||||
|
if pid == 0 {
|
||||||
|
println!("I am the child.");
|
||||||
|
for _ in 0..7 { yield_(); }
|
||||||
|
exit(MAGIC);
|
||||||
|
} else {
|
||||||
|
println!("I am parent, fork a child pid {}", pid);
|
||||||
|
}
|
||||||
|
println!("I am the parent, waiting now..");
|
||||||
|
let mut xstate: i32 = 0;
|
||||||
|
assert!(waitpid(pid as usize, &mut xstate) == pid && xstate == MAGIC);
|
||||||
|
assert!(waitpid(pid as usize, &mut xstate) < 0 && wait(&mut xstate) <= 0);
|
||||||
|
println!("waitpid {} ok.", pid);
|
||||||
|
println!("exit pass.");
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
44
user/src/bin/fantastic_text.rs
Normal file
44
user/src/bin/fantastic_text.rs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate user_lib;
|
||||||
|
|
||||||
|
macro_rules! color_text {
|
||||||
|
($text:expr, $color:expr) => {{
|
||||||
|
format_args!("\x1b[{}m{}\x1b[0m", $color, $text)
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn main() -> i32 {
|
||||||
|
println!(
|
||||||
|
"{}{}{}{}{} {}{}{}{} {}{}{}{}{}{}",
|
||||||
|
color_text!("H", 31),
|
||||||
|
color_text!("e", 32),
|
||||||
|
color_text!("l", 33),
|
||||||
|
color_text!("l", 34),
|
||||||
|
color_text!("o", 35),
|
||||||
|
color_text!("R", 36),
|
||||||
|
color_text!("u", 37),
|
||||||
|
color_text!("s", 90),
|
||||||
|
color_text!("t", 91),
|
||||||
|
color_text!("u", 92),
|
||||||
|
color_text!("C", 93),
|
||||||
|
color_text!("o", 94),
|
||||||
|
color_text!("r", 95),
|
||||||
|
color_text!("e", 96),
|
||||||
|
color_text!("!", 97),
|
||||||
|
);
|
||||||
|
|
||||||
|
let text =
|
||||||
|
"reguler \x1b[4munderline\x1b[24m \x1b[7mreverse\x1b[27m \x1b[9mstrikethrough\x1b[29m";
|
||||||
|
println!("\x1b[47m{}\x1b[0m", color_text!(text, 30));
|
||||||
|
for i in 31..38 {
|
||||||
|
println!("{}", color_text!(text, i));
|
||||||
|
}
|
||||||
|
for i in 90..98 {
|
||||||
|
println!("{}", color_text!(text, i));
|
||||||
|
}
|
||||||
|
0
|
||||||
|
}
|
34
user/src/bin/forktest.rs
Normal file
34
user/src/bin/forktest.rs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate user_lib;
|
||||||
|
|
||||||
|
use user_lib::{fork, wait, exit};
|
||||||
|
|
||||||
|
const MAX_CHILD: usize = 20;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn main() -> i32 {
|
||||||
|
for i in 0..MAX_CHILD {
|
||||||
|
let pid = fork();
|
||||||
|
if pid == 0 {
|
||||||
|
println!("I am child {}", i);
|
||||||
|
exit(0);
|
||||||
|
} else {
|
||||||
|
println!("forked child pid = {}", pid);
|
||||||
|
}
|
||||||
|
assert!(pid > 0);
|
||||||
|
}
|
||||||
|
let mut exit_code: i32 = 0;
|
||||||
|
for _ in 0..MAX_CHILD {
|
||||||
|
if wait(&mut exit_code) <= 0 {
|
||||||
|
panic!("wait stopped early");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if wait(&mut exit_code) > 0 {
|
||||||
|
panic!("wait got too many");
|
||||||
|
}
|
||||||
|
println!("forktest pass.");
|
||||||
|
0
|
||||||
|
}
|
35
user/src/bin/forktest2.rs
Normal file
35
user/src/bin/forktest2.rs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate user_lib;
|
||||||
|
|
||||||
|
use user_lib::{fork, wait, get_time, getpid, exit, yield_,};
|
||||||
|
|
||||||
|
static NUM: usize = 13;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn main() -> i32 {
|
||||||
|
for _ in 0..NUM {
|
||||||
|
let pid = fork();
|
||||||
|
if pid == 0 {
|
||||||
|
let current_time = get_time();
|
||||||
|
let sleep_length = (current_time as i32 as isize) * (current_time as i32 as isize) % 1000 + 1000;
|
||||||
|
println!("Subprocess {} sleep for {} ms", getpid(), sleep_length);
|
||||||
|
while get_time() < current_time + sleep_length {
|
||||||
|
yield_();
|
||||||
|
}
|
||||||
|
println!("Subprocess {} OK!", getpid());
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut xstate: i32 = 0;
|
||||||
|
for _ in 0..NUM {
|
||||||
|
assert!(wait(&mut xstate) > 0);
|
||||||
|
assert_eq!(xstate, 0);
|
||||||
|
}
|
||||||
|
assert!(wait(&mut xstate) < 0);
|
||||||
|
println!("r_forktest2 test passed!");
|
||||||
|
0
|
||||||
|
}
|
28
user/src/bin/forktest_simple.rs
Normal file
28
user/src/bin/forktest_simple.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate user_lib;
|
||||||
|
|
||||||
|
use user_lib::{fork, getpid, wait};
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn main() -> i32 {
|
||||||
|
assert_eq!(wait(&mut 0i32), -1);
|
||||||
|
println!("sys_wait without child process test passed!");
|
||||||
|
println!("parent start, pid = {}!", getpid());
|
||||||
|
let pid = fork();
|
||||||
|
if pid == 0 {
|
||||||
|
// child process
|
||||||
|
println!("hello child process!");
|
||||||
|
100
|
||||||
|
} else {
|
||||||
|
// parent process
|
||||||
|
let mut xstate: i32 = 0;
|
||||||
|
println!("ready waiting on parent process!");
|
||||||
|
assert_eq!(pid, wait(&mut xstate));
|
||||||
|
assert_eq!(xstate, 100);
|
||||||
|
println!("child process pid = {}, exit code = {}", pid, xstate);
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
11
user/src/bin/hello_world.rs
Normal file
11
user/src/bin/hello_world.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate user_lib;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn main() -> i32 {
|
||||||
|
println!("Hello world from user mode program!");
|
||||||
|
0
|
||||||
|
}
|
@ -4,9 +4,9 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate user_lib;
|
extern crate user_lib;
|
||||||
|
|
||||||
use user_lib::{fork, wait, yield_, exit, getpid, get_time, wait_once};
|
use user_lib::{fork, wait, yield_, exit, getpid, get_time};
|
||||||
|
|
||||||
static NUM: usize = 13;
|
static NUM: usize = 20;
|
||||||
const N: usize = 10;
|
const N: usize = 10;
|
||||||
static P: i32 = 10007;
|
static P: i32 = 10007;
|
||||||
type Arr = [[i32; N]; N];
|
type Arr = [[i32; N]; N];
|
||||||
@ -50,7 +50,7 @@ pub fn main() -> i32 {
|
|||||||
if pid == 0 {
|
if pid == 0 {
|
||||||
let current_time = get_time();
|
let current_time = get_time();
|
||||||
let times = (current_time as i32 as isize) * (current_time as i32 as isize) % 1000;
|
let times = (current_time as i32 as isize) * (current_time as i32 as isize) % 1000;
|
||||||
work(times * 40);
|
work(times * 10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ pub fn main() -> i32 {
|
|||||||
panic!("wait failed.");
|
panic!("wait failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert!(wait_once(&mut xstate) < 0);
|
assert!(wait(&mut xstate) < 0);
|
||||||
println!("matrix passed.");
|
println!("matrix passed.");
|
||||||
0
|
0
|
||||||
}
|
}
|
30
user/src/bin/sleep.rs
Normal file
30
user/src/bin/sleep.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate user_lib;
|
||||||
|
|
||||||
|
use user_lib::{sleep, exit, get_time, fork, waitpid};
|
||||||
|
|
||||||
|
fn sleepy() {
|
||||||
|
let time: usize = 100;
|
||||||
|
for i in 0..5 {
|
||||||
|
sleep(time);
|
||||||
|
println!("sleep {} x {} msecs.", i + 1, time);
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn main() -> i32 {
|
||||||
|
let current_time = get_time();
|
||||||
|
let pid = fork();
|
||||||
|
let mut xstate: i32 = 0;
|
||||||
|
if pid == 0 {
|
||||||
|
sleepy();
|
||||||
|
}
|
||||||
|
assert!(waitpid(pid as usize, &mut xstate) == pid && xstate == 0);
|
||||||
|
println!("use {} msecs.", get_time() - current_time);
|
||||||
|
println!("sleep pass.");
|
||||||
|
0
|
||||||
|
}
|
19
user/src/bin/sleep_simple.rs
Normal file
19
user/src/bin/sleep_simple.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate user_lib;
|
||||||
|
|
||||||
|
use user_lib::{get_time, sleep};
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn main() -> i32 {
|
||||||
|
println!("into sleep test!");
|
||||||
|
let start = get_time();
|
||||||
|
println!("current time_msec = {}", start);
|
||||||
|
sleep(100);
|
||||||
|
let end = get_time();
|
||||||
|
println!("time_msec = {} after sleeping 100 ticks, delta = {}ms!", end, end - start);
|
||||||
|
println!("r_sleep passed!");
|
||||||
|
0
|
||||||
|
}
|
17
user/src/bin/stack_overflow.rs
Normal file
17
user/src/bin/stack_overflow.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate user_lib;
|
||||||
|
|
||||||
|
fn f(d: usize) {
|
||||||
|
println!("d = {}",d);
|
||||||
|
f(d + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn main() -> i32 {
|
||||||
|
println!("It should trigger segmentation fault!");
|
||||||
|
f(0);
|
||||||
|
0
|
||||||
|
}
|
@ -53,7 +53,7 @@ pub fn main() -> i32 {
|
|||||||
}
|
}
|
||||||
print!(">> ");
|
print!(">> ");
|
||||||
}
|
}
|
||||||
DL => {
|
BS | DL => {
|
||||||
if !line.is_empty() {
|
if !line.is_empty() {
|
||||||
print!("{}", BS as char);
|
print!("{}", BS as char);
|
||||||
print!(" ");
|
print!(" ");
|
||||||
|
40
user/src/bin/usertests.rs
Normal file
40
user/src/bin/usertests.rs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate user_lib;
|
||||||
|
|
||||||
|
static TESTS: &[&str] = &[
|
||||||
|
"exit\0",
|
||||||
|
"fantastic_text\0",
|
||||||
|
"forktest\0",
|
||||||
|
"forktest2\0",
|
||||||
|
"forktest_simple\0",
|
||||||
|
"hello_world\0",
|
||||||
|
"matrix\0",
|
||||||
|
"sleep\0",
|
||||||
|
"sleep_simple\0",
|
||||||
|
"stack_overflow\0",
|
||||||
|
"yield\0",
|
||||||
|
];
|
||||||
|
|
||||||
|
use user_lib::{exec, fork, waitpid};
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn main() -> i32 {
|
||||||
|
for test in TESTS {
|
||||||
|
println!("Usertests: Running {}", test);
|
||||||
|
let pid = fork();
|
||||||
|
if pid == 0 {
|
||||||
|
exec(*test);
|
||||||
|
panic!("unreachable!");
|
||||||
|
} else {
|
||||||
|
let mut xstate: i32 = Default::default();
|
||||||
|
let wait_pid = waitpid(pid as usize, &mut xstate);
|
||||||
|
assert_eq!(pid, wait_pid);
|
||||||
|
println!("\x1b[32mUsertests: Test {} in Process {} exited with code {}\x1b[0m", test, pid, xstate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("Usertests passed!");
|
||||||
|
0
|
||||||
|
}
|
17
user/src/bin/yield.rs
Normal file
17
user/src/bin/yield.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate user_lib;
|
||||||
|
use user_lib::{getpid, yield_};
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn main() -> i32 {
|
||||||
|
println!("Hello, I am process {}.", getpid());
|
||||||
|
for i in 0..5 {
|
||||||
|
yield_();
|
||||||
|
println!("Back in process {}, iteration {}.", getpid(), i);
|
||||||
|
}
|
||||||
|
println!("yield pass.");
|
||||||
|
0
|
||||||
|
}
|
@ -51,19 +51,25 @@ pub fn exec(path: &str) -> isize { sys_exec(path) }
|
|||||||
pub fn wait(exit_code: &mut i32) -> isize {
|
pub fn wait(exit_code: &mut i32) -> isize {
|
||||||
loop {
|
loop {
|
||||||
match sys_waitpid(-1, exit_code as *mut _) {
|
match sys_waitpid(-1, exit_code as *mut _) {
|
||||||
-1 => { yield_(); }
|
-2 => { yield_(); }
|
||||||
|
// -1 or a real pid
|
||||||
exit_pid => return exit_pid,
|
exit_pid => return exit_pid,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn wait_once(exit_code: &mut i32) -> isize {
|
|
||||||
sys_waitpid(-1, exit_code as *mut _)
|
|
||||||
}
|
|
||||||
pub fn waitpid(pid: usize, exit_code: &mut i32) -> isize {
|
pub fn waitpid(pid: usize, exit_code: &mut i32) -> isize {
|
||||||
loop {
|
loop {
|
||||||
match sys_waitpid(pid as isize, exit_code as *mut _) {
|
match sys_waitpid(pid as isize, exit_code as *mut _) {
|
||||||
-1 => { yield_(); }
|
-2 => { yield_(); }
|
||||||
|
// -1 or a real pid
|
||||||
exit_pid => return exit_pid,
|
exit_pid => return exit_pid,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
pub fn sleep(period_ms: usize) {
|
||||||
|
let start = sys_get_time();
|
||||||
|
while sys_get_time() < start + period_ms as isize {
|
||||||
|
sys_yield();
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user