forked from rcore-os/zCore
Fix pthread_cond & pthread_tsd & ...
This commit is contained in:
parent
d6687d9a65
commit
767e9dd745
|
@ -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)]
|
||||
|
|
|
@ -241,12 +241,8 @@ impl LinuxProcess {
|
|||
|
||||
/// Get futex object.
|
||||
#[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();
|
||||
// if uaddr == 683520 {
|
||||
// return None;
|
||||
// }
|
||||
Some(
|
||||
inner
|
||||
.futexes
|
||||
.entry(uaddr)
|
||||
|
@ -254,8 +250,7 @@ impl LinuxProcess {
|
|||
let value = unsafe { &*(uaddr as *const AtomicI32) };
|
||||
Futex::new(value)
|
||||
})
|
||||
.clone(),
|
||||
)
|
||||
.clone()
|
||||
}
|
||||
|
||||
/// Get lowest free fd
|
||||
|
|
|
@ -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<UserOutPtr<RobustList>>,
|
||||
len_ptr: UserOutPtr<usize>,
|
||||
_head_ptr: UserOutPtr<UserOutPtr<RobustList>>,
|
||||
_len_ptr: UserOutPtr<usize>,
|
||||
) -> SysResult;
|
||||
/// Set robust list.
|
||||
fn set_robust_list(&self, head: UserInPtr<RobustList>, len: usize);
|
||||
|
@ -61,14 +60,11 @@ impl ThreadExt for Thread {
|
|||
|
||||
fn get_robust_list(
|
||||
&self,
|
||||
mut head_ptr: UserOutPtr<UserOutPtr<RobustList>>,
|
||||
mut len_ptr: UserOutPtr<usize>,
|
||||
mut _head_ptr: UserOutPtr<UserOutPtr<RobustList>>,
|
||||
mut _len_ptr: UserOutPtr<usize>,
|
||||
) -> 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.
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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::<i32>(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::<i32>(uaddr2) {
|
||||
return Err(LxError::EINVAL);
|
||||
}
|
||||
val2 = timeout_addr;
|
||||
}
|
||||
let op = op - FutexFlags::PRIVATE;
|
||||
let timeout = if op.contains(FutexFlags::WAKE) {
|
||||
self.into_inout_userptr::<TimeSpec>(0).unwrap()
|
||||
} else {
|
||||
|
@ -102,26 +107,27 @@ 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 {
|
||||
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(),
|
||||
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 future = futex.wait(val, false, self.thread.id() as i32);
|
||||
let res = if duration.as_millis() == 0 {
|
||||
future.await
|
||||
} else {
|
||||
|
@ -145,12 +151,52 @@ impl Syscall<'_> {
|
|||
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)),
|
||||
}
|
||||
}
|
||||
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)),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
warn!("unsupported futex operation: {:?}", op);
|
||||
Err(LxError::ENOPROTOOPT)
|
||||
}
|
||||
},
|
||||
None => Err(LxError::EAGAIN),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
|
|
@ -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<RobustList>, len: usize) -> SysResult {
|
||||
warn!("in sys_set_robust_list");
|
||||
if len != size_of::<RobustList>().into() {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,8 +57,13 @@ impl Futex {
|
|||
///
|
||||
/// [`wait_with_owner`]: Futex::wait_with_owner
|
||||
/// [`wake`]: Futex::wake
|
||||
pub fn wait(self: &Arc<Self>, current_value: u32) -> impl Future<Output = ZxResult> {
|
||||
self.wait_with_owner(current_value, None, None)
|
||||
pub fn wait(
|
||||
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.
|
||||
|
@ -117,12 +122,16 @@ impl Futex {
|
|||
current_value: u32,
|
||||
thread: Option<Arc<Thread>>,
|
||||
new_owner: Option<Arc<Thread>>,
|
||||
lock_pi: bool,
|
||||
thread_id: i32,
|
||||
) -> impl Future<Output = ZxResult> {
|
||||
#[must_use = "wait does nothing unless polled/`await`-ed"]
|
||||
struct FutexFuture {
|
||||
waiter: Arc<Waiter>,
|
||||
current_value: u32,
|
||||
new_owner: Option<Arc<Thread>>,
|
||||
lock_pi: bool,
|
||||
thread_id: i32,
|
||||
}
|
||||
impl Future for FutexFuture {
|
||||
type Output = ZxResult;
|
||||
|
@ -133,16 +142,30 @@ 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 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");
|
||||
warn!("Futex BAD_STATE!!!");
|
||||
return Poll::Ready(Err(ZxError::BAD_STATE));
|
||||
}
|
||||
}
|
||||
// check new owner
|
||||
let mut futex = inner.futex.inner.lock();
|
||||
if !futex.is_valid_new_owner(&self.new_owner) {
|
||||
|
@ -182,6 +205,8 @@ impl Futex {
|
|||
}),
|
||||
current_value,
|
||||
new_owner,
|
||||
lock_pi,
|
||||
thread_id,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -224,12 +249,15 @@ impl Futex {
|
|||
requeue_count: usize,
|
||||
requeue_futex: &Arc<Futex>,
|
||||
new_requeue_owner: Option<Arc<Thread>>,
|
||||
check_value: bool,
|
||||
) -> ZxResult {
|
||||
let mut inner = self.inner.lock();
|
||||
if check_value {
|
||||
// check value
|
||||
if self.value.load(Ordering::SeqCst) != current_value {
|
||||
return Err(ZxError::BAD_STATE);
|
||||
}
|
||||
}
|
||||
// wake
|
||||
for _ in 0..wake_count {
|
||||
if let Some(waiter) = inner.waiter_queue.pop_front() {
|
||||
|
|
|
@ -74,6 +74,7 @@ impl Syscall<'_> {
|
|||
requeue_count as usize,
|
||||
&requeue_futex,
|
||||
new_requeue_owner,
|
||||
true,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue