Patch feat robust futex (#682)

* feat: 实现robust lock机制

* 前面更改vscode,修改回来

* 修改dadk的路径

* 提交.gitnore和.cargo,删除LICENSE,修改README

* 修改一个warn

* 删除.rustc_info.json

* 删除target文件夹

* 恢复DragonOS的LICENSE,删除Cargo.lock

* 将校验用户空间地址的代码写入函数内;将部分match分支用ok_or代替

* 修改wakeup函数获取running queue时unwrap一个None值发生panic

* 测试程序使用syscalls库进行系统调用
This commit is contained in:
hmt
2024-04-06 22:26:34 +08:00
committed by GitHub
parent 23ef2b33d1
commit 06560afa2a
11 changed files with 825 additions and 15 deletions

View File

@ -3,7 +3,12 @@ use alloc::{
sync::{Arc, Weak},
};
use core::hash::{Hash, Hasher};
use core::{intrinsics::likely, sync::atomic::AtomicU64};
use core::{
intrinsics::{likely, unlikely},
mem,
sync::atomic::AtomicU64,
};
use hashbrown::HashMap;
use system_error::SystemError;
@ -12,9 +17,9 @@ use crate::{
exception::InterruptArch,
libs::spinlock::{SpinLock, SpinLockGuard},
mm::{ucontext::AddressSpace, MemoryManagementArch, VirtAddr},
process::{ProcessControlBlock, ProcessManager},
process::{Pid, ProcessControlBlock, ProcessManager},
sched::{schedule, SchedMode},
syscall::user_access::UserBufferReader,
syscall::user_access::{UserBufferReader, UserBufferWriter},
time::{
timer::{next_n_us_timer_jiffies, Timer, WakeUpHelper},
TimeSpec,
@ -635,3 +640,251 @@ impl Futex {
Ok(*oldval)
}
}
//用于指示在处理robust list是最多处理多少个条目
const ROBUST_LIST_LIMIT: isize = 2048;
#[derive(Debug, Copy, Clone)]
pub struct RobustList {
next: VirtAddr,
}
#[derive(Debug, Copy, Clone)]
pub struct RobustListHead {
list: RobustList,
futex_offset: isize,
list_op_pending: VirtAddr,
}
impl RobustListHead {
/// # 获得futex的用户空间地址
pub fn futex_uaddr(&self, entry: VirtAddr) -> VirtAddr {
return VirtAddr::new(entry.data() + self.futex_offset as usize);
}
/// #获得list_op_peding的用户空间地址
pub fn pending_uaddr(&self) -> Option<VirtAddr> {
if self.list_op_pending.is_null() {
return None;
} else {
return Some(self.futex_uaddr(self.list_op_pending));
}
}
/// # 在内核注册robust list
/// ## 参数
/// - head_uaddrrobust list head用户空间地址
/// - lenrobust list head的长度
pub fn set_robust_list(head_uaddr: VirtAddr, len: usize) -> Result<usize, SystemError> {
let robust_list_head_len = mem::size_of::<&RobustListHead>();
if unlikely(len != robust_list_head_len) {
return Err(SystemError::EINVAL);
}
let user_buffer_reader = UserBufferReader::new(
head_uaddr.as_ptr::<RobustListHead>(),
mem::size_of::<RobustListHead>(),
true,
)?;
let robust_list_head = *user_buffer_reader.read_one_from_user::<RobustListHead>(0)?;
// 向内核注册robust list
ProcessManager::current_pcb().set_robust_list(Some(robust_list_head));
return Ok(0);
}
/// # 获取robust list head到用户空间
/// ## 参数
/// - pid当前进程/线程的pid
/// -
pub fn get_robust_list(
pid: usize,
head_uaddr: VirtAddr,
len_ptr_uaddr: VirtAddr,
) -> Result<usize, SystemError> {
// 获取当前进程的process control block
let pcb: Arc<ProcessControlBlock> = if pid == 0 {
ProcessManager::current_pcb()
} else {
ProcessManager::find(Pid::new(pid)).ok_or(SystemError::ESRCH)?
};
// TODO: 检查当前进程是否能ptrace另一个进程
let ptrace = true;
if !ptrace {
return Err(SystemError::EPERM);
}
//获取当前线程的robust list head 和 长度
let robust_list_head = (*pcb.get_robust_list()).ok_or(SystemError::EINVAL)?;
// 将len拷贝到用户空间len_ptr
let mut user_writer = UserBufferWriter::new(
len_ptr_uaddr.as_ptr::<usize>(),
core::mem::size_of::<usize>(),
true,
)?;
user_writer.copy_one_to_user(&mem::size_of::<RobustListHead>(), 0)?;
// 将head拷贝到用户空间head
let mut user_writer = UserBufferWriter::new(
head_uaddr.as_ptr::<RobustListHead>(),
mem::size_of::<RobustListHead>(),
true,
)?;
user_writer.copy_one_to_user(&robust_list_head, 0)?;
return Ok(0);
}
/// # 进程/线程退出时清理工作
/// ## 参数
/// - current当前进程/线程的pcb
/// - pid当前进程/线程的pid
pub fn exit_robust_list(pcb: Arc<ProcessControlBlock>) {
//指向当前进程的robust list头部的指针
let head = match *pcb.get_robust_list() {
Some(rl) => rl,
None => {
return;
}
};
// 遍历当前进程/线程的robust list
for futex_uaddr in head.futexes() {
let ret = Self::handle_futex_death(futex_uaddr, pcb.pid().into() as u32);
if ret.is_err() {
return;
}
}
pcb.set_robust_list(None);
}
/// # 返回robust list的迭代器将robust list list_op_pending 放到最后(如果存在)
fn futexes(&self) -> FutexIterator<'_> {
return FutexIterator::new(self);
}
/// # 处理进程即将死亡时进程已经持有的futex唤醒其他等待该futex的线程
/// ## 参数
/// - futex_uaddrfutex的用户空间地址
/// - pid: 当前进程/线程的pid
fn handle_futex_death(futex_uaddr: VirtAddr, pid: u32) -> Result<usize, SystemError> {
let futex_val = {
if futex_uaddr.is_null() {
return Err(SystemError::EINVAL);
}
let user_buffer_reader = UserBufferReader::new(
futex_uaddr.as_ptr::<u32>(),
core::mem::size_of::<u32>(),
true,
)?;
*user_buffer_reader.read_one_from_user::<u32>(0)?
};
let mut uval = futex_val;
loop {
// 该futex可能被其他进程占有
let owner = uval & FUTEX_TID_MASK;
if owner != pid {
break;
}
// 判断是否有FUTEX_WAITERS和标记FUTEX_OWNER_DIED
let mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED;
// 读取用户空间目前的futex字段判断在此之前futex是否有被修改
let user_buffer_reader = UserBufferReader::new(
futex_uaddr.as_ptr::<u32>(),
core::mem::size_of::<u32>(),
true,
)?;
let nval = *user_buffer_reader.read_one_from_user::<u32>(0)?;
if nval != mval {
uval = nval;
let mut user_buffer_writer = UserBufferWriter::new(
futex_uaddr.as_ptr::<u32>(),
core::mem::size_of::<u32>(),
true,
)?;
user_buffer_writer.copy_one_to_user(&mval, 0)?;
continue;
}
// 有等待者,进行唤醒操作
if nval & FUTEX_WAITERS != 0 {
let mut flags = FutexFlag::FLAGS_MATCH_NONE;
flags.insert(FutexFlag::FLAGS_SHARED);
Futex::futex_wake(futex_uaddr, flags, 1, FUTEX_BITSET_MATCH_ANY)?;
}
break;
}
return Ok(0);
}
}
pub struct FutexIterator<'a> {
robust_list_head: &'a RobustListHead,
entry: VirtAddr,
count: isize,
}
impl<'a> FutexIterator<'a> {
pub fn new(robust_list_head: &'a RobustListHead) -> Self {
return Self {
robust_list_head,
entry: robust_list_head.list.next,
count: 0,
};
}
fn is_end(&mut self) -> bool {
return self.count < 0;
}
}
impl<'a> Iterator for FutexIterator<'a> {
type Item = VirtAddr;
fn next(&mut self) -> Option<Self::Item> {
if self.is_end() {
return None;
}
while self.entry.data() != &self.robust_list_head.list as *const RobustList as usize {
if self.count == ROBUST_LIST_LIMIT {
break;
}
if self.entry.is_null() {
return None;
}
//获取futex val地址
let futex_uaddr = if self.entry.data() != self.robust_list_head.list_op_pending.data() {
Some(self.robust_list_head.futex_uaddr(self.entry))
} else {
None
};
let user_buffer_reader = UserBufferReader::new(
self.entry.as_ptr::<RobustList>(),
mem::size_of::<RobustList>(),
true,
)
.ok()?;
let next_entry = user_buffer_reader
.read_one_from_user::<RobustList>(0)
.ok()?;
self.entry = next_entry.next;
self.count += 1;
if futex_uaddr.is_some() {
return futex_uaddr;
}
}
self.count -= 1;
self.robust_list_head.pending_uaddr()
}
}

