Skip to content

Commit

Permalink
添加thread和futex机制 (#411)
Browse files Browse the repository at this point in the history
* 初步实现clone系统调用

* 实现了线程,初步实现futex机制,添加了几个小的系统调用

* 更改pcb引用计数问题

* 解决死锁bug

---------

Co-authored-by: LoGin <[email protected]>
  • Loading branch information
GnoCiYeH and fslongjin authored Nov 1, 2023
1 parent 665f4a7 commit 971462b
Show file tree
Hide file tree
Showing 25 changed files with 1,641 additions and 147 deletions.
63 changes: 44 additions & 19 deletions kernel/src/arch/x86_64/process/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ use core::{
sync::atomic::{compiler_fence, Ordering},
};

use alloc::{string::String, sync::Arc, vec::Vec};
use alloc::{
string::String,
sync::{Arc, Weak},
vec::Vec,
};

use memoffset::offset_of;
use x86::{controlregs::Cr4, segmentation::SegmentSelector};
Expand All @@ -20,14 +24,16 @@ use crate::{
VirtAddr,
},
process::{
fork::CloneFlags, KernelStack, ProcessControlBlock, ProcessFlags, ProcessManager,
SwitchResult, SWITCH_RESULT,
fork::{CloneFlags, KernelCloneArgs},
KernelStack, ProcessControlBlock, ProcessFlags, ProcessManager, SwitchResult,
SWITCH_RESULT,
},
syscall::{Syscall, SystemError},
};

use self::{
kthread::kernel_thread_bootstrap_stage1,
syscall::ARCH_SET_FS,
table::{switch_fs_and_gs, KERNEL_DS, USER_DS},
};

Expand All @@ -38,6 +44,9 @@ pub mod kthread;
pub mod syscall;
pub mod table;

pub const IA32_FS_BASE: u32 = 0xC000_0100;
pub const IA32_GS_BASE: u32 = 0xC000_0101;

