Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions os/src/mm/memory_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ impl MemorySet {
areas: Vec::new(),
}
}
/// Check if memory range include allocated memory
pub fn include_allocated(&self, start_address: VirtAddr, end_address: VirtAddr) -> bool {
self.areas.iter().any(|area| {
area.vpn_range.get_end() > start_address.floor()
&& area.vpn_range.get_start() < end_address.ceil()
})
}
/// Get the page table token
pub fn token(&self) -> usize {
self.page_table.token()
Expand All @@ -63,6 +70,20 @@ impl MemorySet {
None,
);
}
/// free a framed area
pub fn free_framed_area(&mut self, start_address: VirtAddr, end_address: VirtAddr) {
let virtual_page_start = start_address.floor();
let virtual_page_end = end_address.ceil();
let index = self.areas.iter_mut().position(|map| {
map.vpn_range.get_start() == virtual_page_start
&& map.vpn_range.get_end() == virtual_page_end
});

if let Some(index) = index {
self.areas[index].unmap(&mut self.page_table);
self.areas.remove(index);
}
}
fn push(&mut self, mut map_area: MapArea, data: Option<&[u8]>) {
map_area.map(&mut self.page_table);
if let Some(data) = data {
Expand Down
2 changes: 1 addition & 1 deletion os/src/mm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use address::{StepByOne, VPNRange};
pub use frame_allocator::{frame_alloc, FrameTracker};
pub use memory_set::remap_test;
pub use memory_set::{kernel_stack_position, MapPermission, MemorySet, KERNEL_SPACE};
pub use page_table::{translated_byte_buffer, PageTableEntry};
pub use page_table::{get_physocal_address, translated_byte_buffer, PageTableEntry};
use page_table::{PTEFlags, PageTable};

/// initiate heap allocator, frame allocator and kernel space
Expand Down
20 changes: 20 additions & 0 deletions os/src/mm/page_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,23 @@ pub fn translated_byte_buffer(token: usize, ptr: *const u8, len: usize) -> Vec<&
}
v
}

/// get the physical address from the virtual address
pub fn get_physocal_address(token: usize, ptr: usize) -> usize {
let page_table = PageTable::from_token(token);

// get the virtual address and the offset
let virtual_address = VirtAddr::from(ptr);
let offset_address = virtual_address.page_offset();

// get the physical address
let virt_page_num = virtual_address.floor();
let physical_page_num = match page_table.translate(virt_page_num) {
Some(virt_page_num) => virt_page_num.ppn(),
None => panic!("Invalid address: 0x{:x}", ptr),
};

let physical_address = physical_page_num.0 << 12 | offset_address;

physical_address
}
8 changes: 6 additions & 2 deletions os/src/syscall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,17 @@ const SYSCALL_MMAP: usize = 222;
/// taskinfo syscall
const SYSCALL_TASK_INFO: usize = 410;

mod fs;
mod process;
pub(crate) mod fs;
pub(crate) mod process;

use fs::*;
use process::*;

use crate::task::update_task_info;