View File

@ -1,8 +1,15 @@
use system_error::SystemError;
use crate::{mm::VirtAddr, syscall::Syscall, time::TimeSpec};
use crate::{
mm::{verify_area, VirtAddr},
syscall::Syscall,
time::TimeSpec,
};
use super::{constant::*, futex::Futex};
use super::{
constant::*,
futex::{Futex, RobustListHead},
};
impl Syscall {
pub fn do_futex(
@ -14,6 +21,9 @@ impl Syscall {
val2: u32,
val3: u32,
) -> Result<usize, SystemError> {
verify_area(uaddr, core::mem::size_of::<u32>())?;
verify_area(uaddr2, core::mem::size_of::<u32>())?;
let cmd = FutexArg::from_bits(operation.bits() & FutexFlag::FUTEX_CMD_MASK.bits())
.ok_or(SystemError::ENOSYS)?;
@ -101,4 +111,25 @@ impl Syscall {
}
}
}
pub fn set_robust_list(head_uaddr: VirtAddr, len: usize) -> Result<usize, SystemError> {
//判断用户空间地址的合法性
verify_area(head_uaddr, core::mem::size_of::<u32>())?;
let ret = RobustListHead::set_robust_list(head_uaddr, len);
return ret;
}
pub fn get_robust_list(
pid: usize,
head_uaddr: VirtAddr,
len_ptr_uaddr: VirtAddr,
) -> Result<usize, SystemError> {
//判断用户空间地址的合法性
verify_area(head_uaddr, core::mem::size_of::<u32>())?;
verify_area(len_ptr_uaddr, core::mem::size_of::<u32>())?;
let ret = RobustListHead::get_robust_list(pid, head_uaddr, len_ptr_uaddr);
return ret;
}
}