Browse Source

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库进行系统调用
hmt 11 months ago
parent
commit
06560afa2a

+ 256 - 3
kernel/src/libs/futex/futex.rs

@@ -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_uaddr:robust list head用户空间地址
+    /// - len:robust 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_uaddr:futex的用户空间地址
+    /// - 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()
+    }
+}

+ 33 - 2
kernel/src/libs/futex/syscall.rs

@@ -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;
+    }
 }

+ 20 - 2
kernel/src/process/mod.rs

@@ -16,6 +16,7 @@ use system_error::SystemError;
 
 use crate::{
     arch::{
+        cpu::current_cpu_id,
         ipc::signal::{AtomicSignal, SigSet, Signal},
         process::ArchPCBInfo,
         CurrentIrqArch,
@@ -33,7 +34,7 @@ use crate::{
         casting::DowncastArc,
         futex::{
             constant::{FutexFlag, FUTEX_BITSET_MATCH_ANY},
-            futex::Futex,
+            futex::{Futex, RobustListHead},
         },
         lock_free_flags::LockFreeFlags,
         rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
@@ -230,7 +231,8 @@ impl ProcessManager {
                 // avoid deadlock
                 drop(writer);
 
-                let rq = cpu_rq(pcb.sched_info().on_cpu().unwrap().data() as usize);
+                let rq =
+                    cpu_rq(pcb.sched_info().on_cpu().unwrap_or(current_cpu_id()).data() as usize);
 
                 let (rq, _guard) = rq.self_lock();
                 rq.update_rq_clock();
@@ -405,6 +407,8 @@ impl ProcessManager {
             unsafe { clear_user(addr, core::mem::size_of::<i32>()).expect("clear tid failed") };
         }
 
+        RobustListHead::exit_robust_list(pcb.clone());
+
         // 如果是vfork出来的进程,则需要处理completion
         if thread.vfork_done.is_some() {
             thread.vfork_done.as_ref().unwrap().complete_all();
@@ -629,6 +633,9 @@ pub struct ProcessControlBlock {
 
     /// 线程信息
     thread: RwLock<ThreadInfo>,
+
+    /// 进程的robust lock列表
+    robust_list: RwLock<Option<RobustListHead>>,
 }
 
 impl ProcessControlBlock {
@@ -694,6 +701,7 @@ impl ProcessControlBlock {
             children: RwLock::new(Vec::new()),
             wait_queue: WaitQueue::default(),
             thread: RwLock::new(ThreadInfo::new()),
+            robust_list: RwLock::new(None),
         };
 
         // 初始化系统调用栈
@@ -940,6 +948,16 @@ impl ProcessControlBlock {
     pub fn sig_struct_irqsave(&self) -> SpinLockGuard<SignalStruct> {
         self.sig_struct.lock_irqsave()
     }
+
+    #[inline(always)]
+    pub fn get_robust_list(&self) -> RwLockReadGuard<Option<RobustListHead>> {
+        return self.robust_list.read_irqsave();
+    }
+
+    #[inline(always)]
+    pub fn set_robust_list(&self, new_robust_list: Option<RobustListHead>) {
+        *self.robust_list.write_irqsave() = new_robust_list;
+    }
 }
 
 impl Drop for ProcessControlBlock {

+ 20 - 8
kernel/src/syscall/mod.rs

@@ -690,9 +690,6 @@ impl Syscall {
                 let uaddr2 = VirtAddr::new(args[4]);
                 let val3 = args[5] as u32;
 
-                verify_area(uaddr, core::mem::size_of::<u32>())?;
-                verify_area(uaddr2, core::mem::size_of::<u32>())?;
-
                 let mut timespec = None;
                 if utime != 0 && operation.contains(FutexFlag::FLAGS_HAS_TIMEOUT) {
                     let reader = UserBufferReader::new(
@@ -707,6 +704,26 @@ impl Syscall {
                 Self::do_futex(uaddr, operation, val, timespec, uaddr2, utime as u32, val3)
             }
 
+            SYS_SET_ROBUST_LIST => {
+                let head = args[0];
+                let head_uaddr = VirtAddr::new(head);
+                let len = args[1];
+
+                let ret = Self::set_robust_list(head_uaddr, len);
+                return ret;
+            }
+
+            SYS_GET_ROBUST_LIST => {
+                let pid = args[0];
+                let head = args[1];
+                let head_uaddr = VirtAddr::new(head);
+                let len_ptr = args[2];
+                let len_ptr_uaddr = VirtAddr::new(len_ptr);
+
+                let ret = Self::get_robust_list(pid, head_uaddr, len_ptr_uaddr);
+                return ret;
+            }
+
             SYS_READV => Self::readv(args[0] as i32, args[1], args[2]),
             SYS_WRITEV => Self::writev(args[0] as i32, args[1], args[2]),
 
@@ -952,11 +969,6 @@ impl Syscall {
                 Ok(0)
             }
 
-            SYS_SET_ROBUST_LIST => {
-                kwarn!("SYS_SET_ROBUST_LIST has not yet been implemented");
-                Ok(0)
-            }
-
             SYS_RSEQ => {
                 kwarn!("SYS_RSEQ has not yet been implemented");
                 Ok(0)

+ 2 - 0
user/apps/test-for-robustfutex/.cargo/config.toml

@@ -0,0 +1,2 @@
+[build]
+target = "x86_64-unknown-linux-musl"

+ 3 - 0
user/apps/test-for-robustfutex/.gitignore

@@ -0,0 +1,3 @@
+/target
+Cargo.lock
+/install/

+ 12 - 0
user/apps/test-for-robustfutex/Cargo.toml

@@ -0,0 +1,12 @@
+[package]
+name = "test-for-robustfutex"
+version = "0.1.0"
+edition = "2021"
+description = "some tests for robust futex"
+authors = [ "hmt <[email protected]>" ]
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+syscalls = '0.6.18'
+libc = '0.2.153'

+ 56 - 0
user/apps/test-for-robustfutex/Makefile

@@ -0,0 +1,56 @@
+TOOLCHAIN="+nightly-2023-08-15-x86_64-unknown-linux-gnu"
+RUSTFLAGS+=""
+
+ifdef DADK_CURRENT_BUILD_DIR
+# 如果是在dadk中编译,那么安装到dadk的安装目录中
+	INSTALL_DIR = $(DADK_CURRENT_BUILD_DIR)
+else
+# 如果是在本地编译,那么安装到当前目录下的install目录中
+	INSTALL_DIR = ./install
+endif
+
+ifeq ($(ARCH), x86_64)
+	export RUST_TARGET=x86_64-unknown-linux-musl
+else ifeq ($(ARCH), riscv64)
+	export RUST_TARGET=riscv64gc-unknown-linux-gnu
+else 
+# 默认为x86_86,用于本地编译
+	export RUST_TARGET=x86_64-unknown-linux-musl
+endif
+
+run:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --target $(RUST_TARGET)
+
+build:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --target $(RUST_TARGET)
+
+clean:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --target $(RUST_TARGET)
+
+test:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test --target $(RUST_TARGET)
+
+doc:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) doc --target $(RUST_TARGET)
+
+fmt:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) fmt
+
+fmt-check:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) fmt --check
+
+run-release:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --target $(RUST_TARGET) --release
+
+build-release:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --target $(RUST_TARGET) --release
+
+clean-release:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --target $(RUST_TARGET) --release
+
+test-release:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test --target $(RUST_TARGET) --release
+
+.PHONY: install
+install:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) install --target $(RUST_TARGET) --path . --no-track --root $(INSTALL_DIR) --force

+ 5 - 0
user/apps/test-for-robustfutex/README.md

@@ -0,0 +1,5 @@
+# 测试robust lock机制
+
+此代码主要是用于测试:
+1、robust lock机制中的两个系统调用是否能正常使用
+2、当持有锁的线程异常终止时,等待该锁的其他线程能够被通知到,以避免死锁或数据不一样

+ 394 - 0
user/apps/test-for-robustfutex/src/main.rs

@@ -0,0 +1,394 @@
+extern crate libc;
+extern crate syscalls;
+
+use std::{
+    ffi::c_void,
+    mem::{self, size_of},
+    process,
+    ptr::{self, NonNull},
+    sync::atomic::{AtomicI32, Ordering},
+    thread,
+    time::Duration,
+};
+
+use syscalls::{
+    syscall0, syscall2, syscall3, syscall6,
+    Sysno::{futex, get_robust_list, gettid, set_robust_list},
+};
+
+use libc::{
+    c_int, mmap, perror, EXIT_FAILURE, MAP_ANONYMOUS, MAP_FAILED, MAP_SHARED, PROT_READ, PROT_WRITE,
+};
+
+const FUTEX_WAIT: usize = 0;
+const FUTEX_WAKE: usize = 1;
+
+// 封装futex
+#[derive(Clone, Copy, Debug)]
+struct Futex {
+    addr: *mut u32,
+}
+
+impl Futex {
+    pub fn new(addr: *mut u32) -> Self {
+        return Futex { addr };
+    }
+
+    pub fn get_addr(&self, offset: isize) -> *mut u32 {
+        return unsafe { self.addr.offset(offset) };
+    }
+
+    pub fn get_val(&self, offset: isize) -> u32 {
+        return unsafe { self.addr.offset(offset).read() };
+    }
+
+    pub fn set_val(&self, val: u32, offset: isize) {
+        unsafe {
+            self.addr.offset(offset).write(val);
+        }
+    }
+}
+
+unsafe impl Send for Futex {}
+unsafe impl Sync for Futex {}
+
+#[derive(Clone, Copy, Debug)]
+struct Lock {
+    addr: *mut i32,
+}
+
+impl Lock {
+    pub fn new(addr: *mut i32) -> Self {
+        return Lock { addr };
+    }
+
+    pub fn get_val(&self, offset: isize) -> i32 {
+        return unsafe { self.addr.offset(offset).read() };
+    }
+
+    pub fn set_val(&self, val: i32, offset: isize) {
+        unsafe {
+            self.addr.offset(offset).write(val);
+        }
+    }
+}
+
+unsafe impl Send for Lock {}
+unsafe impl Sync for Lock {}
+
+#[derive(Debug, Clone, Copy)]
+struct RobustList {
+    next: *const RobustList,
+}
+
+#[derive(Debug, Clone, Copy)]
+struct RobustListHead {
+    list: RobustList,
+    /// 向kernel提供了要检查的futex字段的相对位置,保持用户空间的灵活性,可以自由
+    /// 地调整其数据结构,而无需向内核硬编码任何特定的偏移量
+    /// futexes中前面的地址是用来存入robust list中(list.next),后面是存放具体的futex val
+    /// 这个字段的作用就是从前面的地址偏移到后面的地址中从而获取futex val
+    #[allow(dead_code)]
+    futex_offset: isize,
+    /// 潜在的竞争条件:由于添加和删除列表是在获取锁之后进行的,这給线程留下了一个小窗口,在此期间可能会导致异常退出,
+    /// 从而使锁被悬挂,为了防止这种可能性。用户空间还维护了一个简单的list_op_pending字段,允许线程在获取锁后但还未添加到
+    /// 列表时就异常退出时进行清理。并且在完成列表添加或删除操作后将其清除
+    /// 这里没有测试这个,在内核中实现实际上就是把list_op_pending地址进行一次唤醒(如果有等待者)
+    #[allow(dead_code)]
+    list_op_pending: *const RobustList,
+}
+
+fn error_handle(msg: &str) -> ! {
+    unsafe { perror(msg.as_ptr() as *const i8) };
+    process::exit(EXIT_FAILURE)
+}
+
+fn futex_wait(futexes: Futex, thread: &str, offset_futex: isize, lock: Lock, offset_count: isize) {
+    loop {
+        let atomic_count = AtomicI32::new(lock.get_val(offset_count));
+        if atomic_count
+            .compare_exchange(1, 0, Ordering::SeqCst, Ordering::SeqCst)
+            .is_ok()
+        {
+            lock.set_val(0, offset_count);
+
+            // 设置futex锁当前被哪个线程占用
+            let tid = unsafe { syscall0(gettid).unwrap() as u32 };
+            futexes.set_val(futexes.get_val(offset_futex) | tid, offset_futex);
+
+            break;
+        }
+
+        println!("{} wating...", thread);
+        let futex_val = futexes.get_val(offset_futex);
+        futexes.set_val(futex_val | 0x8000_0000, offset_futex);
+        let ret = unsafe {
+            syscall6(
+                futex,
+                futexes.get_addr(offset_futex) as usize,
+                FUTEX_WAIT,
+                futexes.get_val(offset_futex) as usize,
+                0,
+                0,
+                0,
+            )
+        };
+        if ret.is_err() {
+            error_handle("futex_wait failed");
+        }
+
+        // 被唤醒后释放锁
+        let atomic_count = AtomicI32::new(lock.get_val(offset_count));
+        if atomic_count
+            .compare_exchange(0, 1, Ordering::SeqCst, Ordering::SeqCst)
+            .is_ok()
+        {
+            lock.set_val(1, offset_count);
+
+            // 释放futex锁,不被任何线程占用
+            futexes.set_val(futexes.get_val(offset_futex) & 0xc000_0000, offset_futex);
+
+            break;
+        }
+    }
+}
+
+fn futex_wake(futexes: Futex, thread: &str, offset_futex: isize, lock: Lock, offset_count: isize) {
+    let atomic_count = AtomicI32::new(lock.get_val(offset_count));
+    if atomic_count
+        .compare_exchange(0, 1, Ordering::SeqCst, Ordering::SeqCst)
+        .is_ok()
+    {
+        lock.set_val(1, offset_count);
+
+        // 释放futex锁,不被任何线程占用
+        futexes.set_val(futexes.get_val(offset_futex) & 0xc000_0000, offset_futex);
+
+        // 如果没有线程/进程在等这个futex,则不必唤醒, 释放改锁即可
+        let futex_val = futexes.get_val(offset_futex);
+        if futex_val & 0x8000_0000 == 0 {
+            return;
+        }
+
+        futexes.set_val(futex_val & !(1 << 31), offset_futex);
+        let ret = unsafe {
+            syscall6(
+                futex,
+                futexes.get_addr(offset_futex) as usize,
+                FUTEX_WAKE,
+                1,
+                0,
+                0,
+                0,
+            )
+        };
+        if ret.is_err() {
+            error_handle("futex wake failed");
+        }
+        println!("{} waked", thread);
+    }
+}
+
+fn set_list(futexes: Futex) {
+    let head = RobustListHead {
+        list: RobustList { next: ptr::null() },
+        futex_offset: 44,
+        list_op_pending: ptr::null(),
+    };
+    let head = NonNull::from(&head).as_ptr();
+    unsafe {
+        // 加入第一个futex
+        let head_ref_mut = &mut *head;
+        head_ref_mut.list.next = futexes.get_addr(0) as *const RobustList;
+
+        // 加入第二个futex
+        let list_2 = NonNull::from(&*head_ref_mut.list.next).as_ptr();
+        let list_2_ref_mut = &mut *list_2;
+        list_2_ref_mut.next = futexes.get_addr(1) as *const RobustList;
+
+        //println!("robust list next: {:?}", (*head).list.next );
+        //println!("robust list next next: {:?}", (*(*head).list.next).next );
+
+        // 向内核注册robust list
+        let len = mem::size_of::<*mut RobustListHead>();
+        let ret = syscall2(set_robust_list, head as usize, len);
+        if ret.is_err() {
+            println!("failed to set_robust_list, ret = {:?}", ret);
+        }
+    }
+}
+
+fn main() {
+    test01();
+
+    println!("-------------");
+
+    test02();
+
+    println!("-------------");
+}
+
+//测试set_robust_list和get_robust_list两个系统调用是否能正常使用
+fn test01() {
+    // 创建robust list 头指针
+    let head = RobustListHead {
+        list: RobustList { next: ptr::null() },
+        futex_offset: 8,
+        list_op_pending: ptr::null(),
+    };
+    let head = NonNull::from(&head).as_ptr();
+
+    let futexes = unsafe {
+        mmap(
+            ptr::null_mut::<c_void>(),
+            (size_of::<c_int>() * 2) as libc::size_t,
+            PROT_READ | PROT_WRITE,
+            MAP_ANONYMOUS | MAP_SHARED,
+            -1,
+            0,
+        ) as *mut u32
+    };
+    if futexes == MAP_FAILED as *mut u32 {
+        error_handle("futexes_addr mmap failed");
+    }
+
+    unsafe {
+        futexes.offset(11).write(0x0000_0000);
+        futexes.offset(12).write(0x8000_0000);
+        println!("futex1 next addr: {:?}", futexes.offset(0));
+        println!("futex2 next addr: {:?}", futexes.offset(1));
+        println!("futex1 val addr: {:?}", futexes.offset(11));
+        println!("futex2 val addr: {:?}", futexes.offset(12));
+        println!("futex1 val: {:#x?}", futexes.offset(11).read());
+        println!("futex2 val: {:#x?}", futexes.offset(12).read());
+    }
+
+    // 打印注册之前的robust list
+    println!("robust list next(get behind): {:?}", &unsafe { *head });
+
+    unsafe {
+        let head_ref_mut = &mut *head;
+        head_ref_mut.list.next = futexes.offset(0) as *const RobustList;
+        let list_2 = NonNull::from(&*head_ref_mut.list.next).as_ptr();
+        let list_2_ref_mut = &mut *list_2;
+        list_2_ref_mut.next = futexes.offset(1) as *const RobustList;
+        println!("robust list next addr: {:?}", (*head).list.next);
+        println!(
+            "robust list next next addr: {:?}",
+            (*(*head).list.next).next
+        );
+    }
+
+    unsafe {
+        let len = mem::size_of::<*mut RobustListHead>();
+        let ret = syscall2(set_robust_list, head as usize, len);
+        if ret.is_err() {
+            println!("failed to set_robust_list, ret = {:?}", ret);
+        }
+    }
+
+    println!("get before, set after: {:?}", head);
+    println!("get before, set after: {:?}", &unsafe { *head });
+    unsafe {
+        let len: usize = 0;
+        println!("len = {}", len);
+        let len_ptr = NonNull::from(&len).as_ptr();
+        let ret = syscall3(get_robust_list, 0, head as usize, len_ptr as usize);
+        println!("get len = {}", len);
+        if ret.is_err() {
+            println!("failed to get_robust_list, ret = {:?}", ret);
+        }
+
+        println!("futex1 val: {:#x}", futexes.offset(11).read());
+        println!("futex2 val: {:#x}", futexes.offset(12).read());
+        println!("robust list next: {:?}", futexes.offset(0));
+        println!("robust list next next: {:#x?}", futexes.offset(0).read());
+    }
+    println!("robust list head(get after): {:?}", head);
+    println!("robust list next(get after): {:?}", &unsafe { *head });
+}
+
+//测试一个线程异常退出时futex的robustness(多线程测试,目前futex还不支持多进程)
+fn test02() {
+    let futexes = unsafe {
+        mmap(
+            ptr::null_mut::<c_void>(),
+            (size_of::<c_int>() * 2) as libc::size_t,
+            PROT_READ | PROT_WRITE,
+            MAP_ANONYMOUS | MAP_SHARED,
+            -1,
+            0,
+        ) as *mut u32
+    };
+    if futexes == MAP_FAILED as *mut u32 {
+        error_handle("mmap failed");
+    }
+    let count = unsafe {
+        mmap(
+            ptr::null_mut::<c_void>(),
+            (size_of::<c_int>() * 2) as libc::size_t,
+            PROT_READ | PROT_WRITE,
+            MAP_ANONYMOUS | MAP_SHARED,
+            -1,
+            0,
+        ) as *mut i32
+    };
+    if count == MAP_FAILED as *mut i32 {
+        error_handle("mmap failed");
+    }
+
+    unsafe {
+        // 在这个示例中,第一段和第二段地址放入robust list,第11段地址和第12段地址存放futex val
+        futexes.offset(11).write(0x0000_0000);
+        futexes.offset(12).write(0x0000_0000);
+        println!("futex1 next addr: {:?}", futexes.offset(0));
+        println!("futex2 next addr: {:?}", futexes.offset(1));
+        println!("futex1 val addr: {:?}", futexes.offset(11));
+        println!("futex2 val addr: {:?}", futexes.offset(12));
+        println!("futex1 val: {:#x?}", futexes.offset(11).read());
+        println!("futex2 val: {:#x?}", futexes.offset(12).read());
+
+        count.offset(0).write(1);
+        count.offset(1).write(0);
+        println!("count1 val: {:?}", count.offset(0).read());
+        println!("count2 val: {:?}", count.offset(1).read());
+    }
+
+    let futexes = Futex::new(futexes);
+    let locks = Lock::new(count);
+
+    // tid1 = 7
+    let thread1 = thread::spawn(move || {
+        set_list(futexes);
+        thread::sleep(Duration::from_secs(2));
+        for i in 0..2 {
+            futex_wait(futexes, "thread1", 11, locks, 0);
+            println!("thread1 times: {}", i);
+            thread::sleep(Duration::from_secs(3));
+
+            let tid = unsafe { syscall0(gettid).unwrap() as u32 };
+            futexes.set_val(futexes.get_val(12) | tid, 12);
+
+            if i == 1 {
+                // 让thread1异常退出,从而无法唤醒thread2,检测robustness
+                println!("Thread1 exiting early due to simulated error.");
+                return;
+            }
+            futex_wake(futexes, "thread2", 12, locks, 1);
+        }
+    });
+
+    // tid2 = 6
+    set_list(futexes);
+    for i in 0..2 {
+        futex_wait(futexes, "thread2", 12, locks, 1);
+        println!("thread2 times: {}", i);
+
+        let tid = unsafe { syscall0(gettid).unwrap() as u32 };
+        futexes.set_val(futexes.get_val(11) | tid, 11);
+
+        futex_wake(futexes, "thread1", 11, locks, 0);
+    }
+
+    thread1.join().unwrap();
+}

+ 24 - 0
user/dadk/config/test_for_robustfutex_0_1_0.dadk

@@ -0,0 +1,24 @@
+{
+  "name": "test-for-robustfutex",
+  "version": "0.1.0",
+  "description": "some tests for robust futex",
+  "rust_target": null,
+  "task_type": {
+    "BuildFromSource": {
+      "Local": {
+        "path": "apps/test-for-robustfutex"
+      }
+    }
+  },
+  "depends": [],
+  "build": {
+    "build_command": "make install"
+  },
+  "install": {
+    "in_dragonos_path": "/"
+  },
+  "clean": {
+    "clean_command": "make clean"
+  },
+  "envs": []
+}