From 767e9dd745a8bd5abb87ebaafbb53dc05006ec53 Mon Sep 17 00:00:00 2001 From: Zichun Yu Date: Mon, 4 Apr 2022 19:30:52 +0800 Subject: [PATCH] Fix pthread_cond & pthread_tsd & ... --- linux-object/src/lib.rs | 2 +- linux-object/src/process.rs | 23 ++--- linux-object/src/thread.rs | 22 ++--- linux-syscall/src/lib.rs | 16 ++-- linux-syscall/src/misc.rs | 144 ++++++++++++++++++++---------- linux-syscall/src/task.rs | 2 + loader/src/linux.rs | 1 + zCore/src/utils.rs | 2 +- zircon-object/src/signal/futex.rs | 44 +++++++-- zircon-syscall/src/futex.rs | 1 + 10 files changed, 164 insertions(+), 93 deletions(-) diff --git a/linux-object/src/lib.rs b/linux-object/src/lib.rs index 6b35c143..72264f41 100644 --- a/linux-object/src/lib.rs +++ b/linux-object/src/lib.rs @@ -1,7 +1,7 @@ //! Linux kernel objects #![no_std] -// #![deny(warnings, unsafe_code, missing_docs)] +#![deny(warnings, unsafe_code, missing_docs)] #![allow(clippy::upper_case_acronyms)] #![allow(clippy::uninit_vec)] #![feature(bool_to_option)] diff --git a/linux-object/src/process.rs b/linux-object/src/process.rs index 8c455b27..e63568f2 100644 --- a/linux-object/src/process.rs +++ b/linux-object/src/process.rs @@ -241,21 +241,16 @@ impl LinuxProcess { /// Get futex object. #[allow(unsafe_code)] - pub fn get_futex(&self, uaddr: VirtAddr) -> Option> { + pub fn get_futex(&self, uaddr: VirtAddr) -> Arc { let mut inner = self.inner.lock(); - // if uaddr == 683520 { - // return None; - // } - Some( - inner - .futexes - .entry(uaddr) - .or_insert_with(|| { - let value = unsafe { &*(uaddr as *const AtomicI32) }; - Futex::new(value) - }) - .clone(), - ) + inner + .futexes + .entry(uaddr) + .or_insert_with(|| { + let value = unsafe { &*(uaddr as *const AtomicI32) }; + Futex::new(value) + }) + .clone() } /// Get lowest free fd diff --git a/linux-object/src/thread.rs b/linux-object/src/thread.rs index b792d04b..e435207b 100644 --- a/linux-object/src/thread.rs +++ b/linux-object/src/thread.rs @@ -1,6 +1,5 @@ //! Linux Thread -use crate::error::LxError; use crate::error::SysResult; use crate::process::ProcessExt; use crate::signal::{SignalStack, Sigset}; @@ -22,8 +21,8 @@ pub trait ThreadExt { /// Get robust list. fn get_robust_list( &self, - head_ptr: UserOutPtr>, - len_ptr: UserOutPtr, + _head_ptr: UserOutPtr>, + _len_ptr: UserOutPtr, ) -> SysResult; /// Set robust list. fn set_robust_list(&self, head: UserInPtr, len: usize); @@ -61,14 +60,11 @@ impl ThreadExt for Thread { fn get_robust_list( &self, - mut head_ptr: UserOutPtr>, - mut len_ptr: UserOutPtr, + mut _head_ptr: UserOutPtr>, + mut _len_ptr: UserOutPtr, ) -> SysResult { - // if self.lock_linux().robust_list_len == 0 { - // return Err(LxError::EFAULT); - // } - head_ptr = (self.lock_linux().robust_list.as_ptr() as *mut RobustList as usize).into(); - len_ptr = (&self.lock_linux().robust_list_len as *const usize as usize).into(); + _head_ptr = (self.lock_linux().robust_list.as_ptr() as *mut RobustList as usize).into(); + _len_ptr = (&self.lock_linux().robust_list_len as *const usize as usize).into(); Ok(0) } @@ -89,7 +85,7 @@ impl CurrentThreadExt for CurrentThread { info!("exit: do futex {:?} wake 1", clear_child_tid); clear_child_tid.write(0).unwrap(); let uaddr = clear_child_tid.as_ptr() as VirtAddr; - let futex = self.proc().linux().get_futex(uaddr).unwrap(); + let futex = self.proc().linux().get_futex(uaddr); futex.wake(1); } self.exit(); @@ -100,11 +96,11 @@ impl CurrentThreadExt for CurrentThread { #[derive(Default)] pub struct RobustList { /// head - head: usize, + pub head: usize, /// off pub off: isize, /// pending - pending: usize, + pub pending: usize, } /// Linux specific thread information. diff --git a/linux-syscall/src/lib.rs b/linux-syscall/src/lib.rs index e04591c0..0caba9c8 100644 --- a/linux-syscall/src/lib.rs +++ b/linux-syscall/src/lib.rs @@ -15,7 +15,7 @@ //! #![no_std] -// #![deny(warnings, unsafe_code, missing_docs)] +#![deny(warnings, unsafe_code, missing_docs)] #![allow(clippy::upper_case_acronyms)] #[macro_use] @@ -363,10 +363,6 @@ impl Syscall<'_> { } // process - #[cfg(target_arch = "riscv64")] - Sys::CLONE => self.sys_clone(a0, a1, a2.into(), a3, a4.into()), - #[cfg(target_arch = "x86_64")] - Sys::CLONE => self.sys_clone(a0, a1, a2.into(), a4, a3.into()), Sys::EXECVE => self.sys_execve( self.into_in_userptr(a0).unwrap(), self.into_in_userptr(a1).unwrap(), @@ -379,7 +375,10 @@ impl Syscall<'_> { .await } Sys::SET_TID_ADDRESS => self.sys_set_tid_address(self.into_out_userptr(a0).unwrap()), - Sys::FUTEX => self.sys_futex(a0, a1 as _, a2 as _, a3).await, + Sys::FUTEX => { + info!("Futex: {} {} {} {} {} {}", a0, a1, a2, a3, a4, a5); + self.sys_futex(a0, a1 as _, a2 as _, a3, a4, a5 as _).await + } // Sys::FUTEX => self.unimplemented("futex", Ok(0)), Sys::TKILL => self.unimplemented("tkill", Ok(0)), Sys::GET_ROBUST_LIST => { @@ -532,6 +531,7 @@ impl Syscall<'_> { Sys::CHOWN => self.unimplemented("chown", Ok(0)), Sys::ARCH_PRCTL => self.sys_arch_prctl(a0 as _, a1), Sys::TIME => self.sys_time(self.into_out_userptr(a0).unwrap()), + Sys::CLONE => self.sys_clone(a0, a1, a2.into(), a4, a3.into()), // Sys::EPOLL_CREATE => self.sys_epoll_create(a0), // Sys::EPOLL_WAIT => self.sys_epoll_wait(a0, a1.into(), a2, a3), _ => self.unknown_syscall(sys_type), @@ -540,10 +540,10 @@ impl Syscall<'_> { #[cfg(target_arch = "riscv64")] async fn riscv64_syscall(&mut self, sys_type: Sys, args: [usize; 6]) -> SysResult { - debug!("riscv64_syscall: {:?}, {:?}", sys_type, args); - //let [a0, a1, a2, a3, a4, _a5] = args; + let [a0, a1, a2, a3, a4, _a5] = args; match sys_type { //Sys::OPEN => self.sys_open(a0.into(), a1, a2), + Sys::CLONE => self.sys_clone(a0, a1, a2.into(), a3, a4.into()), _ => self.unknown_syscall(sys_type), } } diff --git a/linux-syscall/src/misc.rs b/linux-syscall/src/misc.rs index a2a1839b..1b2d2ee7 100644 --- a/linux-syscall/src/misc.rs +++ b/linux-syscall/src/misc.rs @@ -4,10 +4,7 @@ use core::time::Duration; use futures::pin_mut; use kernel_hal::timer::timer_now; use linux_object::time::*; -use zircon_object::{ - task::{IntoResult, ThreadState}, - ZxResult, -}; +use zircon_object::task::ThreadState; impl Syscall<'_> { #[cfg(target_arch = "x86_64")] @@ -82,6 +79,8 @@ impl Syscall<'_> { op: u32, val: u32, timeout_addr: usize, + uaddr2: usize, + _val3: u32, ) -> SysResult { if let Err(_) = self.into_inout_userptr::(uaddr) { return Err(LxError::EINVAL); @@ -89,9 +88,15 @@ impl Syscall<'_> { let op = FutexFlags::from_bits_truncate(op); if !op.contains(FutexFlags::PRIVATE) { warn!("process-shared futex is unimplemented"); - return Err(LxError::ENOPROTOOPT); + // return Err(LxError::ENOPROTOOPT); + } + let mut val2 = 0; + if op.contains(FutexFlags::REQUEUE) { + if let Err(_) = self.into_inout_userptr::(uaddr2) { + return Err(LxError::EINVAL); + } + val2 = timeout_addr; } - let op = op - FutexFlags::PRIVATE; let timeout = if op.contains(FutexFlags::WAKE) { self.into_inout_userptr::(0).unwrap() } else { @@ -102,55 +107,96 @@ impl Syscall<'_> { } }; warn!( - "Futex: uaddr: {:#x}, op: {:x}, val: {}, timeout_ptr: {:x?}", + "Futex: uaddr: {:#x}, op: {:x}, val: {}, timeout_ptr: {:x?}, val2: {}", uaddr, op.bits(), val, - timeout + timeout, + val2, ); - let futex_op = self.linux_process().get_futex(uaddr); - match futex_op { - Some(futex) => match op { - FutexFlags::WAIT => { - let timeout = timeout.read_if_not_null()?; - let duration: Duration = match timeout { - Some(T) => T.into(), - None => Duration::from_secs(0), - }; - let into_lxerror = |e: ZxError| match e { - ZxError::BAD_STATE => LxError::EAGAIN, - e => e.into(), - }; - let future = futex.wait(val); - let res = if duration.as_millis() == 0 { - future.await - } else { - warn!("duration: {:?}", duration); - pin_mut!(future); - self.thread - .blocking_run( - future, - ThreadState::BlockedFutex, - timer_now() + duration, - None, - ) - .await - }; - match res { - Ok(_) => return Ok(0), - Err(e) => return Err(into_lxerror(e)), - } + let futex = self.linux_process().get_futex(uaddr); + let op = op - FutexFlags::PRIVATE; + match op { + FutexFlags::WAIT => { + let timeout = timeout.read_if_not_null()?; + let duration: Duration = match timeout { + Some(t) => t.into(), + None => Duration::from_secs(0), + }; + let into_lxerror = |e: ZxError| match e { + ZxError::BAD_STATE => LxError::EAGAIN, + e => e.into(), + }; + let future = futex.wait(val, false, self.thread.id() as i32); + let res = if duration.as_millis() == 0 { + future.await + } else { + warn!("duration: {:?}", duration); + pin_mut!(future); + self.thread + .blocking_run( + future, + ThreadState::BlockedFutex, + timer_now() + duration, + None, + ) + .await + }; + match res { + Ok(_) => return Ok(0), + Err(e) => return Err(into_lxerror(e)), } - FutexFlags::WAKE => { - let woken_up_count = futex.wake(val as usize); - Ok(woken_up_count) + } + FutexFlags::WAKE => { + let woken_up_count = futex.wake(val as usize); + Ok(woken_up_count) + } + FutexFlags::LOCK_PI => { + let timeout = timeout.read_if_not_null()?; + let duration: Duration = match timeout { + Some(t) => t.into(), + None => Duration::from_secs(0), + }; + let into_lxerror = |e: ZxError| match e { + ZxError::BAD_STATE => LxError::EAGAIN, + e => e.into(), + }; + let future = futex.wait(val, true, self.thread.id() as i32); + let res = if duration.as_millis() == 0 { + future.await + } else { + warn!("duration: {:?}", duration); + pin_mut!(future); + self.thread + .blocking_run( + future, + ThreadState::BlockedFutex, + timer_now() + duration, + None, + ) + .await + }; + match res { + Ok(_) => return Ok(0), + Err(e) => return Err(into_lxerror(e)), } - _ => { - warn!("unsupported futex operation: {:?}", op); - Err(LxError::ENOPROTOOPT) + } + FutexFlags::REQUEUE => { + let requeue_futex = self.linux_process().get_futex(uaddr2); + let into_lxerror = |e: ZxError| match e { + ZxError::BAD_STATE => LxError::EAGAIN, + e => e.into(), + }; + let res = futex.requeue(0, val as usize, val2, &requeue_futex, None, false); + match res { + Ok(_) => return Ok(0), + Err(e) => return Err(into_lxerror(e)), } - }, - None => Err(LxError::EAGAIN), + } + _ => { + warn!("unsupported futex operation: {:?}", op); + Err(LxError::ENOPROTOOPT) + } } } @@ -218,6 +264,8 @@ bitflags! { /// wakes at most val of the waiters that are waiting on the futex word at the address uaddr. const WAKE = 1; /// + const REQUEUE = 3; + /// const LOCK_PI = 6; /// const UNLOCK_PI = 7; diff --git a/linux-syscall/src/task.rs b/linux-syscall/src/task.rs index 2c99b8b0..e2335573 100644 --- a/linux-syscall/src/task.rs +++ b/linux-syscall/src/task.rs @@ -297,6 +297,7 @@ impl Syscall<'_> { Ok(tid as usize) } + /// Get robust list. pub fn sys_get_robust_list( &self, pid: i32, @@ -313,6 +314,7 @@ impl Syscall<'_> { Ok(0) } + /// Set robust list. pub fn sys_set_robust_list(&self, head: UserInPtr, len: usize) -> SysResult { warn!("in sys_set_robust_list"); if len != size_of::().into() { diff --git a/loader/src/linux.rs b/loader/src/linux.rs index 6879459d..82545eeb 100644 --- a/loader/src/linux.rs +++ b/loader/src/linux.rs @@ -60,6 +60,7 @@ async fn run_user(thread: CurrentThread) { } info!("back to user: thread id = {}", thread.id()); + // run trace!("go to user: {:#x?}", ctx); ctx.enter_uspace(); diff --git a/zCore/src/utils.rs b/zCore/src/utils.rs index a8eb7b39..74c78364 100644 --- a/zCore/src/utils.rs +++ b/zCore/src/utils.rs @@ -62,7 +62,7 @@ pub fn boot_options() -> BootOptions { #[cfg(feature = "linux")] root_proc: String::from(*options.get("ROOTPROC").unwrap_or(&"/bin/busybox?sh")), // root_proc: String::from(*options.get("ROOTPROC") - // .unwrap_or(&"/libc-test/functional/pthread_robust.exe")), + // .unwrap_or(&"/libc-test/functional/pthread_mutex.exe")), } } } diff --git a/zircon-object/src/signal/futex.rs b/zircon-object/src/signal/futex.rs index fad30c64..a2e943e8 100644 --- a/zircon-object/src/signal/futex.rs +++ b/zircon-object/src/signal/futex.rs @@ -57,8 +57,13 @@ impl Futex { /// /// [`wait_with_owner`]: Futex::wait_with_owner /// [`wake`]: Futex::wake - pub fn wait(self: &Arc, current_value: u32) -> impl Future { - self.wait_with_owner(current_value, None, None) + pub fn wait( + self: &Arc, + current_value: u32, + lock_pi: bool, + thread_id: i32, + ) -> impl Future { + self.wait_with_owner(current_value, None, None, lock_pi, thread_id) } /// Wake some number of threads waiting on a futex. @@ -117,12 +122,16 @@ impl Futex { current_value: u32, thread: Option>, new_owner: Option>, + lock_pi: bool, + thread_id: i32, ) -> impl Future { #[must_use = "wait does nothing unless polled/`await`-ed"] struct FutexFuture { waiter: Arc, current_value: u32, new_owner: Option>, + lock_pi: bool, + thread_id: i32, } impl Future for FutexFuture { type Output = ZxResult; @@ -133,15 +142,29 @@ impl Futex { if inner.woken { // set new owner on success inner.futex.inner.lock().set_owner(self.new_owner.clone()); + warn!("Futex Ready!!!"); return Poll::Ready(Ok(())); } // first time? if inner.waker.is_none() { // check value let value = inner.futex.value.load(Ordering::SeqCst); - if value as u32 != self.current_value { - warn!("Futex BAD STATE"); - return Poll::Ready(Err(ZxError::BAD_STATE)); + if self.lock_pi { + if value as u32 == 0 { + warn!("This is {}", self.thread_id); + inner.futex.value.store(self.thread_id, Ordering::SeqCst); + } else { + inner + .futex + .value + .store((value as u32 | 0x80000000) as i32, Ordering::SeqCst); + } + return Poll::Ready(Ok(())); + } else { + if value as u32 != self.current_value { + warn!("Futex BAD_STATE!!!"); + return Poll::Ready(Err(ZxError::BAD_STATE)); + } } // check new owner let mut futex = inner.futex.inner.lock(); @@ -182,6 +205,8 @@ impl Futex { }), current_value, new_owner, + lock_pi, + thread_id, } } @@ -224,11 +249,14 @@ impl Futex { requeue_count: usize, requeue_futex: &Arc, new_requeue_owner: Option>, + check_value: bool, ) -> ZxResult { let mut inner = self.inner.lock(); - // check value - if self.value.load(Ordering::SeqCst) != current_value { - return Err(ZxError::BAD_STATE); + if check_value { + // check value + if self.value.load(Ordering::SeqCst) != current_value { + return Err(ZxError::BAD_STATE); + } } // wake for _ in 0..wake_count { diff --git a/zircon-syscall/src/futex.rs b/zircon-syscall/src/futex.rs index 726d7479..76950c33 100644 --- a/zircon-syscall/src/futex.rs +++ b/zircon-syscall/src/futex.rs @@ -74,6 +74,7 @@ impl Syscall<'_> { requeue_count as usize, &requeue_futex, new_requeue_owner, + true, )?; Ok(()) }