Stage2: multiple user threads based on uniprocessor, see new added test race_adder and threads.
This commit is contained in:
parent
4fa4e9cab4
commit
a341b338c8
12 changed files with 254 additions and 57 deletions
|
@ -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 {
|
||||
|
|
36
user/src/bin/race_adder.rs
Normal file
36
user/src/bin/race_adder.rs
Normal 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
38
user/src/bin/threads.rs
Normal 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
|
||||
}
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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])
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue