mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-16 08:46:48 +00:00
add syscall sched_yield
This commit is contained in:
parent
9e8e9e62b2
commit
7ce1938a00
@ -15,4 +15,4 @@ pub const PAGE_SIZE_BITS: usize = 0xc;
|
||||
|
||||
pub const KVA_START: usize = (usize::MAX) << PAGE_SIZE_BITS;
|
||||
|
||||
pub const DEFAULT_LOG_LEVEL: LogLevel = LogLevel::Info;
|
||||
pub const DEFAULT_LOG_LEVEL: LogLevel = LogLevel::Trace;
|
||||
|
@ -35,6 +35,7 @@ use core::{mem, panic::PanicInfo};
|
||||
pub use self::error::Error;
|
||||
pub use self::prelude::Result;
|
||||
pub(crate) use self::sync::up::UPSafeCell;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use bootloader::{
|
||||
boot_info::{FrameBuffer, MemoryRegionKind},
|
||||
@ -45,6 +46,8 @@ pub use trap::{allocate_irq, IrqAllocateHandle, TrapFrame};
|
||||
use trap::{IrqCallbackHandle, IrqLine};
|
||||
pub use vm::Pod;
|
||||
use x86_64_util::enable_common_cpu_features;
|
||||
pub use util::AlignExt;
|
||||
|
||||
static mut IRQ_CALLBACK_LIST: Vec<IrqCallbackHandle> = Vec::new();
|
||||
|
||||
#[cfg(not(feature = "serial_print"))]
|
||||
|
@ -51,7 +51,9 @@ pub(crate) fn get_idle_task_cx_ptr() -> *mut TaskContext {
|
||||
|
||||
/// call this function to switch to other task by using GLOBAL_SCHEDULER
|
||||
pub fn schedule() {
|
||||
switch_to_task(fetch_task().expect("no more task found"));
|
||||
if let Some(task) = fetch_task() {
|
||||
switch_to_task(task);
|
||||
}
|
||||
}
|
||||
|
||||
/// call this function to switch to other task
|
||||
|
@ -128,7 +128,7 @@ impl Task {
|
||||
/// Note that this method cannot be simply named "yield" as the name is
|
||||
/// a Rust keyword.
|
||||
pub fn yield_now() {
|
||||
todo!()
|
||||
schedule();
|
||||
}
|
||||
|
||||
/// Spawns a task that executes a function.
|
||||
|
@ -2,6 +2,9 @@
|
||||
/// `u64`, and `usize`, to provide methods to make integers aligned to a
|
||||
/// power of two.
|
||||
pub trait AlignExt {
|
||||
/// returns whether the number is a power of two
|
||||
fn is_power_of_two(&self) -> bool;
|
||||
|
||||
/// Returns to the smallest number that is greater than or equal to
|
||||
/// `self` and is a multiple of the given power of two.
|
||||
///
|
||||
@ -41,6 +44,10 @@ macro_rules! impl_align_ext {
|
||||
($( $uint_type:ty ),+,) => {
|
||||
$(
|
||||
impl AlignExt for $uint_type {
|
||||
fn is_power_of_two(&self) -> bool {
|
||||
(*self != 0) && ((*self & (*self - 1)) == 0)
|
||||
}
|
||||
|
||||
fn align_up(self, align: Self) -> Self {
|
||||
assert!(align.is_power_of_two() && align >= 2);
|
||||
self.checked_add(align - 1).unwrap() & !(align - 1)
|
||||
@ -69,29 +76,29 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_align_up() {
|
||||
let input_ns = [0, 1, 2, 9, 15, 21, 32, 47, 50];
|
||||
let input_as = [2, 2, 2, 2, 4, 4, 8, 8, 8];
|
||||
let output_ns = [0, 2, 2, 10, 16, 24, 32, 48, 56];
|
||||
let input_ns = [0usize, 1, 2, 9, 15, 21, 32, 47, 50];
|
||||
let input_as = [2usize, 2, 2, 2, 4, 4, 8, 8, 8];
|
||||
let output_ns = [0usize, 2, 2, 10, 16, 24, 32, 48, 56];
|
||||
|
||||
for i in 0..input_ns.len() {
|
||||
let n = input_ns[i];
|
||||
let a = input_as[i];
|
||||
let n2 = output_ns[i];
|
||||
assert!(align_up(n, a) == n2);
|
||||
assert!(n.align_up(a) == n2);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_align_down() {
|
||||
let input_ns = [0, 1, 2, 9, 15, 21, 32, 47, 50];
|
||||
let input_as = [2, 2, 2, 2, 4, 4, 8, 8, 8];
|
||||
let output_ns = [0, 0, 2, 8, 12, 20, 32, 40, 48];
|
||||
let input_ns = [0usize, 1, 2, 9, 15, 21, 32, 47, 50];
|
||||
let input_as = [2usize, 2, 2, 2, 4, 4, 8, 8, 8];
|
||||
let output_ns = [0usize, 0, 2, 8, 12, 20, 32, 40, 48];
|
||||
|
||||
for i in 0..input_ns.len() {
|
||||
let n = input_ns[i];
|
||||
let a = input_as[i];
|
||||
let n2 = output_ns[i];
|
||||
assert!(align_down(n, a) == n2);
|
||||
assert!(n.align_down(a) == n2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,12 @@ pub fn init_process() {
|
||||
process.pid()
|
||||
);
|
||||
|
||||
let hello_c_content = read_hello_c_content();
|
||||
// glibc requires the filename starts as "/"
|
||||
let hello_c_filename = CString::new("/hello_c").unwrap();
|
||||
let process = Process::spawn_user_process(hello_c_filename, hello_c_content);
|
||||
info!("spawn hello_c process, pid = {}", process.pid());
|
||||
|
||||
let fork_content = read_fork_content();
|
||||
let fork_filename = CString::new("fork").unwrap();
|
||||
let process = Process::spawn_user_process(fork_filename, fork_content);
|
||||
@ -52,13 +58,11 @@ pub fn init_process() {
|
||||
process.pid()
|
||||
);
|
||||
|
||||
let hello_c_content = read_hello_c_content();
|
||||
// glibc requires the filename starts as "/"
|
||||
let hello_c_filename = CString::new("/hello_c").unwrap();
|
||||
let process = Process::spawn_user_process(hello_c_filename, hello_c_content);
|
||||
info!("spawn hello_c process, pid = {}", process.pid());
|
||||
|
||||
loop {}
|
||||
loop {
|
||||
// We don't have preemptive scheduler now.
|
||||
// The long running init process should yield its own execution to allow other tasks to go on.
|
||||
Process::yield_now();
|
||||
}
|
||||
}
|
||||
|
||||
/// first process never return
|
||||
|
@ -10,6 +10,7 @@ use kxos_frame::{
|
||||
config::PAGE_SIZE,
|
||||
debug,
|
||||
vm::{Vaddr, VmIo, VmPerm, VmSpace},
|
||||
AlignExt,
|
||||
};
|
||||
|
||||
use super::{
|
||||
@ -252,9 +253,8 @@ impl InitStack {
|
||||
}
|
||||
/// returns the u64 start address
|
||||
fn write_u64(&mut self, val: u64, vm_space: &VmSpace) -> u64 {
|
||||
let start_address = align_down(self.pos - 8, 8);
|
||||
let start_address = (self.pos - 8).align_down(8);
|
||||
self.pos = start_address;
|
||||
// debug!("start_address: 0x{:x}", start_address);
|
||||
vm_space
|
||||
.write_val(start_address, &val)
|
||||
.expect("Write u64 failed");
|
||||
@ -289,16 +289,6 @@ impl InitStack {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_power_of_two(val: usize) -> bool {
|
||||
(val != 0) && ((val & (val - 1)) == 0)
|
||||
}
|
||||
|
||||
/// align should be the pow of 2
|
||||
fn align_down(vaddr: usize, align: usize) -> usize {
|
||||
assert!(is_power_of_two(align));
|
||||
vaddr & !(align - 1)
|
||||
}
|
||||
|
||||
/// generate random [u8; 16].
|
||||
/// FIXME: generate really random value. Now only return array with fixed values.
|
||||
fn generate_random_for_aux_vec() -> [u8; 16] {
|
||||
|
@ -7,7 +7,6 @@ use alloc::{
|
||||
vec::Vec,
|
||||
};
|
||||
use kxos_frame::cpu::CpuContext;
|
||||
use kxos_frame::vm::{Vaddr, VmPerm};
|
||||
// use kxos_frame::{sync::SpinLock, task::Task, user::UserSpace};
|
||||
use kxos_frame::{
|
||||
debug,
|
||||
@ -20,7 +19,6 @@ use spin::Mutex;
|
||||
use crate::memory::mmap_area::MmapArea;
|
||||
use crate::memory::user_heap::UserHeap;
|
||||
use crate::process::task::create_forked_task;
|
||||
use crate::syscall::mmap::MMapFlags;
|
||||
|
||||
use self::status::ProcessStatus;
|
||||
use self::task::create_user_task_from_elf;
|
||||
@ -140,6 +138,7 @@ impl Process {
|
||||
})
|
||||
}
|
||||
|
||||
/// returns the pid
|
||||
pub fn pid(&self) -> usize {
|
||||
self.pid
|
||||
}
|
||||
@ -183,10 +182,16 @@ impl Process {
|
||||
self.task.send_to_scheduler();
|
||||
}
|
||||
|
||||
/// yield the current process to allow other processes to run
|
||||
pub fn yield_now() {
|
||||
Task::yield_now();
|
||||
}
|
||||
|
||||
fn user_space(&self) -> Option<&Arc<UserSpace>> {
|
||||
self.user_space.as_ref()
|
||||
}
|
||||
|
||||
/// returns the vm space if the process does have, otherwise None
|
||||
pub fn vm_space(&self) -> Option<&VmSpace> {
|
||||
match self.user_space {
|
||||
None => None,
|
||||
@ -194,6 +199,7 @@ impl Process {
|
||||
}
|
||||
}
|
||||
|
||||
/// returns the user heap if the process does have, otherwise None
|
||||
pub fn user_heap(&self) -> Option<&UserHeap> {
|
||||
match self.user_vm {
|
||||
None => None,
|
||||
@ -201,6 +207,7 @@ impl Process {
|
||||
}
|
||||
}
|
||||
|
||||
/// returns the mmap area if the process does have, otherwise None
|
||||
pub fn mmap_area(&self) -> Option<&MmapArea> {
|
||||
match self.user_vm {
|
||||
None => None,
|
||||
@ -208,10 +215,13 @@ impl Process {
|
||||
}
|
||||
}
|
||||
|
||||
/// whether the process has child process
|
||||
pub fn has_child(&self) -> bool {
|
||||
self.children.lock().len() != 0
|
||||
}
|
||||
|
||||
/// get the first(and only) child process
|
||||
/// FIXME: deal with multiple children processes
|
||||
pub fn get_child_process(&self) -> Arc<Process> {
|
||||
let children_lock = self.children.lock();
|
||||
let child_len = children_lock.len();
|
||||
@ -223,6 +233,7 @@ impl Process {
|
||||
.clone()
|
||||
}
|
||||
|
||||
/// Fork a child process
|
||||
/// WorkAround: This function only create a new process, but did not schedule the process to run
|
||||
pub fn fork(parent_context: CpuContext) -> Arc<Process> {
|
||||
let child_pid = new_pid();
|
||||
@ -271,29 +282,9 @@ impl Process {
|
||||
child
|
||||
}
|
||||
|
||||
pub fn mmap(&self, len: usize, vm_perm: VmPerm, flags: MMapFlags, offset: usize) -> Vaddr {
|
||||
let mmap_area = self
|
||||
.mmap_area()
|
||||
.expect("mmap should work on process with mmap area");
|
||||
let user_space = self
|
||||
.user_space()
|
||||
.expect("mmap should work on process with user space");
|
||||
let vm_space = user_space.vm_space();
|
||||
mmap_area.mmap(len, offset, vm_perm, flags, vm_space)
|
||||
}
|
||||
|
||||
pub fn filename(&self) -> Option<&CString> {
|
||||
self.filename.as_ref()
|
||||
}
|
||||
|
||||
// pub fn copy_bytes_from_user(&self, vaddr: Vaddr, buf: &mut [u8]) {
|
||||
// self.user_space()
|
||||
// .unwrap()
|
||||
// .vm_space()
|
||||
// .read_bytes(vaddr, buf)
|
||||
// .unwrap();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
/// Get the init process
|
||||
|
@ -32,6 +32,7 @@ mod gettid;
|
||||
pub mod mmap;
|
||||
mod mprotect;
|
||||
mod readlink;
|
||||
mod sched_yield;
|
||||
mod tgkill;
|
||||
mod uname;
|
||||
mod write;
|
||||
@ -45,6 +46,7 @@ const SYS_BRK: u64 = 12;
|
||||
const SYS_RT_SIGACTION: u64 = 13;
|
||||
const SYS_RT_SIGPROCMASK: u64 = 14;
|
||||
const SYS_WRITEV: u64 = 20;
|
||||
const SYS_SCHED_YIELD: u64 = 24;
|
||||
const SYS_GETPID: u64 = 39;
|
||||
const SYS_FORK: u64 = 57;
|
||||
const SYS_EXIT: u64 = 60;
|
||||
|
11
src/kxos-std/src/syscall/sched_yield.rs
Normal file
11
src/kxos-std/src/syscall/sched_yield.rs
Normal file
@ -0,0 +1,11 @@
|
||||
use kxos_frame::debug;
|
||||
|
||||
use crate::{process::Process, syscall::SYS_SCHED_YIELD};
|
||||
|
||||
use super::SyscallResult;
|
||||
|
||||
pub fn sys_sched_yield() -> SyscallResult {
|
||||
debug!("[syscall][id={}][SYS_SCHED_YIELD]", SYS_SCHED_YIELD);
|
||||
Process::yield_now();
|
||||
SyscallResult::Return(0)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user