extern "C" {
/// 从中断返回
fn ret_from_intr();
Expand Down Expand Up @@ -175,27 +184,31 @@ impl ArchPCBInfo {
if x86::controlregs::cr4().contains(Cr4::CR4_ENABLE_FSGSBASE) {
self.fsbase = x86::current::segmentation::rdfsbase() as usize;
} else {
self.fsbase = 0;
self.fsbase = x86::msr::rdmsr(IA32_FS_BASE) as usize;
}
}

pub unsafe fn save_gsbase(&mut self) {
if x86::controlregs::cr4().contains(Cr4::CR4_ENABLE_FSGSBASE) {
self.gsbase = x86::current::segmentation::rdgsbase() as usize;
} else {
self.gsbase = 0;
self.gsbase = x86::msr::rdmsr(IA32_GS_BASE) as usize;
}
}

pub unsafe fn restore_fsbase(&mut self) {
if x86::controlregs::cr4().contains(Cr4::CR4_ENABLE_FSGSBASE) {
x86::current::segmentation::wrfsbase(self.fsbase as u64);
} else {
x86::msr::wrmsr(IA32_FS_BASE, self.fsbase as u64);
}
}

pub unsafe fn restore_gsbase(&mut self) {
if x86::controlregs::cr4().contains(Cr4::CR4_ENABLE_FSGSBASE) {
x86::current::segmentation::wrgsbase(self.gsbase as u64);
} else {
x86::msr::wrmsr(IA32_GS_BASE, self.gsbase as u64);
}
}

Expand Down Expand Up @@ -228,11 +241,11 @@ impl ProcessControlBlock {
panic!("current_pcb is null");
}
unsafe {
// 为了防止内核栈的pcb指针被释放,这里需要将其包装一下,使得Arc的drop不会被调用
let arc_wrapper: ManuallyDrop<Arc<ProcessControlBlock>> =
ManuallyDrop::new(Arc::from_raw(*p));
// 为了防止内核栈的pcb weak 指针被释放,这里需要将其包装一下
let weak_wrapper: ManuallyDrop<Weak<ProcessControlBlock>> =
ManuallyDrop::new(Weak::from_raw(*p));

let new_arc: Arc<ProcessControlBlock> = Arc::clone(&arc_wrapper);
let new_arc: Arc<ProcessControlBlock> = weak_wrapper.upgrade().unwrap();
return new_arc;
}
}
Expand All @@ -255,11 +268,12 @@ impl ProcessManager {
///
/// 由于这个过程与具体的架构相关,所以放在这里
pub fn copy_thread(
_clone_flags: &CloneFlags,
current_pcb: &Arc<ProcessControlBlock>,
new_pcb: &Arc<ProcessControlBlock>,
clone_args: KernelCloneArgs,
current_trapframe: &TrapFrame,
) -> Result<(), SystemError> {
let clone_flags = clone_args.flags;
let mut child_trapframe = current_trapframe.clone();

// 子进程的返回值为0
Expand All @@ -278,6 +292,10 @@ impl ProcessManager {

// 拷贝栈帧
unsafe {
let usp = clone_args.stack;
if usp != 0 {
child_trapframe.rsp = usp as u64;
}
let trap_frame_ptr = trap_frame_vaddr.data() as *mut TrapFrame;
*trap_frame_ptr = child_trapframe;
}
Expand All @@ -296,15 +314,19 @@ impl ProcessManager {
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.rip = kthread_bootstrap_stage1_func_addr;
} else {
new_arch_guard.rip = ret_from_intr as usize;
}

// 设置tls
if clone_flags.contains(CloneFlags::CLONE_SETTLS) {
drop(new_arch_guard);
Syscall::do_arch_prctl_64(new_pcb, ARCH_SET_FS, clone_args.tls, true)?;
}

return Ok(());
}

Expand Down Expand Up @@ -335,28 +357,28 @@ impl ProcessManager {
compiler_fence(Ordering::SeqCst);

next_addr_space.read().user_mapper.utable.make_current();
drop(next_addr_space);
compiler_fence(Ordering::SeqCst);
// 切换内核栈

// 获取arch info的锁,并强制泄露其守卫(切换上下文后,在switch_finish_hook中会释放锁)
let next_arch = SpinLockGuard::leak(next.arch_info());
let prev_arch = SpinLockGuard::leak(prev.arch_info());
let next_arch = SpinLockGuard::leak(next.arch_info()) as *mut ArchPCBInfo;
let prev_arch = SpinLockGuard::leak(prev.arch_info()) as *mut ArchPCBInfo;

prev_arch.rip = switch_back as usize;
(*prev_arch).rip = switch_back as usize;

// 恢复当前的 preempt count*2
ProcessManager::current_pcb().preempt_enable();
ProcessManager::current_pcb().preempt_enable();
SWITCH_RESULT.as_mut().unwrap().get_mut().prev_pcb = Some(prev.clone());
SWITCH_RESULT.as_mut().unwrap().get_mut().next_pcb = Some(next.clone());

// 切换tss
TSSManager::current_tss().set_rsp(
x86::Ring::Ring0,
next.kernel_stack().stack_max_address().data() as u64,
);
SWITCH_RESULT.as_mut().unwrap().get_mut().prev_pcb = Some(prev);
SWITCH_RESULT.as_mut().unwrap().get_mut().next_pcb = Some(next);
// kdebug!("switch tss ok");

compiler_fence(Ordering::SeqCst);
// 正式切换上下文
switch_to_inner(prev_arch, next_arch);
Expand All @@ -365,7 +387,7 @@ impl ProcessManager {

/// 保存上下文,然后切换进程,接着jmp到`switch_finish_hook`钩子函数
#[naked]
unsafe extern "sysv64" fn switch_to_inner(prev: &mut ArchPCBInfo, next: &mut ArchPCBInfo) {
unsafe extern "sysv64" fn switch_to_inner(prev: *mut ArchPCBInfo, next: *mut ArchPCBInfo) {
asm!(
// As a quick reminder for those who are unfamiliar with the System V ABI (extern "C"):
//
Expand Down Expand Up @@ -394,6 +416,9 @@ unsafe extern "sysv64" fn switch_to_inner(prev: &mut ArchPCBInfo, next: &mut Arc
mov [rdi + {off_fs}], fs
mov [rdi + {off_gs}], gs
// mov fs, [rsi + {off_fs}]
// mov gs, [rsi + {off_gs}]
push rbp
push rax
Expand Down
74 changes: 71 additions & 3 deletions kernel/src/arch/x86_64/process/syscall.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use alloc::{string::String, vec::Vec};
use alloc::{string::String, sync::Arc, vec::Vec};

use crate::{
arch::{
Expand All @@ -10,9 +10,9 @@ use crate::{
mm::ucontext::AddressSpace,
process::{
exec::{load_binary_file, ExecParam, ExecParamFlags},
ProcessManager,
ProcessControlBlock, ProcessManager,
},
syscall::{Syscall, SystemError},
syscall::{user_access::UserBufferWriter, Syscall, SystemError},
};

impl Syscall {
Expand Down Expand Up @@ -105,6 +105,8 @@ impl Syscall {
regs.rflags = 0x200;
regs.rax = 1;

drop(param);

// kdebug!("regs: {:?}\n", regs);

// kdebug!(
Expand All @@ -114,4 +116,70 @@ impl Syscall {

return Ok(());
}

/// ## 用于控制和查询与体系结构相关的进程特定选项
pub fn arch_prctl(option: usize, arg2: usize) -> Result<usize, SystemError> {
let pcb = ProcessManager::current_pcb();
if let Err(SystemError::EINVAL) = Self::do_arch_prctl_64(&pcb, option, arg2, true) {
Self::do_arch_prctl_common(option, arg2)?;
}
Ok(0)
}

/// ## 64位下控制fs/gs base寄存器的方法
pub fn do_arch_prctl_64(
pcb: &Arc<ProcessControlBlock>,
option: usize,
arg2: usize,
from_user: bool,
) -> Result<usize, SystemError> {
let mut arch_info = pcb.arch_info_irqsave();
match option {
ARCH_GET_FS => {
unsafe { arch_info.save_fsbase() };
let mut writer = UserBufferWriter::new(
arg2 as *mut usize,
core::mem::size_of::<usize>(),
from_user,
)?;
writer.copy_one_to_user(&arch_info.fsbase, 0)?;
}
ARCH_GET_GS => {
unsafe { arch_info.save_gsbase() };
let mut writer = UserBufferWriter::new(
arg2 as *mut usize,
core::mem::size_of::<usize>(),
from_user,
)?;
writer.copy_one_to_user(&arch_info.gsbase, 0)?;
}
ARCH_SET_FS => {
arch_info.fsbase = arg2;
// 如果是当前进程则直接写入寄存器
if pcb.pid() == ProcessManager::current_pcb().pid() {
unsafe { arch_info.restore_fsbase() }
}
}
ARCH_SET_GS => {
arch_info.gsbase = arg2;
if pcb.pid() == ProcessManager::current_pcb().pid() {
unsafe { arch_info.restore_gsbase() }
}
}
_ => {
return Err(SystemError::EINVAL);
}
}
Ok(0)
}

#[allow(dead_code)]
pub fn do_arch_prctl_common(_option: usize, _arg2: usize) -> Result<usize, SystemError> {
todo!("do_arch_prctl_common not unimplemented");
}
}

pub const ARCH_SET_GS: usize = 0x1001;
pub const ARCH_SET_FS: usize = 0x1002;
pub const ARCH_GET_FS: usize = 0x1003;
pub const ARCH_GET_GS: usize = 0x1004;
33 changes: 33 additions & 0 deletions kernel/src/arch/x86_64/rand.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,38 @@
use core::arch::x86_64::_rdtsc;

use alloc::vec::Vec;

use crate::{
libs::rand::GRandFlags,
syscall::{user_access::UserBufferWriter, Syscall, SystemError},
};

pub fn rand() -> usize {
return unsafe { (_rdtsc() * _rdtsc() + 998244353_u64 * _rdtsc()) as usize };
}

impl Syscall {
/// ## 将随机字节填入buf
///
/// ### 该系统调用与linux不一致,因为目前没有其他随机源
pub fn get_random(buf: *mut u8, len: usize, flags: GRandFlags) -> Result<usize, SystemError> {
if flags.bits() == (GRandFlags::GRND_INSECURE.bits() | GRandFlags::GRND_RANDOM.bits()) {
return Err(SystemError::EINVAL);
}

let mut writer = UserBufferWriter::new(buf, len, true)?;

let mut ret = Vec::new();
let mut count = 0;
while count < len {
let rand = rand();
for offset in 0..4 {
ret.push((rand >> offset * 2) as u8);
count += 1;
}
}

writer.copy_to_user(&ret, 0)?;
Ok(len)
}
}
Loading

0 comments on commit 971462b

Please sign in to comment.