add condvar in kernel and app
This commit is contained in:
parent
a3ec647496
commit
b3bce3bef2
8 changed files with 243 additions and 34 deletions
56
user/src/bin/test_condvar.rs
Normal file
56
user/src/bin/test_condvar.rs
Normal file
|
@ -0,0 +1,56 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
#[macro_use]
|
||||
extern crate user_lib;
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use user_lib::{condvar_create, condvar_signal, condvar_wait, mutex_blocking_create, mutex_lock, mutex_unlock};
|
||||
use user_lib::{thread_create, waittid, sleep};
|
||||
use user_lib::exit;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
static mut A: usize = 0;
|
||||
|
||||
const CONDVAR_ID: usize = 0;
|
||||
const MUTEX_ID: usize = 0;
|
||||
|
||||
unsafe fn first() -> ! {
|
||||
sleep(10);
|
||||
println!("First work, Change A --> 1 and wakeup Second");
|
||||
mutex_lock(MUTEX_ID);
|
||||
A=1;
|
||||
condvar_signal(CONDVAR_ID);
|
||||
mutex_unlock(MUTEX_ID);
|
||||
exit(0)
|
||||
}
|
||||
|
||||
unsafe fn second() -> ! {
|
||||
println!("Second want to continue,but need to wait A=1");
|
||||
mutex_lock(MUTEX_ID);
|
||||
while A==0 {
|
||||
println!("Second: A is {}", A);
|
||||
condvar_wait(CONDVAR_ID, MUTEX_ID);
|
||||
}
|
||||
mutex_unlock(MUTEX_ID);
|
||||
println!("A is {}, Second can work now", A);
|
||||
exit(0)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn main() -> i32 {
|
||||
// create condvar & mutex
|
||||
assert_eq!(condvar_create() as usize, CONDVAR_ID);
|
||||
assert_eq!(mutex_blocking_create() as usize, MUTEX_ID);
|
||||
// create threads
|
||||
let mut threads = Vec::new();
|
||||
threads.push(thread_create(first as usize, 0));
|
||||
threads.push(thread_create(second as usize, 0));
|
||||
// wait for all threads to complete
|
||||
for thread in threads.iter() {
|
||||
waittid(*thread as usize);
|
||||
}
|
||||
println!("test_condvar passed!");
|
||||
0
|
||||
}
|
114
user/src/lib.rs
114
user/src/lib.rs
|
@ -6,16 +6,16 @@
|
|||
|
||||
#[macro_use]
|
||||
pub mod console;
|
||||
mod syscall;
|
||||
mod lang_items;
|
||||
mod syscall;
|
||||
|
||||
extern crate alloc;
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
|
||||
use syscall::*;
|
||||
use buddy_system_allocator::LockedHeap;
|
||||
use alloc::vec::Vec;
|
||||
use buddy_system_allocator::LockedHeap;
|
||||
use syscall::*;
|
||||
|
||||
const USER_HEAP_SIZE: usize = 32768;
|
||||
|
||||
|
@ -38,16 +38,16 @@ pub extern "C" fn _start(argc: usize, argv: usize) -> ! {
|
|||
}
|
||||
let mut v: Vec<&'static str> = Vec::new();
|
||||
for i in 0..argc {
|
||||
let str_start = unsafe {
|
||||
((argv + i * core::mem::size_of::<usize>()) as *const usize).read_volatile()
|
||||
};
|
||||
let len = (0usize..).find(|i| unsafe {
|
||||
((str_start + *i) as *const u8).read_volatile() == 0
|
||||
}).unwrap();
|
||||
let str_start =
|
||||
unsafe { ((argv + i * core::mem::size_of::<usize>()) as *const usize).read_volatile() };
|
||||
let len = (0usize..)
|
||||
.find(|i| unsafe { ((str_start + *i) as *const u8).read_volatile() == 0 })
|
||||
.unwrap();
|
||||
v.push(
|
||||
core::str::from_utf8(unsafe {
|
||||
core::slice::from_raw_parts(str_start as *const u8, len)
|
||||
}).unwrap()
|
||||
})
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
exit(main(argc, v.as_slice()));
|
||||
|
@ -69,22 +69,48 @@ bitflags! {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn dup(fd: usize) -> isize { sys_dup(fd) }
|
||||
pub fn open(path: &str, flags: OpenFlags) -> isize { sys_open(path, flags.bits) }
|
||||
pub fn close(fd: usize) -> isize { sys_close(fd) }
|
||||
pub fn pipe(pipe_fd: &mut [usize]) -> isize { sys_pipe(pipe_fd) }
|
||||
pub fn read(fd: usize, buf: &mut [u8]) -> isize { sys_read(fd, buf) }
|
||||
pub fn write(fd: usize, buf: &[u8]) -> isize { sys_write(fd, buf) }
|
||||
pub fn exit(exit_code: i32) -> ! { sys_exit(exit_code); }
|
||||
pub fn yield_() -> isize { sys_yield() }
|
||||
pub fn get_time() -> isize { sys_get_time() }
|
||||
pub fn getpid() -> isize { sys_getpid() }
|
||||
pub fn fork() -> isize { sys_fork() }
|
||||
pub fn exec(path: &str, args: &[*const u8]) -> isize { sys_exec(path, args) }
|
||||
pub fn dup(fd: usize) -> isize {
|
||||
sys_dup(fd)
|
||||
}
|
||||
pub fn open(path: &str, flags: OpenFlags) -> isize {
|
||||
sys_open(path, flags.bits)
|
||||
}
|
||||
pub fn close(fd: usize) -> isize {
|
||||
sys_close(fd)
|
||||
}
|
||||
pub fn pipe(pipe_fd: &mut [usize]) -> isize {
|
||||
sys_pipe(pipe_fd)
|
||||
}
|
||||
pub fn read(fd: usize, buf: &mut [u8]) -> isize {
|
||||
sys_read(fd, buf)
|
||||
}
|
||||
pub fn write(fd: usize, buf: &[u8]) -> isize {
|
||||
sys_write(fd, buf)
|
||||
}
|
||||
pub fn exit(exit_code: i32) -> ! {
|
||||
sys_exit(exit_code);
|
||||
}
|
||||
pub fn yield_() -> isize {
|
||||
sys_yield()
|
||||
}
|
||||
pub fn get_time() -> isize {
|
||||
sys_get_time()
|
||||
}
|
||||
pub fn getpid() -> isize {
|
||||
sys_getpid()
|
||||
}
|
||||
pub fn fork() -> isize {
|
||||
sys_fork()
|
||||
}
|
||||
pub fn exec(path: &str, args: &[*const u8]) -> isize {
|
||||
sys_exec(path, args)
|
||||
}
|
||||
pub fn wait(exit_code: &mut i32) -> isize {
|
||||
loop {
|
||||
match sys_waitpid(-1, exit_code as *mut _) {
|
||||
-2 => { yield_(); }
|
||||
-2 => {
|
||||
yield_();
|
||||
}
|
||||
// -1 or a real pid
|
||||
exit_pid => return exit_pid,
|
||||
}
|
||||
|
@ -94,7 +120,9 @@ pub fn wait(exit_code: &mut i32) -> isize {
|
|||
pub fn waitpid(pid: usize, exit_code: &mut i32) -> isize {
|
||||
loop {
|
||||
match sys_waitpid(pid as isize, exit_code as *mut _) {
|
||||
-2 => { yield_(); }
|
||||
-2 => {
|
||||
yield_();
|
||||
}
|
||||
// -1 or a real pid
|
||||
exit_pid => return exit_pid,
|
||||
}
|
||||
|
@ -104,21 +132,35 @@ pub fn sleep(sleep_ms: usize) {
|
|||
sys_sleep(sleep_ms);
|
||||
}
|
||||
|
||||
pub fn thread_create(entry: usize, arg: usize) -> isize { sys_thread_create(entry, arg) }
|
||||
pub fn gettid() -> isize { sys_gettid() }
|
||||
pub fn thread_create(entry: usize, arg: usize) -> isize {
|
||||
sys_thread_create(entry, arg)
|
||||
}
|
||||
pub fn gettid() -> isize {
|
||||
sys_gettid()
|
||||
}
|
||||
pub fn waittid(tid: usize) -> isize {
|
||||
loop {
|
||||
match sys_waittid(tid) {
|
||||
-2 => { yield_(); }
|
||||
-2 => {
|
||||
yield_();
|
||||
}
|
||||
exit_code => return exit_code,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mutex_create() -> isize { sys_mutex_create(false) }
|
||||
pub fn mutex_blocking_create() -> isize { sys_mutex_create(true) }
|
||||
pub fn mutex_lock(mutex_id: usize) { sys_mutex_lock(mutex_id); }
|
||||
pub fn mutex_unlock(mutex_id: usize) { sys_mutex_unlock(mutex_id); }
|
||||
pub fn mutex_create() -> isize {
|
||||
sys_mutex_create(false)
|
||||
}
|
||||
pub fn mutex_blocking_create() -> isize {
|
||||
sys_mutex_create(true)
|
||||
}
|
||||
pub fn mutex_lock(mutex_id: usize) {
|
||||
sys_mutex_lock(mutex_id);
|
||||
}
|
||||
pub fn mutex_unlock(mutex_id: usize) {
|
||||
sys_mutex_unlock(mutex_id);
|
||||
}
|
||||
pub fn semaphore_create(res_count: usize) -> isize {
|
||||
sys_semaphore_create(res_count)
|
||||
}
|
||||
|
@ -128,4 +170,12 @@ pub fn semaphore_up(sem_id: usize) {
|
|||
pub fn semaphore_down(sem_id: usize) {
|
||||
sys_semaphore_down(sem_id);
|
||||
}
|
||||
|
||||
pub fn condvar_create() -> isize {
|
||||
sys_condvar_create(0)
|
||||
}
|
||||
pub fn condvar_signal(condvar_id: usize) {
|
||||
sys_condvar_signal(condvar_id);
|
||||
}
|
||||
pub fn condvar_wait(condvar_id: usize, mutex_id: usize) {
|
||||
sys_condvar_wait(condvar_id, mutex_id);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,9 @@ const SYSCALL_MUTEX_UNLOCK: usize = 1012;
|
|||
const SYSCALL_SEMAPHORE_CREATE: usize = 1020;
|
||||
const SYSCALL_SEMAPHORE_UP: usize = 1021;
|
||||
const SYSCALL_SEMAPHORE_DOWN: usize = 1022;
|
||||
const SYSCALL_CONDVAR_CREATE: usize = 1030;
|
||||
const SYSCALL_CONDVAR_SIGNAL: usize = 1031;
|
||||
const SYSCALL_CONDVAR_WAIT: usize = 1032;
|
||||
|
||||
fn syscall(id: usize, args: [usize; 3]) -> isize {
|
||||
let mut ret: isize;
|
||||
|
@ -128,3 +131,15 @@ pub fn sys_semaphore_up(sem_id: usize) -> isize {
|
|||
pub fn sys_semaphore_down(sem_id: usize) -> isize {
|
||||
syscall(SYSCALL_SEMAPHORE_DOWN, [sem_id, 0, 0])
|
||||
}
|
||||
|
||||
pub fn sys_condvar_create(_arg: usize) -> isize {
|
||||
syscall(SYSCALL_CONDVAR_CREATE, [_arg, 0, 0])
|
||||
}
|
||||
|
||||
pub fn sys_condvar_signal(condvar_id: usize) -> isize {
|
||||
syscall(SYSCALL_CONDVAR_SIGNAL, [condvar_id, 0, 0])
|
||||
}
|
||||
|
||||
pub fn sys_condvar_wait(condvar_id: usize, mutex_id:usize) -> isize {
|
||||
syscall(SYSCALL_CONDVAR_WAIT, [condvar_id, mutex_id, 0])
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue