Fix pthread_cond & pthread_tsd & ...

This commit is contained in:
Zichun Yu 2022-04-04 19:30:52 +08:00
parent d6687d9a65
commit 767e9dd745
10 changed files with 164 additions and 93 deletions

View File

@ -1,7 +1,7 @@
//! Linux kernel objects //! Linux kernel objects
#![no_std] #![no_std]
// #![deny(warnings, unsafe_code, missing_docs)] #![deny(warnings, unsafe_code, missing_docs)]
#![allow(clippy::upper_case_acronyms)] #![allow(clippy::upper_case_acronyms)]
#![allow(clippy::uninit_vec)] #![allow(clippy::uninit_vec)]
#![feature(bool_to_option)] #![feature(bool_to_option)]

View File

@ -241,21 +241,16 @@ impl LinuxProcess {
/// Get futex object. /// Get futex object.
#[allow(unsafe_code)] #[allow(unsafe_code)]
pub fn get_futex(&self, uaddr: VirtAddr) -> Option<Arc<Futex>> { pub fn get_futex(&self, uaddr: VirtAddr) -> Arc<Futex> {
let mut inner = self.inner.lock(); let mut inner = self.inner.lock();
// if uaddr == 683520 { inner
// return None; .futexes
// } .entry(uaddr)
Some( .or_insert_with(|| {
inner let value = unsafe { &*(uaddr as *const AtomicI32) };
.futexes Futex::new(value)
.entry(uaddr) })
.or_insert_with(|| { .clone()
let value = unsafe { &*(uaddr as *const AtomicI32) };
Futex::new(value)
})
.clone(),
)
} }
/// Get lowest free fd /// Get lowest free fd

View File

@ -1,6 +1,5 @@
//! Linux Thread //! Linux Thread
use crate::error::LxError;
use crate::error::SysResult; use crate::error::SysResult;
use crate::process::ProcessExt; use crate::process::ProcessExt;
use crate::signal::{SignalStack, Sigset}; use crate::signal::{SignalStack, Sigset};
@ -22,8 +21,8 @@ pub trait ThreadExt {
/// Get robust list. /// Get robust list.
fn get_robust_list( fn get_robust_list(
&self, &self,
head_ptr: UserOutPtr<UserOutPtr<RobustList>>, _head_ptr: UserOutPtr<UserOutPtr<RobustList>>,
len_ptr: UserOutPtr<usize>, _len_ptr: UserOutPtr<usize>,
) -> SysResult; ) -> SysResult;
/// Set robust list. /// Set robust list.
fn set_robust_list(&self, head: UserInPtr<RobustList>, len: usize); fn set_robust_list(&self, head: UserInPtr<RobustList>, len: usize);
@ -61,14 +60,11 @@ impl ThreadExt for Thread {
fn get_robust_list( fn get_robust_list(
&self, &self,
mut head_ptr: UserOutPtr<UserOutPtr<RobustList>>, mut _head_ptr: UserOutPtr<UserOutPtr<RobustList>>,
mut len_ptr: UserOutPtr<usize>, mut _len_ptr: UserOutPtr<usize>,
) -> SysResult { ) -> SysResult {
// if self.lock_linux().robust_list_len == 0 { _head_ptr = (self.lock_linux().robust_list.as_ptr() as *mut RobustList as usize).into();
// return Err(LxError::EFAULT); _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) Ok(0)
} }
@ -89,7 +85,7 @@ impl CurrentThreadExt for CurrentThread {
info!("exit: do futex {:?} wake 1", clear_child_tid); info!("exit: do futex {:?} wake 1", clear_child_tid);
clear_child_tid.write(0).unwrap(); clear_child_tid.write(0).unwrap();
let uaddr = clear_child_tid.as_ptr() as VirtAddr; 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); futex.wake(1);
} }
self.exit(); self.exit();
@ -100,11 +96,11 @@ impl CurrentThreadExt for CurrentThread {
#[derive(Default)] #[derive(Default)]
pub struct RobustList { pub struct RobustList {
/// head /// head
head: usize, pub head: usize,
/// off /// off
pub off: isize, pub off: isize,
/// pending /// pending
pending: usize, pub pending: usize,
} }
/// Linux specific thread information. /// Linux specific thread information.

View File

@ -15,7 +15,7 @@
//! //!
#![no_std] #![no_std]
// #![deny(warnings, unsafe_code, missing_docs)] #![deny(warnings, unsafe_code, missing_docs)]
#![allow(clippy::upper_case_acronyms)] #![allow(clippy::upper_case_acronyms)]
#[macro_use] #[macro_use]
@ -363,10 +363,6 @@ impl Syscall<'_> {
} }
// process // 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( Sys::EXECVE => self.sys_execve(
self.into_in_userptr(a0).unwrap(), self.into_in_userptr(a0).unwrap(),
self.into_in_userptr(a1).unwrap(), self.into_in_userptr(a1).unwrap(),
@ -379,7 +375,10 @@ impl Syscall<'_> {
.await .await
} }
Sys::SET_TID_ADDRESS => self.sys_set_tid_address(self.into_out_userptr(a0).unwrap()), 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::FUTEX => self.unimplemented("futex", Ok(0)),
Sys::TKILL => self.unimplemented("tkill", Ok(0)), Sys::TKILL => self.unimplemented("tkill", Ok(0)),
Sys::GET_ROBUST_LIST => { Sys::GET_ROBUST_LIST => {
@ -532,6 +531,7 @@ impl Syscall<'_> {
Sys::CHOWN => self.unimplemented("chown", Ok(0)), Sys::CHOWN => self.unimplemented("chown", Ok(0)),
Sys::ARCH_PRCTL => self.sys_arch_prctl(a0 as _, a1), Sys::ARCH_PRCTL => self.sys_arch_prctl(a0 as _, a1),
Sys::TIME => self.sys_time(self.into_out_userptr(a0).unwrap()), 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_CREATE => self.sys_epoll_create(a0),
// Sys::EPOLL_WAIT => self.sys_epoll_wait(a0, a1.into(), a2, a3), // Sys::EPOLL_WAIT => self.sys_epoll_wait(a0, a1.into(), a2, a3),
_ => self.unknown_syscall(sys_type), _ => self.unknown_syscall(sys_type),
@ -540,10 +540,10 @@ impl Syscall<'_> {
#[cfg(target_arch = "riscv64")] #[cfg(target_arch = "riscv64")]
async fn riscv64_syscall(&mut self, sys_type: Sys, args: [usize; 6]) -> SysResult { 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 { match sys_type {
//Sys::OPEN => self.sys_open(a0.into(), a1, a2), //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), _ => self.unknown_syscall(sys_type),
} }
} }

View File

@ -4,10 +4,7 @@ use core::time::Duration;
use futures::pin_mut; use futures::pin_mut;
use kernel_hal::timer::timer_now; use kernel_hal::timer::timer_now;
use linux_object::time::*; use linux_object::time::*;
use zircon_object::{ use zircon_object::task::ThreadState;
task::{IntoResult, ThreadState},
ZxResult,
};
impl Syscall<'_> { impl Syscall<'_> {
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
@ -82,6 +79,8 @@ impl Syscall<'_> {
op: u32, op: u32,
val: u32, val: u32,
timeout_addr: usize, timeout_addr: usize,
uaddr2: usize,
_val3: u32,
) -> SysResult { ) -> SysResult {
if let Err(_) = self.into_inout_userptr::<i32>(uaddr) { if let Err(_) = self.into_inout_userptr::<i32>(uaddr) {
return Err(LxError::EINVAL); return Err(LxError::EINVAL);
@ -89,9 +88,15 @@ impl Syscall<'_> {
let op = FutexFlags::from_bits_truncate(op); let op = FutexFlags::from_bits_truncate(op);
if !op.contains(FutexFlags::PRIVATE) { if !op.contains(FutexFlags::PRIVATE) {
warn!("process-shared futex is unimplemented"); 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::<i32>(uaddr2) {
return Err(LxError::EINVAL);
}
val2 = timeout_addr;
} }
let op = op - FutexFlags::PRIVATE;
let timeout = if op.contains(FutexFlags::WAKE) { let timeout = if op.contains(FutexFlags::WAKE) {
self.into_inout_userptr::<TimeSpec>(0).unwrap() self.into_inout_userptr::<TimeSpec>(0).unwrap()
} else { } else {
@ -102,55 +107,96 @@ impl Syscall<'_> {
} }
}; };
warn!( warn!(
"Futex: uaddr: {:#x}, op: {:x}, val: {}, timeout_ptr: {:x?}", "Futex: uaddr: {:#x}, op: {:x}, val: {}, timeout_ptr: {:x?}, val2: {}",
uaddr, uaddr,
op.bits(), op.bits(),
val, val,
timeout timeout,
val2,
); );
let futex_op = self.linux_process().get_futex(uaddr); let futex = self.linux_process().get_futex(uaddr);
match futex_op { let op = op - FutexFlags::PRIVATE;
Some(futex) => match op { match op {
FutexFlags::WAIT => { FutexFlags::WAIT => {
let timeout = timeout.read_if_not_null()?; let timeout = timeout.read_if_not_null()?;
let duration: Duration = match timeout { let duration: Duration = match timeout {
Some(T) => T.into(), Some(t) => t.into(),
None => Duration::from_secs(0), None => Duration::from_secs(0),
}; };
let into_lxerror = |e: ZxError| match e { let into_lxerror = |e: ZxError| match e {
ZxError::BAD_STATE => LxError::EAGAIN, ZxError::BAD_STATE => LxError::EAGAIN,
e => e.into(), e => e.into(),
}; };
let future = futex.wait(val); let future = futex.wait(val, false, self.thread.id() as i32);
let res = if duration.as_millis() == 0 { let res = if duration.as_millis() == 0 {
future.await future.await
} else { } else {
warn!("duration: {:?}", duration); warn!("duration: {:?}", duration);
pin_mut!(future); pin_mut!(future);
self.thread self.thread
.blocking_run( .blocking_run(
future, future,
ThreadState::BlockedFutex, ThreadState::BlockedFutex,
timer_now() + duration, timer_now() + duration,
None, None,
) )
.await .await
}; };
match res { match res {
Ok(_) => return Ok(0), Ok(_) => return Ok(0),
Err(e) => return Err(into_lxerror(e)), Err(e) => return Err(into_lxerror(e)),
}
} }
FutexFlags::WAKE => { }
let woken_up_count = futex.wake(val as usize); FutexFlags::WAKE => {
Ok(woken_up_count) 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); FutexFlags::REQUEUE => {
Err(LxError::ENOPROTOOPT) 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. /// wakes at most val of the waiters that are waiting on the futex word at the address uaddr.
const WAKE = 1; const WAKE = 1;
/// ///
const REQUEUE = 3;
///
const LOCK_PI = 6; const LOCK_PI = 6;
/// ///
const UNLOCK_PI = 7; const UNLOCK_PI = 7;

View File

@ -297,6 +297,7 @@ impl Syscall<'_> {
Ok(tid as usize) Ok(tid as usize)
} }
/// Get robust list.
pub fn sys_get_robust_list( pub fn sys_get_robust_list(
&self, &self,
pid: i32, pid: i32,
@ -313,6 +314,7 @@ impl Syscall<'_> {
Ok(0) Ok(0)
} }
/// Set robust list.
pub fn sys_set_robust_list(&self, head: UserInPtr<RobustList>, len: usize) -> SysResult { pub fn sys_set_robust_list(&self, head: UserInPtr<RobustList>, len: usize) -> SysResult {
warn!("in sys_set_robust_list"); warn!("in sys_set_robust_list");
if len != size_of::<RobustList>().into() { if len != size_of::<RobustList>().into() {

View File

@ -60,6 +60,7 @@ async fn run_user(thread: CurrentThread) {
} }
info!("back to user: thread id = {}", thread.id()); info!("back to user: thread id = {}", thread.id());
// run // run
trace!("go to user: {:#x?}", ctx); trace!("go to user: {:#x?}", ctx);
ctx.enter_uspace(); ctx.enter_uspace();

View File

@ -62,7 +62,7 @@ pub fn boot_options() -> BootOptions {
#[cfg(feature = "linux")] #[cfg(feature = "linux")]
root_proc: String::from(*options.get("ROOTPROC").unwrap_or(&"/bin/busybox?sh")), root_proc: String::from(*options.get("ROOTPROC").unwrap_or(&"/bin/busybox?sh")),
// root_proc: String::from(*options.get("ROOTPROC") // root_proc: String::from(*options.get("ROOTPROC")
// .unwrap_or(&"/libc-test/functional/pthread_robust.exe")), // .unwrap_or(&"/libc-test/functional/pthread_mutex.exe")),
} }
} }
} }

View File

@ -57,8 +57,13 @@ impl Futex {
/// ///
/// [`wait_with_owner`]: Futex::wait_with_owner /// [`wait_with_owner`]: Futex::wait_with_owner
/// [`wake`]: Futex::wake /// [`wake`]: Futex::wake
pub fn wait(self: &Arc<Self>, current_value: u32) -> impl Future<Output = ZxResult> { pub fn wait(
self.wait_with_owner(current_value, None, None) self: &Arc<Self>,
current_value: u32,
lock_pi: bool,
thread_id: i32,
) -> impl Future<Output = ZxResult> {
self.wait_with_owner(current_value, None, None, lock_pi, thread_id)
} }
/// Wake some number of threads waiting on a futex. /// Wake some number of threads waiting on a futex.
@ -117,12 +122,16 @@ impl Futex {
current_value: u32, current_value: u32,
thread: Option<Arc<Thread>>, thread: Option<Arc<Thread>>,
new_owner: Option<Arc<Thread>>, new_owner: Option<Arc<Thread>>,
lock_pi: bool,
thread_id: i32,
) -> impl Future<Output = ZxResult> { ) -> impl Future<Output = ZxResult> {
#[must_use = "wait does nothing unless polled/`await`-ed"] #[must_use = "wait does nothing unless polled/`await`-ed"]
struct FutexFuture { struct FutexFuture {
waiter: Arc<Waiter>, waiter: Arc<Waiter>,
current_value: u32, current_value: u32,
new_owner: Option<Arc<Thread>>, new_owner: Option<Arc<Thread>>,
lock_pi: bool,
thread_id: i32,
} }
impl Future for FutexFuture { impl Future for FutexFuture {
type Output = ZxResult; type Output = ZxResult;
@ -133,15 +142,29 @@ impl Futex {
if inner.woken { if inner.woken {
// set new owner on success // set new owner on success
inner.futex.inner.lock().set_owner(self.new_owner.clone()); inner.futex.inner.lock().set_owner(self.new_owner.clone());
warn!("Futex Ready!!!");
return Poll::Ready(Ok(())); return Poll::Ready(Ok(()));
} }
// first time? // first time?
if inner.waker.is_none() { if inner.waker.is_none() {
// check value // check value
let value = inner.futex.value.load(Ordering::SeqCst); let value = inner.futex.value.load(Ordering::SeqCst);
if value as u32 != self.current_value { if self.lock_pi {
warn!("Futex BAD STATE"); if value as u32 == 0 {
return Poll::Ready(Err(ZxError::BAD_STATE)); 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 // check new owner
let mut futex = inner.futex.inner.lock(); let mut futex = inner.futex.inner.lock();
@ -182,6 +205,8 @@ impl Futex {
}), }),
current_value, current_value,
new_owner, new_owner,
lock_pi,
thread_id,
} }
} }
@ -224,11 +249,14 @@ impl Futex {
requeue_count: usize, requeue_count: usize,
requeue_futex: &Arc<Futex>, requeue_futex: &Arc<Futex>,
new_requeue_owner: Option<Arc<Thread>>, new_requeue_owner: Option<Arc<Thread>>,
check_value: bool,
) -> ZxResult { ) -> ZxResult {
let mut inner = self.inner.lock(); let mut inner = self.inner.lock();
// check value if check_value {
if self.value.load(Ordering::SeqCst) != current_value { // check value
return Err(ZxError::BAD_STATE); if self.value.load(Ordering::SeqCst) != current_value {
return Err(ZxError::BAD_STATE);
}
} }
// wake // wake
for _ in 0..wake_count { for _ in 0..wake_count {

View File

@ -74,6 +74,7 @@ impl Syscall<'_> {
requeue_count as usize, requeue_count as usize,
&requeue_futex, &requeue_futex,
new_requeue_owner, new_requeue_owner,
true,
)?; )?;
Ok(()) Ok(())
} }