riscv: copy-thread (#696)

This commit is contained in:
LoGin 2024-04-05 16:37:08 +08:00 committed by GitHub
parent dfe53cf087
commit e8eab1ac82
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 140 additions and 14 deletions

View File

@ -62,7 +62,7 @@ x86_64 = "=0.14.10"
# target为riscv64时使用下面的依赖
[target.'cfg(target_arch = "riscv64")'.dependencies]
riscv = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/riscv.git", revision = "01fc40d", features = [ "s-mode" ] }
riscv = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/riscv.git", revision = "bf771288c3", features = [ "s-mode" ] }
sbi-rt = { version = "=0.0.3", features = ["legacy"] }

View File

@ -242,7 +242,7 @@ unsafe extern "C" fn _save_context() -> ! {
#[naked]
#[no_mangle]
unsafe extern "C" fn ret_from_exception() -> ! {
pub unsafe extern "C" fn ret_from_exception() -> ! {
asm!(
concat!("
ld s0, {off_status}(sp)

View File

@ -111,4 +111,49 @@ impl TrapFrame {
pub fn is_from_user(&self) -> bool {
self.status.spp() == riscv::register::sstatus::SPP::User
}
pub fn new() -> Self {
Self {
epc: 0,
ra: 0,
sp: 0,
gp: 0,
tp: 0,
t0: 0,
t1: 0,
t2: 0,
s0: 0,
s1: 0,
a0: 0,
a1: 0,
a2: 0,
a3: 0,
a4: 0,
a5: 0,
a6: 0,
a7: 0,
s2: 0,
s3: 0,
s4: 0,
s5: 0,
s6: 0,
s7: 0,
s8: 0,
s9: 0,
s10: 0,
s11: 0,
t3: 0,
t4: 0,
t5: 0,
t6: 0,
status: unsafe { core::mem::zeroed() },
badaddr: 0,
cause: unsafe { core::mem::zeroed() },
origin_a0: 0,
}
}
pub fn set_return_value(&mut self, value: usize) {
self.a0 = value;
}
}

View File

@ -1,10 +1,14 @@
use alloc::sync::Arc;
use riscv::register::sstatus::SPP;
use system_error::SystemError;
use crate::process::{
fork::CloneFlags,
kthread::{KernelThreadCreateInfo, KernelThreadMechanism},
Pid,
use crate::{
arch::interrupt::TrapFrame,
process::{
fork::CloneFlags,
kthread::{KernelThreadCreateInfo, KernelThreadMechanism},
Pid, ProcessManager,
},
};
impl KernelThreadMechanism {
@ -13,11 +17,35 @@ impl KernelThreadMechanism {
/// ## 返回值
///
/// 返回创建的内核线程的pid
#[inline(never)]
pub fn __inner_create(
info: &Arc<KernelThreadCreateInfo>,
clone_flags: CloneFlags,
) -> Result<Pid, SystemError> {
unimplemented!("KernelThreadMechanism::__inner_create")
// WARNING: If create failed, we must drop the info manually or it will cause memory leak. (refcount will not decrease when create failed)
let create_info: *const KernelThreadCreateInfo =
KernelThreadCreateInfo::generate_unsafe_arc_ptr(info.clone());
let mut frame = TrapFrame::new();
frame.a0 = create_info as usize;
// 使能中断
frame.status.update_sie(true);
frame.status.update_spp(SPP::Supervisor);
frame.ra = kernel_thread_bootstrap_stage1 as usize;
// fork失败的话子线程不会执行。否则将导致内存安全问题。
let pid = ProcessManager::fork(&frame, clone_flags).map_err(|e| {
unsafe { KernelThreadCreateInfo::parse_unsafe_arc_ptr(create_info) };
e
})?;
ProcessManager::find(pid)
.unwrap()
.set_name(info.name().clone());
return Ok(pid);
}
}

View File

@ -13,16 +13,20 @@ use kdepends::memoffset::offset_of;
use system_error::SystemError;
use crate::{
arch::CurrentIrqArch,
arch::{
interrupt::entry::ret_from_exception, process::kthread::kernel_thread_bootstrap_stage1,
CurrentIrqArch,
},
exception::InterruptArch,
kerror,
libs::spinlock::SpinLockGuard,
mm::VirtAddr,
process::{
fork::KernelCloneArgs, KernelStack, ProcessControlBlock, ProcessManager,
PROCESS_SWITCH_RESULT,
fork::{CloneFlags, KernelCloneArgs},
KernelStack, ProcessControlBlock, ProcessFlags, ProcessManager, PROCESS_SWITCH_RESULT,
},
smp::cpu::ProcessorId,
syscall::Syscall,
};
use super::{
@ -65,7 +69,52 @@ impl ProcessManager {
clone_args: KernelCloneArgs,
current_trapframe: &TrapFrame,
) -> Result<(), SystemError> {
unimplemented!("ProcessManager::copy_thread")
let clone_flags = clone_args.flags;
let mut child_trapframe = *current_trapframe;
// 子进程的返回值为0
child_trapframe.set_return_value(0);
// 设置子进程的栈基址(开始执行中断返回流程时的栈基址)
let mut new_arch_guard = unsafe { new_pcb.arch_info() };
let kernel_stack_guard = new_pcb.kernel_stack();
let trap_frame_vaddr: VirtAddr =
kernel_stack_guard.stack_max_address() - core::mem::size_of::<TrapFrame>();
new_arch_guard.set_stack(trap_frame_vaddr);
// 拷贝栈帧
unsafe {
let usp = clone_args.stack;
if usp != 0 {
child_trapframe.sp = usp;
}
let trap_frame_ptr = trap_frame_vaddr.data() as *mut TrapFrame;
*trap_frame_ptr = child_trapframe;
}
// copy arch info
let current_arch_guard = current_pcb.arch_info_irqsave();
// 拷贝浮点寄存器的状态
new_arch_guard.fp_state = current_arch_guard.fp_state;
drop(current_arch_guard);
// 设置返回地址(子进程开始执行的指令地址)
if new_pcb.flags().contains(ProcessFlags::KTHREAD) {
let kthread_bootstrap_stage1_func_addr = kernel_thread_bootstrap_stage1 as usize;
new_arch_guard.ra = kthread_bootstrap_stage1_func_addr;
} else {
new_arch_guard.ra = ret_from_exception as usize;
}
// 设置tls
if clone_flags.contains(CloneFlags::CLONE_SETTLS) {
drop(new_arch_guard);
todo!("set tls");
}
return Ok(());
}
/// 切换进程
@ -221,7 +270,7 @@ impl ProcessControlBlock {
}
/// PCB中与架构相关的信息
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]
#[allow(dead_code)]
#[repr(C)]
pub struct ArchPCBInfo {
@ -277,12 +326,16 @@ impl ArchPCBInfo {
}
// ### 从另一个ArchPCBInfo处clone,但是保留部分字段不变
pub fn clone_from(&mut self, from: &Self) {
unimplemented!("ArchPCBInfo::clone_from")
*self = from.clone();
}
pub fn set_stack(&mut self, stack: VirtAddr) {
self.ksp = stack.data();
}
}
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]
struct FpDExtState {
f: [u64; 32],
fcsr: u32,