/// handle syscall exception with `syscall_id` and other arguments
pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
update_task_info(syscall_id);
match syscall_id {
SYSCALL_WRITE => sys_write(args[0], args[1] as *const u8, args[2]),
SYSCALL_EXIT => sys_exit(args[0] as i32),
Expand Down
50 changes: 38 additions & 12 deletions os/src/syscall/process.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
//! Process management syscalls
use crate::{
config::MAX_SYSCALL_NUM,
mm::get_physocal_address,
task::{
change_program_brk, exit_current_and_run_next, suspend_current_and_run_next, TaskStatus,
change_program_brk, current_task_info, current_task_mmap, current_task_munmap,
current_user_token, exit_current_and_run_next, suspend_current_and_run_next, TaskStatus,
},
timer::get_time_us,
};

#[repr(C)]
Expand All @@ -17,11 +20,11 @@ pub struct TimeVal {
#[allow(dead_code)]
pub struct TaskInfo {
/// Task status in it's life cycle
status: TaskStatus,
pub(crate) status: TaskStatus,
/// The numbers of syscall called by task
syscall_times: [u32; MAX_SYSCALL_NUM],
pub(crate) syscall_times: [u32; MAX_SYSCALL_NUM],
/// Total running time of task
time: usize,
pub(crate) time: usize,
}

/// task exits and submit an exit code
Expand All @@ -41,29 +44,52 @@ pub fn sys_yield() -> isize {
/// YOUR JOB: get time with second and microsecond
/// HINT: You might reimplement it with virtual memory management.
/// HINT: What if [`TimeVal`] is splitted by two pages ?
pub fn sys_get_time(_ts: *mut TimeVal, _tz: usize) -> isize {
pub fn sys_get_time(ts: *mut TimeVal, _tz: usize) -> isize {
trace!("kernel: sys_get_time");
-1

let token = current_user_token();
let physical_address = get_physocal_address(token, ts as usize);
let time = get_time_us();

// should be write to physical address
unsafe {
*(physical_address as *mut TimeVal) = TimeVal {
sec: time / 1_000_000,
usec: time % 1_000_000,
};
}

0
}

/// YOUR JOB: Finish sys_task_info to pass testcases
/// HINT: You might reimplement it with virtual memory management.
/// HINT: What if [`TaskInfo`] is splitted by two pages ?
pub fn sys_task_info(_ti: *mut TaskInfo) -> isize {
pub fn sys_task_info(ti: *mut TaskInfo) -> isize {
trace!("kernel: sys_task_info NOT IMPLEMENTED YET!");
-1

let token = current_user_token();
let physical_address = get_physocal_address(token, ti as usize);
let ptr = physical_address as *mut TaskInfo;
unsafe {
*ptr = current_task_info();
}

0
}

// YOUR JOB: Implement mmap.
pub fn sys_mmap(_start: usize, _len: usize, _port: usize) -> isize {
pub fn sys_mmap(start: usize, len: usize, port: usize) -> isize {
trace!("kernel: sys_mmap NOT IMPLEMENTED YET!");
-1

current_task_mmap(start, len, port)
}

// YOUR JOB: Implement munmap.
pub fn sys_munmap(_start: usize, _len: usize) -> isize {
pub fn sys_munmap(start: usize, len: usize) -> isize {
trace!("kernel: sys_munmap NOT IMPLEMENTED YET!");
-1

current_task_munmap(start, len)
}
/// change data segment size
pub fn sys_sbrk(size: i32) -> isize {
Expand Down
111 changes: 111 additions & 0 deletions os/src/task/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@ mod switch;
#[allow(clippy::module_inception)]
mod task;

use crate::config::PAGE_SIZE;
use crate::loader::{get_app_data, get_num_app};
use crate::mm::{MapPermission, VirtAddr};
use crate::sync::UPSafeCell;
use crate::syscall::process::TaskInfo;
use crate::timer::get_time_ms;
use crate::trap::TrapContext;
use alloc::vec::Vec;
use lazy_static::*;
Expand Down Expand Up @@ -114,6 +118,75 @@ impl TaskManager {
.find(|id| inner.tasks[*id].task_status == TaskStatus::Ready)
}

/// add syscall trace
fn update_task_info(&self, syscall_id: usize) {
let mut inner = self.inner.exclusive_access();
let current_id = inner.current_task;
let current_task = &mut inner.tasks[current_id];
current_task.task_lastest_syscall_time = get_time_ms();
current_task.task_syscall_trace[syscall_id] += 1;
}

fn get_memory(&self, start: usize, len: usize, port: usize) -> isize {
// check
if start % PAGE_SIZE != 0 {
return -1;
}

if port & !0x7 != 0 || port & 0x7 == 0 {
return -1;
}

let start_address = VirtAddr::from(start);
let end_address = VirtAddr::from(start + len);

let mut inner = self.inner.exclusive_access();
let current_id = inner.current_task;
let current_task = &mut inner.tasks[current_id];

if current_task
.memory_set
.include_allocated(start_address, end_address)
{
return -1;
}

let permissions = MapPermission::from_bits((port as u8) << 1).unwrap() | MapPermission::U;

current_task
.memory_set
.insert_framed_area(start_address, end_address, permissions);

0
}

fn free_memory(&self, start: usize, len: usize) -> isize {
if start % PAGE_SIZE != 0 {
return -1;
}

let start_address = VirtAddr::from(start);
let end_address = VirtAddr::from(start + len);

if !start_address.aligned() {
return -1;
}

if !end_address.aligned() {
return -1;
}

let mut inner = self.inner.exclusive_access();
let current_id = inner.current_task;
let current_task = &mut inner.tasks[current_id];

current_task
.memory_set
.free_framed_area(start_address, end_address);

0
}

/// Get the current 'Running' task's token.
fn get_current_token(&self) -> usize {
let inner = self.inner.exclusive_access();
Expand All @@ -126,6 +199,24 @@ impl TaskManager {
inner.tasks[inner.current_task].get_trap_cx()
}

/// Get task info
fn get_current_task_info(&self) -> TaskInfo {
let inner = self.inner.exclusive_access();
// current task id
let current_id = inner.current_task;
let current_task = &inner.tasks[current_id];

TaskInfo {
status: current_task.task_status,
syscall_times: current_task.task_syscall_trace,
time: {
let start = current_task.task_start_time;
let end = current_task.task_lastest_syscall_time;
end - start
},
}
}

/// Change the current 'Running' task's program break
pub fn change_current_program_brk(&self, size: i32) -> Option<usize> {
let mut inner = self.inner.exclusive_access();
Expand Down Expand Up @@ -188,6 +279,11 @@ pub fn exit_current_and_run_next() {
run_next_task();
}

/// Update task info for syscall
pub fn update_task_info(syscall_id: usize) {
TASK_MANAGER.update_task_info(syscall_id)
}

/// Get the current 'Running' task's token.
pub fn current_user_token() -> usize {
TASK_MANAGER.get_current_token()
Expand All @@ -198,6 +294,21 @@ pub fn current_trap_cx() -> &'static mut TrapContext {
TASK_MANAGER.get_current_trap_cx()
}

/// Get current task control block
pub fn current_task_info() -> TaskInfo {
TASK_MANAGER.get_current_task_info()
}

/// Alloc memory
pub fn current_task_mmap(start: usize, len: usize, port: usize) -> isize {
TASK_MANAGER.get_memory(start, len, port)
}

/// Free up memory
pub fn current_task_munmap(start: usize, len: usize) -> isize {
TASK_MANAGER.free_memory(start, len)
}

/// Change the current 'Running' task's program break
pub fn change_program_brk(size: i32) -> Option<usize> {
TASK_MANAGER.change_current_program_brk(size)
Expand Down
15 changes: 14 additions & 1 deletion os/src/task/task.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
//! Types related to task management
use super::TaskContext;
use crate::config::TRAP_CONTEXT_BASE;
use crate::config::{MAX_SYSCALL_NUM, TRAP_CONTEXT_BASE};
use crate::mm::{
kernel_stack_position, MapPermission, MemorySet, PhysPageNum, VirtAddr, KERNEL_SPACE,
};
use crate::timer::get_time_ms;
use crate::trap::{trap_handler, TrapContext};

/// The task control block (TCB) of a task.
Expand All @@ -28,6 +29,15 @@ pub struct TaskControlBlock {

/// Program break
pub program_brk: usize,

/// The start time of task
pub task_start_time: usize,

/// The end time of task syscall
pub task_lastest_syscall_time: usize,

/// The numbers of syscall called by task
pub task_syscall_trace: [u32; MAX_SYSCALL_NUM],
}

impl TaskControlBlock {
Expand Down Expand Up @@ -63,6 +73,9 @@ impl TaskControlBlock {
base_size: user_sp,
heap_bottom: user_sp,
program_brk: user_sp,
task_start_time: get_time_ms(),
task_lastest_syscall_time: get_time_ms(),
task_syscall_trace: [0; MAX_SYSCALL_NUM],
};
// prepare TrapContext in user space
let trap_cx = task_control_block.get_trap_cx();
Expand Down
Loading