Stage2: multiple user threads based on uniprocessor, see new added test race_adder and threads.

This commit is contained in:
Yifan Wu 2021-10-02 16:18:05 -07:00
parent 4fa4e9cab4
commit a341b338c8
12 changed files with 254 additions and 57 deletions

View file

@ -13,7 +13,6 @@ use user_lib::{
#[no_mangle]
fn main() -> i32 {
println!("start initproc!");
if fork() == 0 {
exec("user_shell\0", &[0 as *const u8]);
} else {

View file

@ -0,0 +1,36 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
extern crate alloc;
use user_lib::{exit, thread_create, waittid};
use alloc::vec::Vec;
static mut A: usize = 0;
const PER_THREAD: usize = 10000000;
const THREAD_COUNT: usize = 50;
unsafe fn f() -> ! {
for _ in 0..PER_THREAD {
let a = &mut A as *mut usize;
let cur = a.read_volatile();
a.write_volatile(cur + 1);
}
exit(0)
}
#[no_mangle]
pub fn main() -> i32 {
let mut v = Vec::new();
for _ in 0..THREAD_COUNT {
v.push(thread_create(f as usize) as usize);
}
for tid in v.iter() {
waittid(*tid);
}
assert_eq!(unsafe { A }, PER_THREAD * THREAD_COUNT);
println!("total = {}", unsafe { A });
0
}

38
user/src/bin/threads.rs Normal file
View file

@ -0,0 +1,38 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
extern crate alloc;
use user_lib::{thread_create, waittid, exit};
use alloc::vec::Vec;
pub fn thread_a() -> ! {
for _ in 0..1000 { print!("a"); }
exit(1)
}
pub fn thread_b() -> ! {
for _ in 0..1000 { print!("b"); }
exit(2)
}
pub fn thread_c() -> ! {
for _ in 0..1000 { print!("c"); }
exit(3)
}
#[no_mangle]
pub fn main() -> i32 {
let mut v = Vec::new();
v.push(thread_create(thread_a as usize));
v.push(thread_create(thread_b as usize));
v.push(thread_create(thread_c as usize));
for tid in v.iter() {
let exit_code = waittid(*tid as usize);
println!("thread#{} exited with code {}", tid, exit_code);
}
println!("main thread exited.");
0
}

View file

@ -106,3 +106,14 @@ pub fn sleep(period_ms: usize) {
sys_yield();
}
}
pub fn thread_create(entry: usize) -> isize { sys_thread_create(entry) }
pub fn gettid() -> isize { sys_gettid() }
pub fn waittid(tid: usize) -> isize {
loop {
match sys_waittid(tid) {
-2 => { yield_(); }
exit_code => return exit_code,
}
}
}

View file

@ -11,6 +11,9 @@ const SYSCALL_GETPID: usize = 172;
const SYSCALL_FORK: usize = 220;
const SYSCALL_EXEC: usize = 221;
const SYSCALL_WAITPID: usize = 260;
const SYSCALL_THREAD_CREATE: usize = 1000;
const SYSCALL_GETTID: usize = 1001;
const SYSCALL_WAITTID: usize = 1002;
fn syscall(id: usize, args: [usize; 3]) -> isize {
let mut ret: isize;
@ -77,4 +80,16 @@ pub fn sys_exec(path: &str, args: &[*const u8]) -> isize {
pub fn sys_waitpid(pid: isize, exit_code: *mut i32) -> isize {
syscall(SYSCALL_WAITPID, [pid as usize, exit_code as usize, 0])
}
}
pub fn sys_thread_create(entry: usize) -> isize {
syscall(SYSCALL_THREAD_CREATE, [entry, 0, 0])
}
pub fn sys_gettid() -> isize {
syscall(SYSCALL_GETTID, [0; 3])
}
pub fn sys_waittid(tid: usize) -> isize {
syscall(SYSCALL_WAITTID, [tid, 0, 0])
}