mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-22 17:03:23 +00:00
Refactor the implementation
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
50761a5cc5
commit
0d6f6f001c
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -692,6 +692,7 @@ dependencies = [
|
|||||||
"pod",
|
"pod",
|
||||||
"rsdp",
|
"rsdp",
|
||||||
"spin 0.9.8",
|
"spin 0.9.8",
|
||||||
|
"static_assertions",
|
||||||
"tdx-guest",
|
"tdx-guest",
|
||||||
"trapframe",
|
"trapframe",
|
||||||
"volatile",
|
"volatile",
|
||||||
@ -1265,6 +1266,12 @@ version = "1.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "static_assertions"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
|
@ -20,6 +20,7 @@ trapframe = { git = "https://github.com/sdww0/trapframe-rs", rev = "e886763" }
|
|||||||
inherit-methods-macro = { git = "https://github.com/jinzhao-dev/inherit-methods-macro", rev = "98f7e3e" }
|
inherit-methods-macro = { git = "https://github.com/jinzhao-dev/inherit-methods-macro", rev = "98f7e3e" }
|
||||||
tdx-guest = { path = "../libs/tdx-guest", optional = true }
|
tdx-guest = { path = "../libs/tdx-guest", optional = true }
|
||||||
bitvec = { version = "1.0", default-features = false, features = ["alloc"] }
|
bitvec = { version = "1.0", default-features = false, features = ["alloc"] }
|
||||||
|
static_assertions = "1.1.0"
|
||||||
|
|
||||||
[target.x86_64-custom.dependencies]
|
[target.x86_64-custom.dependencies]
|
||||||
x86_64 = "0.14.2"
|
x86_64 = "0.14.2"
|
||||||
|
@ -36,22 +36,28 @@ pub fn init() {
|
|||||||
|
|
||||||
fn timer_callback(trap_frame: &TrapFrame) {
|
fn timer_callback(trap_frame: &TrapFrame) {
|
||||||
let current_ticks = TICK.fetch_add(1, Ordering::SeqCst);
|
let current_ticks = TICK.fetch_add(1, Ordering::SeqCst);
|
||||||
|
|
||||||
|
let callbacks = {
|
||||||
|
let mut callbacks = Vec::new();
|
||||||
let mut timeout_list = TIMEOUT_LIST.get().unwrap().lock();
|
let mut timeout_list = TIMEOUT_LIST.get().unwrap().lock();
|
||||||
let mut callbacks: Vec<Arc<TimerCallback>> = Vec::new();
|
|
||||||
while let Some(t) = timeout_list.peek() {
|
while let Some(t) = timeout_list.peek() {
|
||||||
if t.is_cancelled() {
|
if t.is_cancelled() {
|
||||||
// Just ignore the cancelled callback
|
// Just ignore the cancelled callback
|
||||||
timeout_list.pop();
|
timeout_list.pop();
|
||||||
} else if t.expire_ticks <= current_ticks && t.is_enable() {
|
} else if t.expire_ticks <= current_ticks {
|
||||||
callbacks.push(timeout_list.pop().unwrap());
|
callbacks.push(timeout_list.pop().unwrap());
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
drop(timeout_list);
|
callbacks
|
||||||
|
};
|
||||||
|
|
||||||
for callback in callbacks {
|
for callback in callbacks {
|
||||||
callback.callback.call((&callback,));
|
(callback.callback)(&callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
if APIC_TIMER_CALLBACK.is_completed() {
|
if APIC_TIMER_CALLBACK.is_completed() {
|
||||||
APIC_TIMER_CALLBACK.get().unwrap().call(());
|
APIC_TIMER_CALLBACK.get().unwrap().call(());
|
||||||
}
|
}
|
||||||
@ -63,7 +69,6 @@ pub struct TimerCallback {
|
|||||||
expire_ticks: u64,
|
expire_ticks: u64,
|
||||||
data: Arc<dyn Any + Send + Sync>,
|
data: Arc<dyn Any + Send + Sync>,
|
||||||
callback: Box<dyn Fn(&TimerCallback) + Send + Sync>,
|
callback: Box<dyn Fn(&TimerCallback) + Send + Sync>,
|
||||||
enable: AtomicBool,
|
|
||||||
is_cancelled: AtomicBool,
|
is_cancelled: AtomicBool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +82,6 @@ impl TimerCallback {
|
|||||||
expire_ticks: timeout_ticks,
|
expire_ticks: timeout_ticks,
|
||||||
data,
|
data,
|
||||||
callback,
|
callback,
|
||||||
enable: AtomicBool::new(true),
|
|
||||||
is_cancelled: AtomicBool::new(false),
|
is_cancelled: AtomicBool::new(false),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,20 +90,6 @@ impl TimerCallback {
|
|||||||
&self.data
|
&self.data
|
||||||
}
|
}
|
||||||
|
|
||||||
/// disable this timeout
|
|
||||||
pub fn disable(&self) {
|
|
||||||
self.enable.store(false, Ordering::Release)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// enable this timeout
|
|
||||||
pub fn enable(&self) {
|
|
||||||
self.enable.store(false, Ordering::Release)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_enable(&self) -> bool {
|
|
||||||
self.enable.load(Ordering::Acquire)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Whether the set timeout is reached
|
/// Whether the set timeout is reached
|
||||||
pub fn is_expired(&self) -> bool {
|
pub fn is_expired(&self) -> bool {
|
||||||
let current_tick = TICK.load(Ordering::Acquire);
|
let current_tick = TICK.load(Ordering::Acquire);
|
||||||
|
@ -7,5 +7,4 @@ pub enum Error {
|
|||||||
AccessDenied,
|
AccessDenied,
|
||||||
IoError,
|
IoError,
|
||||||
NotEnoughResources,
|
NotEnoughResources,
|
||||||
TimeOut,
|
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate static_assertions;
|
||||||
|
|
||||||
pub mod arch;
|
pub mod arch;
|
||||||
pub mod boot;
|
pub mod boot;
|
||||||
|
@ -26,7 +26,7 @@ impl<T> Mutex<T> {
|
|||||||
///
|
///
|
||||||
/// This method runs in a block way until the mutex can be acquired.
|
/// This method runs in a block way until the mutex can be acquired.
|
||||||
pub fn lock(&self) -> MutexGuard<T> {
|
pub fn lock(&self) -> MutexGuard<T> {
|
||||||
self.queue.wait_until(|| self.try_lock(), None).unwrap()
|
self.queue.wait_until(|| self.try_lock())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Try Acquire the mutex immedidately.
|
/// Try Acquire the mutex immedidately.
|
||||||
|
@ -35,12 +35,12 @@ impl<T> RwMutex<T> {
|
|||||||
|
|
||||||
/// Acquire a read mutex, and if there is a writer, this thread will sleep in the wait queue.
|
/// Acquire a read mutex, and if there is a writer, this thread will sleep in the wait queue.
|
||||||
pub fn read(&self) -> RwMutexReadGuard<T> {
|
pub fn read(&self) -> RwMutexReadGuard<T> {
|
||||||
self.queue.wait_until(|| self.try_read(), None).unwrap()
|
self.queue.wait_until(|| self.try_read())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Acquire a write mutex, and if there is another writer or other readers, this thread will sleep in the wait queue.
|
/// Acquire a write mutex, and if there is another writer or other readers, this thread will sleep in the wait queue.
|
||||||
pub fn write(&self) -> RwMutexWriteGuard<T> {
|
pub fn write(&self) -> RwMutexWriteGuard<T> {
|
||||||
self.queue.wait_until(|| self.try_write(), None).unwrap()
|
self.queue.wait_until(|| self.try_write())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Try acquire a read mutex and return immediately if it fails.
|
/// Try acquire a read mutex and return immediately if it fails.
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
use super::SpinLock;
|
use super::SpinLock;
|
||||||
use crate::arch::timer::add_timeout_list;
|
use crate::arch::timer::add_timeout_list;
|
||||||
use crate::config::TIMER_FREQ;
|
use crate::config::TIMER_FREQ;
|
||||||
use crate::error::Error;
|
|
||||||
use crate::prelude::*;
|
|
||||||
use alloc::{collections::VecDeque, sync::Arc};
|
use alloc::{collections::VecDeque, sync::Arc};
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
@ -37,15 +35,29 @@ impl WaitQueue {
|
|||||||
///
|
///
|
||||||
/// By taking a condition closure, his wait-wakeup mechanism becomes
|
/// By taking a condition closure, his wait-wakeup mechanism becomes
|
||||||
/// more efficient and robust.
|
/// more efficient and robust.
|
||||||
///
|
pub fn wait_until<F, R>(&self, cond: F) -> R
|
||||||
/// The only error result is Error::TIMEOUT, which means the timeout is readched
|
where
|
||||||
/// and the condition returns false.
|
F: FnMut() -> Option<R>,
|
||||||
pub fn wait_until<F, R>(&self, mut cond: F, timeout: Option<&Duration>) -> Result<R>
|
{
|
||||||
|
self.do_wait(cond, None).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wait until some condition returns Some(_), or a given timeout is reached. If
|
||||||
|
/// the condition does not becomes Some(_) before the timeout is reached, the
|
||||||
|
/// function will return None.
|
||||||
|
pub fn wait_until_or_timeout<F, R>(&self, cond: F, timeout: &Duration) -> Option<R>
|
||||||
|
where
|
||||||
|
F: FnMut() -> Option<R>,
|
||||||
|
{
|
||||||
|
self.do_wait(cond, Some(timeout))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_wait<F, R>(&self, mut cond: F, timeout: Option<&Duration>) -> Option<R>
|
||||||
where
|
where
|
||||||
F: FnMut() -> Option<R>,
|
F: FnMut() -> Option<R>,
|
||||||
{
|
{
|
||||||
if let Some(res) = cond() {
|
if let Some(res) = cond() {
|
||||||
return Ok(res);
|
return Some(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
let waiter = Arc::new(Waiter::new());
|
let waiter = Arc::new(Waiter::new());
|
||||||
@ -53,12 +65,12 @@ impl WaitQueue {
|
|||||||
|
|
||||||
let timer_callback = timeout.map(|timeout| {
|
let timer_callback = timeout.map(|timeout| {
|
||||||
let remaining_ticks = {
|
let remaining_ticks = {
|
||||||
let ms_per_tick = 1000 / TIMER_FREQ;
|
|
||||||
|
|
||||||
// FIXME: We currently require 1000 to be a multiple of TIMER_FREQ, but
|
// FIXME: We currently require 1000 to be a multiple of TIMER_FREQ, but
|
||||||
// this may not hold true in the future, because TIMER_FREQ can be greater
|
// this may not hold true in the future, because TIMER_FREQ can be greater
|
||||||
// than 1000. Then, the code need to be refactored.
|
// than 1000. Then, the code need to be refactored.
|
||||||
debug_assert!(ms_per_tick * TIMER_FREQ == 1000);
|
const_assert!(1000 % TIMER_FREQ == 0);
|
||||||
|
|
||||||
|
let ms_per_tick = 1000 / TIMER_FREQ;
|
||||||
|
|
||||||
// The ticks should be equal to or greater than timeout
|
// The ticks should be equal to or greater than timeout
|
||||||
(timeout.as_millis() as u64 + ms_per_tick - 1) / ms_per_tick
|
(timeout.as_millis() as u64 + ms_per_tick - 1) / ms_per_tick
|
||||||
@ -81,11 +93,11 @@ impl WaitQueue {
|
|||||||
timer_callback.cancel();
|
timer_callback.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(res);
|
return Some(res);
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(ref timer_callback) = timer_callback && timer_callback.is_expired() {
|
if let Some(ref timer_callback) = timer_callback && timer_callback.is_expired() {
|
||||||
return Err(Error::TimeOut);
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
waiter.wait();
|
waiter.wait();
|
||||||
|
@ -60,7 +60,7 @@ impl Timer {
|
|||||||
let mut lock = self.inner.lock_irq_disabled();
|
let mut lock = self.inner.lock_irq_disabled();
|
||||||
match &lock.timer_callback {
|
match &lock.timer_callback {
|
||||||
Some(callback) => {
|
Some(callback) => {
|
||||||
callback.disable();
|
callback.cancel();
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
@ -94,7 +94,7 @@ impl Timer {
|
|||||||
pub fn clear(&self) {
|
pub fn clear(&self) {
|
||||||
let mut lock = self.inner.lock_irq_disabled();
|
let mut lock = self.inner.lock_irq_disabled();
|
||||||
if let Some(callback) = &lock.timer_callback {
|
if let Some(callback) = &lock.timer_callback {
|
||||||
callback.disable();
|
callback.cancel();
|
||||||
}
|
}
|
||||||
lock.timeout_tick = 0;
|
lock.timeout_tick = 0;
|
||||||
lock.start_tick = 0;
|
lock.start_tick = 0;
|
||||||
|
@ -2,11 +2,13 @@ use alloc::format;
|
|||||||
use ringbuf::{ring_buffer::RbBase, HeapRb, Rb};
|
use ringbuf::{ring_buffer::RbBase, HeapRb, Rb};
|
||||||
|
|
||||||
use crate::device::tty::line_discipline::LineDiscipline;
|
use crate::device::tty::line_discipline::LineDiscipline;
|
||||||
|
use crate::events::IoEvents;
|
||||||
use crate::fs::device::{Device, DeviceId, DeviceType};
|
use crate::fs::device::{Device, DeviceId, DeviceType};
|
||||||
use crate::fs::file_handle::FileLike;
|
use crate::fs::file_handle::FileLike;
|
||||||
use crate::fs::fs_resolver::FsPath;
|
use crate::fs::fs_resolver::FsPath;
|
||||||
use crate::fs::utils::{AccessMode, Inode, InodeMode, IoEvents, IoctlCmd, Pollee, Poller};
|
use crate::fs::utils::{AccessMode, Inode, InodeMode, IoctlCmd};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::process::signal::{Pollee, Poller};
|
||||||
use crate::util::{read_val_from_user, write_val_to_user};
|
use crate::util::{read_val_from_user, write_val_to_user};
|
||||||
|
|
||||||
const PTS_DIR: &str = "/dev/pts";
|
const PTS_DIR: &str = "/dev/pts";
|
||||||
@ -106,7 +108,7 @@ impl FileLike for PtyMaster {
|
|||||||
if events.is_empty() {
|
if events.is_empty() {
|
||||||
drop(input);
|
drop(input);
|
||||||
// FIXME: deal with pty read timeout
|
// FIXME: deal with pty read timeout
|
||||||
poller.wait_interruptible(None)?;
|
poller.wait()?;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::fs::utils::{IoEvents, Pollee, Poller};
|
use crate::events::IoEvents;
|
||||||
use crate::process::signal::constants::{SIGINT, SIGQUIT};
|
use crate::process::signal::constants::{SIGINT, SIGQUIT};
|
||||||
|
use crate::process::signal::{Pollee, Poller};
|
||||||
use crate::process::ProcessGroup;
|
use crate::process::ProcessGroup;
|
||||||
use crate::thread::work_queue::work_item::WorkItem;
|
use crate::thread::work_queue::work_item::WorkItem;
|
||||||
use crate::thread::work_queue::{submit_work_item, WorkPriority};
|
use crate::thread::work_queue::{submit_work_item, WorkPriority};
|
||||||
@ -253,7 +254,7 @@ impl LineDiscipline {
|
|||||||
let revents = self.pollee.poll(IoEvents::IN, need_poller);
|
let revents = self.pollee.poll(IoEvents::IN, need_poller);
|
||||||
if revents.is_empty() {
|
if revents.is_empty() {
|
||||||
// FIXME: deal with ldisc read timeout
|
// FIXME: deal with ldisc read timeout
|
||||||
poller.as_ref().unwrap().wait_interruptible(None)?;
|
poller.as_ref().unwrap().wait()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,10 @@ use spin::Once;
|
|||||||
use self::driver::TtyDriver;
|
use self::driver::TtyDriver;
|
||||||
use self::line_discipline::LineDiscipline;
|
use self::line_discipline::LineDiscipline;
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::fs::utils::{IoEvents, IoctlCmd, Poller};
|
use crate::events::IoEvents;
|
||||||
|
use crate::fs::utils::IoctlCmd;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::process::signal::Poller;
|
||||||
use crate::process::{process_table, ProcessGroup};
|
use crate::process::{process_table, ProcessGroup};
|
||||||
use crate::util::{read_val_from_user, write_val_to_user};
|
use crate::util::{read_val_from_user, write_val_to_user};
|
||||||
|
|
||||||
|
@ -187,7 +187,6 @@ impl From<jinux_frame::Error> for Error {
|
|||||||
jinux_frame::Error::IoError => Error::new(Errno::EIO),
|
jinux_frame::Error::IoError => Error::new(Errno::EIO),
|
||||||
jinux_frame::Error::NotEnoughResources => Error::new(Errno::EBUSY),
|
jinux_frame::Error::NotEnoughResources => Error::new(Errno::EBUSY),
|
||||||
jinux_frame::Error::PageFault => Error::new(Errno::EFAULT),
|
jinux_frame::Error::PageFault => Error::new(Errno::EFAULT),
|
||||||
jinux_frame::Error::TimeOut => Error::new(Errno::ETIME),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::events::{Events, EventsFilter};
|
use super::{Events, EventsFilter};
|
||||||
|
|
||||||
crate::bitflags! {
|
crate::bitflags! {
|
||||||
pub struct IoEvents: u32 {
|
pub struct IoEvents: u32 {
|
@ -1,8 +1,10 @@
|
|||||||
#[allow(clippy::module_inception)]
|
#[allow(clippy::module_inception)]
|
||||||
mod events;
|
mod events;
|
||||||
|
mod io_events;
|
||||||
mod observer;
|
mod observer;
|
||||||
mod subject;
|
mod subject;
|
||||||
|
|
||||||
pub use self::events::{Events, EventsFilter};
|
pub use self::events::{Events, EventsFilter};
|
||||||
pub use self::observer::Observer;
|
pub use self::observer::Observer;
|
||||||
pub use self::subject::Subject;
|
pub use self::subject::Subject;
|
||||||
|
pub use io_events::IoEvents;
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
|
use crate::events::IoEvents;
|
||||||
use crate::fs::fs_resolver::{FsPath, FsResolver};
|
use crate::fs::fs_resolver::{FsPath, FsResolver};
|
||||||
use crate::fs::utils::Dentry;
|
use crate::fs::utils::Dentry;
|
||||||
use crate::fs::utils::{InodeMode, InodeType, IoEvents, IoctlCmd, Poller};
|
use crate::fs::utils::{InodeMode, InodeType, IoctlCmd};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::process::signal::Poller;
|
||||||
|
|
||||||
/// The abstract of device
|
/// The abstract of device
|
||||||
pub trait Device: Sync + Send {
|
pub trait Device: Sync + Send {
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
use crate::{fs::file_handle::FileLike, prelude::*};
|
use crate::events::IoEvents;
|
||||||
|
use crate::fs::file_handle::FileLike;
|
||||||
|
use crate::prelude::*;
|
||||||
|
use crate::process::signal::Poller;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::fs::device::{Device, DeviceId, DeviceType};
|
use crate::fs::device::{Device, DeviceId, DeviceType};
|
||||||
use crate::fs::utils::{
|
use crate::fs::utils::{
|
||||||
DirentVisitor, FileSystem, FsFlags, Inode, InodeMode, InodeType, IoEvents, IoctlCmd, Metadata,
|
DirentVisitor, FileSystem, FsFlags, Inode, InodeMode, InodeType, IoctlCmd, Metadata,
|
||||||
Poller, SuperBlock, NAME_MAX,
|
SuperBlock, NAME_MAX,
|
||||||
};
|
};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
|
use crate::events::IoEvents;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::process::signal::Poller;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
use crate::events::Observer;
|
use crate::events::{IoEvents, Observer};
|
||||||
use crate::fs::file_handle::FileLike;
|
use crate::fs::file_handle::FileLike;
|
||||||
use crate::fs::file_table::{FdEvents, FileDescripter};
|
use crate::fs::file_table::{FdEvents, FileDescripter};
|
||||||
use crate::fs::utils::{IoEvents, IoctlCmd, Pollee, Poller};
|
use crate::fs::utils::IoctlCmd;
|
||||||
|
use crate::process::signal::{Pollee, Poller};
|
||||||
|
|
||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
@ -191,7 +192,11 @@ impl EpollFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
poller.as_ref().unwrap().wait_interruptible(timeout)?;
|
if let Some(timeout) = timeout {
|
||||||
|
poller.as_ref().unwrap().wait_timeout(timeout)?;
|
||||||
|
} else {
|
||||||
|
poller.as_ref().unwrap().wait()?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use super::file_table::FileDescripter;
|
use super::file_table::FileDescripter;
|
||||||
use super::utils::IoEvents;
|
use crate::events::IoEvents;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
mod epoll_file;
|
mod epoll_file;
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
//! Opend File Handle
|
//! Opend File Handle
|
||||||
|
|
||||||
use crate::events::Observer;
|
use crate::events::{IoEvents, Observer};
|
||||||
use crate::fs::utils::{AccessMode, IoEvents, IoctlCmd, Metadata, Poller, SeekFrom, StatusFlags};
|
use crate::fs::utils::{AccessMode, IoctlCmd, Metadata, SeekFrom, StatusFlags};
|
||||||
use crate::net::socket::Socket;
|
use crate::net::socket::Socket;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::process::signal::Poller;
|
||||||
|
|
||||||
use core::any::Any;
|
use core::any::Any;
|
||||||
|
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
|
use crate::events::IoEvents;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::process::signal::Poller;
|
||||||
use jinux_rights::{Rights, TRights};
|
use jinux_rights::{Rights, TRights};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -7,8 +7,7 @@ use core::sync::atomic::{AtomicU32, Ordering};
|
|||||||
|
|
||||||
use crate::fs::file_handle::FileLike;
|
use crate::fs::file_handle::FileLike;
|
||||||
use crate::fs::utils::{
|
use crate::fs::utils::{
|
||||||
AccessMode, Dentry, DirentVisitor, InodeType, IoEvents, IoctlCmd, Metadata, Poller, SeekFrom,
|
AccessMode, Dentry, DirentVisitor, InodeType, IoctlCmd, Metadata, SeekFrom, StatusFlags,
|
||||||
StatusFlags,
|
|
||||||
};
|
};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use jinux_rights::Rights;
|
use jinux_rights::Rights;
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
use crate::events::Observer;
|
use crate::events::{IoEvents, Observer};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::process::signal::Poller;
|
||||||
|
|
||||||
use super::file_handle::FileLike;
|
use super::file_handle::FileLike;
|
||||||
use super::utils::{
|
use super::utils::{AccessMode, Consumer, InodeMode, InodeType, Metadata, Producer, StatusFlags};
|
||||||
AccessMode, Consumer, InodeMode, InodeType, IoEvents, Metadata, Poller, Producer, StatusFlags,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct PipeReader {
|
pub struct PipeReader {
|
||||||
consumer: Consumer<u8>,
|
consumer: Consumer<u8>,
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
|
use crate::events::IoEvents;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::process::signal::Poller;
|
||||||
use alloc::str;
|
use alloc::str;
|
||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||||
@ -10,8 +12,8 @@ use jinux_util::slot_vec::SlotVec;
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::fs::device::Device;
|
use crate::fs::device::Device;
|
||||||
use crate::fs::utils::{
|
use crate::fs::utils::{
|
||||||
DirentVisitor, FileSystem, FsFlags, Inode, InodeMode, InodeType, IoEvents, IoctlCmd, Metadata,
|
DirentVisitor, FileSystem, FsFlags, Inode, InodeMode, InodeType, IoctlCmd, Metadata,
|
||||||
Poller, SuperBlock, NAME_MAX,
|
SuperBlock, NAME_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A volatile file system whose data and metadata exists only in memory.
|
/// A volatile file system whose data and metadata exists only in memory.
|
||||||
|
@ -2,11 +2,13 @@ use core::sync::atomic::{AtomicBool, AtomicU32, Ordering};
|
|||||||
use jinux_rights_proc::require;
|
use jinux_rights_proc::require;
|
||||||
use ringbuf::{HeapConsumer as HeapRbConsumer, HeapProducer as HeapRbProducer, HeapRb};
|
use ringbuf::{HeapConsumer as HeapRbConsumer, HeapProducer as HeapRbProducer, HeapRb};
|
||||||
|
|
||||||
|
use crate::events::IoEvents;
|
||||||
use crate::events::Observer;
|
use crate::events::Observer;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::process::signal::{Pollee, Poller};
|
||||||
use jinux_rights::{Read, ReadOp, TRights, Write, WriteOp};
|
use jinux_rights::{Read, ReadOp, TRights, Write, WriteOp};
|
||||||
|
|
||||||
use super::{IoEvents, Pollee, Poller, StatusFlags};
|
use super::StatusFlags;
|
||||||
|
|
||||||
/// A unidirectional communication channel, intended to implement IPC, e.g., pipe,
|
/// A unidirectional communication channel, intended to implement IPC, e.g., pipe,
|
||||||
/// unix domain sockets, etc.
|
/// unix domain sockets, etc.
|
||||||
@ -153,7 +155,7 @@ impl<T: Copy> Producer<T> {
|
|||||||
let events = self.poll(mask, Some(&poller));
|
let events = self.poll(mask, Some(&poller));
|
||||||
if events.is_empty() {
|
if events.is_empty() {
|
||||||
// FIXME: should channel deal with timeout?
|
// FIXME: should channel deal with timeout?
|
||||||
poller.wait_interruptible(None)?;
|
poller.wait()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -242,7 +244,7 @@ impl<T: Copy> Consumer<T> {
|
|||||||
let events = self.poll(mask, Some(&poller));
|
let events = self.poll(mask, Some(&poller));
|
||||||
if events.is_empty() {
|
if events.is_empty() {
|
||||||
// FIXME: should channel have timeout?
|
// FIXME: should channel have timeout?
|
||||||
poller.wait_interruptible(None)?;
|
poller.wait()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,11 @@ use core::any::Any;
|
|||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
use jinux_frame::vm::VmFrame;
|
use jinux_frame::vm::VmFrame;
|
||||||
|
|
||||||
use super::{DirentVisitor, FileSystem, IoEvents, IoctlCmd, Poller, SuperBlock};
|
use super::{DirentVisitor, FileSystem, IoctlCmd, SuperBlock};
|
||||||
|
use crate::events::IoEvents;
|
||||||
use crate::fs::device::{Device, DeviceType};
|
use crate::fs::device::{Device, DeviceType};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::process::signal::Poller;
|
||||||
|
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
|
@ -9,11 +9,9 @@ pub use direntry_vec::DirEntryVecExt;
|
|||||||
pub use file_creation_mask::FileCreationMask;
|
pub use file_creation_mask::FileCreationMask;
|
||||||
pub use fs::{FileSystem, FsFlags, SuperBlock};
|
pub use fs::{FileSystem, FsFlags, SuperBlock};
|
||||||
pub use inode::{Inode, InodeMode, InodeType, Metadata};
|
pub use inode::{Inode, InodeMode, InodeType, Metadata};
|
||||||
pub use io_events::IoEvents;
|
|
||||||
pub use ioctl::IoctlCmd;
|
pub use ioctl::IoctlCmd;
|
||||||
pub use mount::MountNode;
|
pub use mount::MountNode;
|
||||||
pub use page_cache::PageCache;
|
pub use page_cache::PageCache;
|
||||||
pub use poll::{Pollee, Poller};
|
|
||||||
pub use status_flags::StatusFlags;
|
pub use status_flags::StatusFlags;
|
||||||
pub use vnode::{Vnode, VnodeWriter};
|
pub use vnode::{Vnode, VnodeWriter};
|
||||||
|
|
||||||
@ -26,11 +24,9 @@ mod direntry_vec;
|
|||||||
mod file_creation_mask;
|
mod file_creation_mask;
|
||||||
mod fs;
|
mod fs;
|
||||||
mod inode;
|
mod inode;
|
||||||
mod io_events;
|
|
||||||
mod ioctl;
|
mod ioctl;
|
||||||
mod mount;
|
mod mount;
|
||||||
mod page_cache;
|
mod page_cache;
|
||||||
mod poll;
|
|
||||||
mod status_flags;
|
mod status_flags;
|
||||||
mod vnode;
|
mod vnode;
|
||||||
|
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
use super::{
|
use super::{
|
||||||
DirentVisitor, FileSystem, FsFlags, Inode, InodeMode, InodeType, IoEvents, IoctlCmd, Metadata,
|
DirentVisitor, FileSystem, FsFlags, Inode, InodeMode, InodeType, IoctlCmd, Metadata, PageCache,
|
||||||
PageCache, Poller,
|
|
||||||
};
|
};
|
||||||
|
use crate::events::IoEvents;
|
||||||
use crate::fs::device::Device;
|
use crate::fs::device::Device;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::process::signal::Poller;
|
||||||
use crate::vm::vmo::Vmo;
|
use crate::vm::vmo::Vmo;
|
||||||
|
|
||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use crate::{
|
use crate::events::IoEvents;
|
||||||
fs::utils::{IoEvents, Pollee, Poller},
|
use crate::prelude::*;
|
||||||
prelude::*,
|
use crate::process::signal::{Pollee, Poller};
|
||||||
};
|
|
||||||
|
|
||||||
use super::Iface;
|
use super::Iface;
|
||||||
use super::{IpAddress, IpEndpoint};
|
use super::{IpAddress, IpEndpoint};
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
|
||||||
|
use crate::events::IoEvents;
|
||||||
use crate::fs::utils::StatusFlags;
|
use crate::fs::utils::StatusFlags;
|
||||||
use crate::net::iface::IpEndpoint;
|
use crate::net::iface::IpEndpoint;
|
||||||
|
|
||||||
|
use crate::process::signal::Poller;
|
||||||
use crate::{
|
use crate::{
|
||||||
fs::{
|
fs::file_handle::FileLike,
|
||||||
file_handle::FileLike,
|
|
||||||
utils::{IoEvents, Poller},
|
|
||||||
},
|
|
||||||
net::{
|
net::{
|
||||||
iface::{AnyBoundSocket, AnyUnboundSocket, RawUdpSocket},
|
iface::{AnyBoundSocket, AnyUnboundSocket, RawUdpSocket},
|
||||||
poll_ifaces,
|
poll_ifaces,
|
||||||
@ -259,7 +258,7 @@ impl Socket for DatagramSocket {
|
|||||||
return_errno_with_message!(Errno::EAGAIN, "try to receive again");
|
return_errno_with_message!(Errno::EAGAIN, "try to receive again");
|
||||||
}
|
}
|
||||||
// FIXME: deal with recvfrom timeout
|
// FIXME: deal with recvfrom timeout
|
||||||
poller.wait_interruptible(None)?;
|
poller.wait()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
|
||||||
|
use crate::events::IoEvents;
|
||||||
use crate::net::iface::IpEndpoint;
|
use crate::net::iface::IpEndpoint;
|
||||||
|
use crate::process::signal::Poller;
|
||||||
use crate::{
|
use crate::{
|
||||||
fs::utils::{IoEvents, Poller},
|
|
||||||
net::{
|
net::{
|
||||||
iface::{AnyBoundSocket, RawTcpSocket},
|
iface::{AnyBoundSocket, RawTcpSocket},
|
||||||
poll_ifaces,
|
poll_ifaces,
|
||||||
@ -58,7 +59,7 @@ impl ConnectedStream {
|
|||||||
return_errno_with_message!(Errno::EAGAIN, "try to recv again");
|
return_errno_with_message!(Errno::EAGAIN, "try to recv again");
|
||||||
}
|
}
|
||||||
// FIXME: deal with receive timeout
|
// FIXME: deal with receive timeout
|
||||||
poller.wait_interruptible(None)?;
|
poller.wait()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
|
||||||
use crate::fs::utils::{IoEvents, Poller};
|
use crate::events::IoEvents;
|
||||||
use crate::net::iface::Iface;
|
use crate::net::iface::Iface;
|
||||||
use crate::net::iface::IpEndpoint;
|
use crate::net::iface::IpEndpoint;
|
||||||
use crate::net::iface::{AnyBoundSocket, AnyUnboundSocket};
|
use crate::net::iface::{AnyBoundSocket, AnyUnboundSocket};
|
||||||
@ -8,6 +8,7 @@ use crate::net::poll_ifaces;
|
|||||||
use crate::net::socket::ip::always_some::AlwaysSome;
|
use crate::net::socket::ip::always_some::AlwaysSome;
|
||||||
use crate::net::socket::ip::common::{bind_socket, get_ephemeral_endpoint};
|
use crate::net::socket::ip::common::{bind_socket, get_ephemeral_endpoint};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::process::signal::Poller;
|
||||||
|
|
||||||
pub struct InitStream {
|
pub struct InitStream {
|
||||||
inner: RwLock<Inner>,
|
inner: RwLock<Inner>,
|
||||||
@ -152,7 +153,7 @@ impl InitStream {
|
|||||||
return_errno_with_message!(Errno::EAGAIN, "try connect again");
|
return_errno_with_message!(Errno::EAGAIN, "try connect again");
|
||||||
} else {
|
} else {
|
||||||
// FIXME: deal with connecting timeout
|
// FIXME: deal with connecting timeout
|
||||||
poller.wait_interruptible(None)?;
|
poller.wait()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
|
||||||
|
use crate::events::IoEvents;
|
||||||
use crate::net::iface::{AnyUnboundSocket, BindPortConfig, IpEndpoint};
|
use crate::net::iface::{AnyUnboundSocket, BindPortConfig, IpEndpoint};
|
||||||
|
|
||||||
use crate::fs::utils::{IoEvents, Poller};
|
|
||||||
use crate::net::iface::{AnyBoundSocket, RawTcpSocket};
|
use crate::net::iface::{AnyBoundSocket, RawTcpSocket};
|
||||||
|
use crate::process::signal::Poller;
|
||||||
use crate::{net::poll_ifaces, prelude::*};
|
use crate::{net::poll_ifaces, prelude::*};
|
||||||
|
|
||||||
use super::connected::ConnectedStream;
|
use super::connected::ConnectedStream;
|
||||||
@ -46,7 +47,7 @@ impl ListenStream {
|
|||||||
return_errno_with_message!(Errno::EAGAIN, "try accept again");
|
return_errno_with_message!(Errno::EAGAIN, "try accept again");
|
||||||
}
|
}
|
||||||
// FIXME: deal with accept timeout
|
// FIXME: deal with accept timeout
|
||||||
poller.wait_interruptible(None)?;
|
poller.wait()?;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
use crate::fs::{
|
use crate::events::IoEvents;
|
||||||
file_handle::FileLike,
|
use crate::fs::{file_handle::FileLike, utils::StatusFlags};
|
||||||
utils::{IoEvents, Poller, StatusFlags},
|
|
||||||
};
|
|
||||||
use crate::net::socket::{
|
use crate::net::socket::{
|
||||||
util::{
|
util::{
|
||||||
send_recv_flags::SendRecvFlags, shutdown_cmd::SockShutdownCmd,
|
send_recv_flags::SendRecvFlags, shutdown_cmd::SockShutdownCmd,
|
||||||
@ -10,6 +8,7 @@ use crate::net::socket::{
|
|||||||
Socket,
|
Socket,
|
||||||
};
|
};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::process::signal::Poller;
|
||||||
|
|
||||||
use self::{connected::ConnectedStream, init::InitStream, listen::ListenStream};
|
use self::{connected::ConnectedStream, init::InitStream, listen::ListenStream};
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
use super::endpoint::Endpoint;
|
use super::endpoint::Endpoint;
|
||||||
use crate::fs::utils::{IoEvents, Poller};
|
use crate::events::IoEvents;
|
||||||
use crate::net::socket::{unix::addr::UnixSocketAddrBound, SockShutdownCmd};
|
use crate::net::socket::{unix::addr::UnixSocketAddrBound, SockShutdownCmd};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::process::signal::Poller;
|
||||||
|
|
||||||
pub(super) struct Connected {
|
pub(super) struct Connected {
|
||||||
local_endpoint: Arc<Endpoint>,
|
local_endpoint: Arc<Endpoint>,
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
use crate::events::IoEvents;
|
||||||
|
use crate::process::signal::Poller;
|
||||||
use crate::{
|
use crate::{
|
||||||
fs::utils::{Channel, Consumer, IoEvents, Poller, Producer, StatusFlags},
|
fs::utils::{Channel, Consumer, Producer, StatusFlags},
|
||||||
net::socket::{unix::addr::UnixSocketAddrBound, SockShutdownCmd},
|
net::socket::{unix::addr::UnixSocketAddrBound, SockShutdownCmd},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
|
||||||
|
use crate::events::IoEvents;
|
||||||
use crate::fs::fs_resolver::{split_path, FsPath};
|
use crate::fs::fs_resolver::{split_path, FsPath};
|
||||||
use crate::fs::utils::{Dentry, InodeMode, InodeType, IoEvents, Pollee, Poller};
|
use crate::fs::utils::{Dentry, InodeMode, InodeType};
|
||||||
use crate::net::socket::unix::addr::{UnixSocketAddr, UnixSocketAddrBound};
|
use crate::net::socket::unix::addr::{UnixSocketAddr, UnixSocketAddrBound};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::process::signal::{Pollee, Poller};
|
||||||
|
|
||||||
use super::connected::Connected;
|
use super::connected::Connected;
|
||||||
use super::endpoint::Endpoint;
|
use super::endpoint::Endpoint;
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
use super::{connected::Connected, endpoint::Endpoint, UnixStreamSocket};
|
use super::{connected::Connected, endpoint::Endpoint, UnixStreamSocket};
|
||||||
|
use crate::events::IoEvents;
|
||||||
use crate::fs::file_handle::FileLike;
|
use crate::fs::file_handle::FileLike;
|
||||||
use crate::fs::utils::{Dentry, Inode, IoEvents, Pollee, Poller};
|
use crate::fs::utils::{Dentry, Inode};
|
||||||
use crate::net::socket::unix::addr::{UnixSocketAddr, UnixSocketAddrBound};
|
use crate::net::socket::unix::addr::{UnixSocketAddr, UnixSocketAddrBound};
|
||||||
use crate::net::socket::SocketAddr;
|
use crate::net::socket::SocketAddr;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::process::signal::{Pollee, Poller};
|
||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
use keyable_arc::KeyableWeak;
|
use keyable_arc::KeyableWeak;
|
||||||
|
|
||||||
@ -133,7 +135,7 @@ impl BacklogTable {
|
|||||||
|
|
||||||
// FIXME: deal with accept timeout
|
// FIXME: deal with accept timeout
|
||||||
if events.is_empty() {
|
if events.is_empty() {
|
||||||
poller.wait_interruptible(None)?;
|
poller.wait()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
|
use crate::events::IoEvents;
|
||||||
use crate::fs::file_handle::FileLike;
|
use crate::fs::file_handle::FileLike;
|
||||||
use crate::fs::fs_resolver::FsPath;
|
use crate::fs::fs_resolver::FsPath;
|
||||||
use crate::fs::utils::{Dentry, InodeType, IoEvents, Poller, StatusFlags};
|
use crate::fs::utils::{Dentry, InodeType, StatusFlags};
|
||||||
use crate::net::socket::unix::addr::UnixSocketAddrBound;
|
use crate::net::socket::unix::addr::UnixSocketAddrBound;
|
||||||
use crate::net::socket::unix::UnixSocketAddr;
|
use crate::net::socket::unix::UnixSocketAddr;
|
||||||
use crate::net::socket::util::send_recv_flags::SendRecvFlags;
|
use crate::net::socket::util::send_recv_flags::SendRecvFlags;
|
||||||
use crate::net::socket::util::sockaddr::SocketAddr;
|
use crate::net::socket::util::sockaddr::SocketAddr;
|
||||||
use crate::net::socket::{SockShutdownCmd, Socket};
|
use crate::net::socket::{SockShutdownCmd, Socket};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::process::signal::Poller;
|
||||||
|
|
||||||
use super::connected::Connected;
|
use super::connected::Connected;
|
||||||
use super::endpoint::Endpoint;
|
use super::endpoint::Endpoint;
|
||||||
|
@ -48,7 +48,7 @@ pub fn do_exit_group(term_status: TermStatus) {
|
|||||||
// Notify parent
|
// Notify parent
|
||||||
let signal = Box::new(KernelSignal::new(SIGCHLD));
|
let signal = Box::new(KernelSignal::new(SIGCHLD));
|
||||||
parent.enqueue_signal(signal);
|
parent.enqueue_signal(signal);
|
||||||
parent.waiting_children().wake_all();
|
parent.children_pauser().resume_all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ impl PosixThread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_pending_signal(&self) -> bool {
|
pub fn has_pending_signal(&self) -> bool {
|
||||||
self.sig_queues.lock().is_empty()
|
!self.sig_queues.lock().is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enqueue_signal(&self, signal: Box<dyn Signal>) {
|
pub fn enqueue_signal(&self, signal: Box<dyn Signal>) {
|
||||||
|
@ -5,11 +5,12 @@ use super::process_group::ProcessGroup;
|
|||||||
use super::process_vm::user_heap::UserHeap;
|
use super::process_vm::user_heap::UserHeap;
|
||||||
use super::process_vm::ProcessVm;
|
use super::process_vm::ProcessVm;
|
||||||
use super::rlimit::ResourceLimits;
|
use super::rlimit::ResourceLimits;
|
||||||
|
use super::signal::constants::SIGCHLD;
|
||||||
use super::signal::sig_disposition::SigDispositions;
|
use super::signal::sig_disposition::SigDispositions;
|
||||||
use super::signal::sig_mask::SigMask;
|
use super::signal::sig_mask::SigMask;
|
||||||
use super::signal::sig_queues::SigQueues;
|
use super::signal::sig_queues::SigQueues;
|
||||||
use super::signal::signals::Signal;
|
use super::signal::signals::Signal;
|
||||||
use super::signal::{SigEvents, SigEventsFilter};
|
use super::signal::{Pauser, SigEvents, SigEventsFilter};
|
||||||
use super::status::ProcessStatus;
|
use super::status::ProcessStatus;
|
||||||
use super::{process_table, TermStatus};
|
use super::{process_table, TermStatus};
|
||||||
use crate::device::tty::get_n_tty;
|
use crate::device::tty::get_n_tty;
|
||||||
@ -20,7 +21,6 @@ use crate::fs::utils::FileCreationMask;
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::thread::{allocate_tid, Thread};
|
use crate::thread::{allocate_tid, Thread};
|
||||||
use crate::vm::vmar::Vmar;
|
use crate::vm::vmar::Vmar;
|
||||||
use jinux_frame::sync::WaitQueue;
|
|
||||||
use jinux_rights::Full;
|
use jinux_rights::Full;
|
||||||
|
|
||||||
pub use builder::ProcessBuilder;
|
pub use builder::ProcessBuilder;
|
||||||
@ -35,8 +35,8 @@ pub struct Process {
|
|||||||
pid: Pid,
|
pid: Pid,
|
||||||
|
|
||||||
process_vm: ProcessVm,
|
process_vm: ProcessVm,
|
||||||
/// wait for child status changed
|
/// Wait for child status changed
|
||||||
waiting_children: WaitQueue,
|
children_pauser: Arc<Pauser>,
|
||||||
|
|
||||||
// Mutable Part
|
// Mutable Part
|
||||||
/// The executable path.
|
/// The executable path.
|
||||||
@ -82,12 +82,20 @@ impl Process {
|
|||||||
sig_dispositions: Arc<Mutex<SigDispositions>>,
|
sig_dispositions: Arc<Mutex<SigDispositions>>,
|
||||||
resource_limits: ResourceLimits,
|
resource_limits: ResourceLimits,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
let children_pauser = {
|
||||||
|
let mut sigset = SigMask::new_full();
|
||||||
|
// SIGCHID does not interrupt pauser. Child process will
|
||||||
|
// resume paused parent when doing exit.
|
||||||
|
sigset.remove_signal(SIGCHLD);
|
||||||
|
Pauser::new_with_sigset(sigset)
|
||||||
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
pid,
|
pid,
|
||||||
threads: Mutex::new(threads),
|
threads: Mutex::new(threads),
|
||||||
executable_path: RwLock::new(executable_path),
|
executable_path: RwLock::new(executable_path),
|
||||||
process_vm,
|
process_vm,
|
||||||
waiting_children: WaitQueue::new(),
|
children_pauser,
|
||||||
status: Mutex::new(ProcessStatus::Uninit),
|
status: Mutex::new(ProcessStatus::Uninit),
|
||||||
parent: Mutex::new(parent),
|
parent: Mutex::new(parent),
|
||||||
children: Mutex::new(BTreeMap::new()),
|
children: Mutex::new(BTreeMap::new()),
|
||||||
@ -190,8 +198,8 @@ impl Process {
|
|||||||
&self.children
|
&self.children
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn waiting_children(&self) -> &WaitQueue {
|
pub fn children_pauser(&self) -> &Arc<Pauser> {
|
||||||
&self.waiting_children
|
&self.children_pauser
|
||||||
}
|
}
|
||||||
|
|
||||||
// *********** Process group ***********
|
// *********** Process group ***********
|
||||||
@ -252,7 +260,7 @@ impl Process {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_pending_signal(&self) -> bool {
|
pub fn has_pending_signal(&self) -> bool {
|
||||||
self.sig_queues.lock().is_empty()
|
!self.sig_queues.lock().is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enqueue_signal(&self, signal: Box<dyn Signal>) {
|
pub fn enqueue_signal(&self, signal: Box<dyn Signal>) {
|
||||||
|
@ -1,11 +1,5 @@
|
|||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
use crate::events::{Events, EventsFilter};
|
||||||
use core::time::Duration;
|
|
||||||
|
|
||||||
use jinux_frame::sync::WaitQueue;
|
|
||||||
|
|
||||||
use crate::events::{Events, EventsFilter, Observer};
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::process::posix_thread::PosixThreadExt;
|
|
||||||
|
|
||||||
use super::sig_mask::SigMask;
|
use super::sig_mask::SigMask;
|
||||||
use super::sig_num::SigNum;
|
use super::sig_num::SigNum;
|
||||||
@ -35,101 +29,3 @@ impl EventsFilter<SigEvents> for SigEventsFilter {
|
|||||||
self.0.contains(event.0)
|
self.0.contains(event.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SigQueueObserver {
|
|
||||||
wait_queue: WaitQueue,
|
|
||||||
mask: SigMask,
|
|
||||||
is_interrupted: AtomicBool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SigQueueObserver {
|
|
||||||
pub fn new(mask: SigMask) -> Arc<Self> {
|
|
||||||
let wait_queue = WaitQueue::new();
|
|
||||||
Arc::new(Self {
|
|
||||||
wait_queue,
|
|
||||||
mask,
|
|
||||||
is_interrupted: AtomicBool::new(false),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Wait until cond() returns Some(_).
|
|
||||||
///
|
|
||||||
/// If some signal is caught before cond() returns Some(_), it will returns EINTR.
|
|
||||||
pub fn wait_until_interruptible<F, R>(
|
|
||||||
self: &Arc<Self>,
|
|
||||||
mut cond: F,
|
|
||||||
timeout: Option<&Duration>,
|
|
||||||
) -> Result<R>
|
|
||||||
where
|
|
||||||
F: FnMut() -> Option<R>,
|
|
||||||
{
|
|
||||||
self.is_interrupted.store(false, Ordering::Release);
|
|
||||||
|
|
||||||
// Register observers on sigqueues
|
|
||||||
|
|
||||||
let observer = Arc::downgrade(self) as Weak<dyn Observer<SigEvents>>;
|
|
||||||
let filter = SigEventsFilter::new(self.mask);
|
|
||||||
|
|
||||||
let current = current!();
|
|
||||||
current.register_sigqueue_observer(observer.clone(), filter);
|
|
||||||
|
|
||||||
let current_thread = current_thread!();
|
|
||||||
let posix_thread = current_thread.as_posix_thread().unwrap();
|
|
||||||
posix_thread.register_sigqueue_observer(observer.clone(), filter);
|
|
||||||
|
|
||||||
// Some signal may come before we register observer, so we do another check here.
|
|
||||||
if posix_thread.has_pending_signal() || current.has_pending_signal() {
|
|
||||||
self.is_interrupted.store(true, Ordering::Release);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Res<R> {
|
|
||||||
Ok(R),
|
|
||||||
Interrupted,
|
|
||||||
}
|
|
||||||
|
|
||||||
let res = self.wait_queue.wait_until(
|
|
||||||
|| {
|
|
||||||
if let Some(res) = cond() {
|
|
||||||
return Some(Res::Ok(res));
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.is_interrupted.load(Ordering::Acquire) {
|
|
||||||
return Some(Res::Interrupted);
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
},
|
|
||||||
timeout,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
current.unregiser_sigqueue_observer(&observer);
|
|
||||||
posix_thread.unregiser_sigqueue_observer(&observer);
|
|
||||||
|
|
||||||
match res {
|
|
||||||
Res::Ok(r) => Ok(r),
|
|
||||||
Res::Interrupted => return_errno_with_message!(Errno::EINTR, "interrupted by signal"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn wait_until_uninterruptible<F, R>(&self, cond: F, timeout: Option<&Duration>) -> Result<R>
|
|
||||||
where
|
|
||||||
F: FnMut() -> Option<R>,
|
|
||||||
{
|
|
||||||
Ok(self.wait_queue.wait_until(cond, timeout)?)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn wake_all(&self) {
|
|
||||||
self.wait_queue.wake_all();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn wake_one(&self) {
|
|
||||||
self.wait_queue.wake_one();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Observer<SigEvents> for SigQueueObserver {
|
|
||||||
fn on_events(&self, events: &SigEvents) {
|
|
||||||
self.is_interrupted.store(true, Ordering::Release);
|
|
||||||
self.wait_queue.wake_all();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
pub mod c_types;
|
pub mod c_types;
|
||||||
pub mod constants;
|
pub mod constants;
|
||||||
mod events;
|
mod events;
|
||||||
|
mod pauser;
|
||||||
|
mod poll;
|
||||||
pub mod sig_action;
|
pub mod sig_action;
|
||||||
pub mod sig_disposition;
|
pub mod sig_disposition;
|
||||||
pub mod sig_mask;
|
pub mod sig_mask;
|
||||||
@ -8,7 +10,9 @@ pub mod sig_num;
|
|||||||
pub mod sig_queues;
|
pub mod sig_queues;
|
||||||
pub mod signals;
|
pub mod signals;
|
||||||
|
|
||||||
pub use events::{SigEvents, SigEventsFilter, SigQueueObserver};
|
pub use events::{SigEvents, SigEventsFilter};
|
||||||
|
pub use pauser::Pauser;
|
||||||
|
pub use poll::{Pollee, Poller};
|
||||||
|
|
||||||
use core::mem;
|
use core::mem;
|
||||||
|
|
||||||
|
176
services/libs/jinux-std/src/process/signal/pauser.rs
Normal file
176
services/libs/jinux-std/src/process/signal/pauser.rs
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
use core::time::Duration;
|
||||||
|
|
||||||
|
use jinux_frame::sync::WaitQueue;
|
||||||
|
|
||||||
|
use crate::events::Observer;
|
||||||
|
use crate::prelude::*;
|
||||||
|
use crate::process::posix_thread::PosixThreadExt;
|
||||||
|
|
||||||
|
use super::sig_mask::SigMask;
|
||||||
|
use super::{SigEvents, SigEventsFilter};
|
||||||
|
|
||||||
|
/// A `Pauser` allows pausing the execution of the current thread until certain conditions are reached.
|
||||||
|
///
|
||||||
|
/// Behind the scene, `Pauser` is implemented with `Waiter` and `WaiterQueue`.
|
||||||
|
/// But unlike its `Waiter` relatives, `Pauser` is aware of POSIX signals:
|
||||||
|
/// if a thread paused by a `Pauser` receives a signal, then the thread will resume its execution.
|
||||||
|
///
|
||||||
|
/// Another key difference is that `Pauser` combines the two roles of `Waiter` and `WaiterQueue`
|
||||||
|
/// into one. Both putting the current thread to sleep and waking it up can be done through the
|
||||||
|
/// same `Pauser` object, using its `pause`- and `resume`-family methods.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// Here is how the current thread can be put to sleep with a `Pauser`.
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// let pauser = Pauser::new(SigMask::new_full());
|
||||||
|
/// // Pause the execution of the current thread until a user-given condition is met
|
||||||
|
/// // or the current thread is interrupted by a signal.
|
||||||
|
/// let res = pauser.pause_until(|| {
|
||||||
|
/// if cond() {
|
||||||
|
/// Some(())
|
||||||
|
/// } else {
|
||||||
|
/// None
|
||||||
|
/// }
|
||||||
|
/// });
|
||||||
|
/// match res {
|
||||||
|
/// Ok(_) => {
|
||||||
|
/// // The user-given condition is met...
|
||||||
|
/// }
|
||||||
|
/// Err(EINTR) => {
|
||||||
|
/// // A signal is received...
|
||||||
|
/// }
|
||||||
|
/// _ => unreachable!()
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Let's assume that another thread has access to the same object of `Arc<Pauser>`.
|
||||||
|
/// Then, this second thread can resume the execution of the first thread
|
||||||
|
/// even when `cond()` does not return `true`.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// pauser.resume_all();
|
||||||
|
/// ```
|
||||||
|
pub struct Pauser {
|
||||||
|
wait_queue: WaitQueue,
|
||||||
|
sigset: SigMask,
|
||||||
|
is_interrupted: AtomicBool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pauser {
|
||||||
|
/// Create a new `Pauser`. The `Pauser` can be interrupted by all signals.
|
||||||
|
pub fn new() -> Arc<Self> {
|
||||||
|
Self::new_with_sigset(SigMask::new_full())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new `Pauser`, the `Pauser` can only be interrupted by signals
|
||||||
|
/// in `sigset`.
|
||||||
|
pub fn new_with_sigset(sigset: SigMask) -> Arc<Self> {
|
||||||
|
let wait_queue = WaitQueue::new();
|
||||||
|
Arc::new(Self {
|
||||||
|
wait_queue,
|
||||||
|
sigset,
|
||||||
|
is_interrupted: AtomicBool::new(false),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Pause the execution of current thread until the `cond` is met ( i.e., `cond()`
|
||||||
|
/// returns `Some(_)` ), or some signal is received by current thread or process.
|
||||||
|
///
|
||||||
|
/// If some signal is received before `cond` is met, this method will returns `Err(EINTR)`.
|
||||||
|
pub fn pause_until<F, R>(self: &Arc<Self>, cond: F) -> Result<R>
|
||||||
|
where
|
||||||
|
F: FnMut() -> Option<R>,
|
||||||
|
{
|
||||||
|
self.do_pause(cond, None)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Pause the execution of current thread until the `cond` is met ( i.e., `cond()` returns
|
||||||
|
/// `Some(_)` ), or some signal is received by current thread or process, or the given
|
||||||
|
/// `timeout` is expired.
|
||||||
|
///
|
||||||
|
/// If `timeout` is expired before the `cond` is met or some signal is received,
|
||||||
|
/// it will returns `Err(ETIME)`.
|
||||||
|
pub fn pause_until_or_timeout<F, R>(self: &Arc<Self>, cond: F, timeout: &Duration) -> Result<R>
|
||||||
|
where
|
||||||
|
F: FnMut() -> Option<R>,
|
||||||
|
{
|
||||||
|
self.do_pause(cond, Some(timeout))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_pause<F, R>(self: &Arc<Self>, mut cond: F, timeout: Option<&Duration>) -> Result<R>
|
||||||
|
where
|
||||||
|
F: FnMut() -> Option<R>,
|
||||||
|
{
|
||||||
|
self.is_interrupted.store(false, Ordering::Release);
|
||||||
|
|
||||||
|
// Register observers on sigqueues
|
||||||
|
|
||||||
|
let observer = Arc::downgrade(self) as Weak<dyn Observer<SigEvents>>;
|
||||||
|
let filter = SigEventsFilter::new(self.sigset);
|
||||||
|
|
||||||
|
let current = current!();
|
||||||
|
current.register_sigqueue_observer(observer.clone(), filter);
|
||||||
|
|
||||||
|
let current_thread = current_thread!();
|
||||||
|
let posix_thread = current_thread.as_posix_thread().unwrap();
|
||||||
|
posix_thread.register_sigqueue_observer(observer.clone(), filter);
|
||||||
|
|
||||||
|
// Some signal may come before we register observer, so we do another check here.
|
||||||
|
if posix_thread.has_pending_signal() || current.has_pending_signal() {
|
||||||
|
self.is_interrupted.store(true, Ordering::Release);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Res<R> {
|
||||||
|
Ok(R),
|
||||||
|
Interrupted,
|
||||||
|
}
|
||||||
|
|
||||||
|
let cond = || {
|
||||||
|
if let Some(res) = cond() {
|
||||||
|
return Some(Res::Ok(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.is_interrupted.load(Ordering::Acquire) {
|
||||||
|
return Some(Res::Interrupted);
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let res = if let Some(timeout) = timeout {
|
||||||
|
self.wait_queue
|
||||||
|
.wait_until_or_timeout(cond, timeout)
|
||||||
|
.ok_or_else(|| Error::with_message(Errno::ETIME, "timeout is reached"))?
|
||||||
|
} else {
|
||||||
|
self.wait_queue.wait_until(cond)
|
||||||
|
};
|
||||||
|
|
||||||
|
current.unregiser_sigqueue_observer(&observer);
|
||||||
|
posix_thread.unregiser_sigqueue_observer(&observer);
|
||||||
|
|
||||||
|
match res {
|
||||||
|
Res::Ok(r) => Ok(r),
|
||||||
|
Res::Interrupted => return_errno_with_message!(Errno::EINTR, "interrupted by signal"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resume all paused threads on this pauser.
|
||||||
|
pub fn resume_all(&self) {
|
||||||
|
self.wait_queue.wake_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resume one paused thread on this pauser.
|
||||||
|
pub fn resume_one(&self) {
|
||||||
|
self.wait_queue.wake_one();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Observer<SigEvents> for Pauser {
|
||||||
|
fn on_events(&self, events: &SigEvents) {
|
||||||
|
self.is_interrupted.store(true, Ordering::Release);
|
||||||
|
self.wait_queue.wake_all();
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,7 @@
|
|||||||
use super::IoEvents;
|
use crate::events::IoEvents;
|
||||||
use crate::events::{Observer, Subject};
|
use crate::events::{Observer, Subject};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::process::signal::sig_mask::SigMask;
|
use crate::process::signal::Pauser;
|
||||||
use crate::process::signal::SigQueueObserver;
|
|
||||||
|
|
||||||
use core::sync::atomic::{AtomicU32, AtomicUsize, Ordering};
|
use core::sync::atomic::{AtomicU32, AtomicUsize, Ordering};
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
@ -160,13 +159,15 @@ impl Poller {
|
|||||||
|
|
||||||
/// Wait until there are any interesting events happen since last `wait`. The `wait`
|
/// Wait until there are any interesting events happen since last `wait`. The `wait`
|
||||||
/// can be interrupted by signal.
|
/// can be interrupted by signal.
|
||||||
pub fn wait_interruptible(&self, timeout: Option<&Duration>) -> Result<()> {
|
pub fn wait(&self) -> Result<()> {
|
||||||
self.inner.event_counter.read_interruptible(timeout)?;
|
self.inner.event_counter.read(None)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn wait_uninterruptible(&self, timeout: Option<&Duration>) -> Result<()> {
|
/// Wait until there are any interesting events happen since last `wait` or a given timeout
|
||||||
self.inner.event_counter.read_uninterruptible(timeout)?;
|
/// is expired. This method can be interrupted by signal.
|
||||||
|
pub fn wait_timeout(&self, timeout: &Duration) -> Result<()> {
|
||||||
|
self.inner.event_counter.read(Some(timeout))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,53 +201,38 @@ impl Drop for Poller {
|
|||||||
/// A counter for wait and wakeup.
|
/// A counter for wait and wakeup.
|
||||||
struct EventCounter {
|
struct EventCounter {
|
||||||
counter: AtomicUsize,
|
counter: AtomicUsize,
|
||||||
observer: Arc<SigQueueObserver>,
|
pauser: Arc<Pauser>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventCounter {
|
impl EventCounter {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let observer = {
|
let pauser = Pauser::new();
|
||||||
// FIXME: choose the suitable mask
|
|
||||||
let mask = SigMask::new_full();
|
|
||||||
SigQueueObserver::new(mask)
|
|
||||||
};
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
counter: AtomicUsize::new(0),
|
counter: AtomicUsize::new(0),
|
||||||
observer,
|
pauser,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_interruptible(&self, timeout: Option<&Duration>) -> Result<usize> {
|
pub fn read(&self, timeout: Option<&Duration>) -> Result<usize> {
|
||||||
self.observer.wait_until_interruptible(
|
let cond = || {
|
||||||
|| {
|
|
||||||
let val = self.counter.swap(0, Ordering::Relaxed);
|
let val = self.counter.swap(0, Ordering::Relaxed);
|
||||||
if val > 0 {
|
if val > 0 {
|
||||||
Some(val)
|
Some(val)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
timeout,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read_uninterruptible(&self, timeout: Option<&Duration>) -> Result<usize> {
|
if let Some(timeout) = timeout {
|
||||||
self.observer.wait_until_uninterruptible(
|
self.pauser.pause_until_or_timeout(cond, timeout)
|
||||||
|| {
|
|
||||||
let val = self.counter.swap(0, Ordering::Relaxed);
|
|
||||||
if val > 0 {
|
|
||||||
Some(val)
|
|
||||||
} else {
|
} else {
|
||||||
None
|
self.pauser.pause_until(cond)
|
||||||
}
|
}
|
||||||
},
|
|
||||||
timeout,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(&self) {
|
pub fn write(&self) {
|
||||||
self.counter.fetch_add(1, Ordering::Relaxed);
|
self.counter.fetch_add(1, Ordering::Relaxed);
|
||||||
self.observer.wake_one();
|
self.pauser.resume_one();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -26,8 +26,7 @@ pub fn wait_child_exit(
|
|||||||
wait_options: WaitOptions,
|
wait_options: WaitOptions,
|
||||||
) -> Result<(Pid, ExitCode)> {
|
) -> Result<(Pid, ExitCode)> {
|
||||||
let current = current!();
|
let current = current!();
|
||||||
let (pid, exit_code) = current.waiting_children().wait_until(
|
let (pid, exit_code) = current.children_pauser().pause_until(|| {
|
||||||
|| {
|
|
||||||
let unwaited_children = current
|
let unwaited_children = current
|
||||||
.children()
|
.children()
|
||||||
.lock()
|
.lock()
|
||||||
@ -68,9 +67,7 @@ pub fn wait_child_exit(
|
|||||||
|
|
||||||
// wait
|
// wait
|
||||||
None
|
None
|
||||||
},
|
})??;
|
||||||
None,
|
|
||||||
)??;
|
|
||||||
|
|
||||||
Ok((pid, exit_code as _))
|
Ok((pid, exit_code as _))
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,7 @@ use super::SyscallReturn;
|
|||||||
use super::SYS_CLOCK_NANOSLEEP;
|
use super::SYS_CLOCK_NANOSLEEP;
|
||||||
use crate::log_syscall_entry;
|
use crate::log_syscall_entry;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::process::signal::sig_mask::SigMask;
|
use crate::process::signal::Pauser;
|
||||||
use crate::process::signal::SigQueueObserver;
|
|
||||||
use crate::time::{clockid_t, now_as_duration, timespec_t, ClockID, TIMER_ABSTIME};
|
use crate::time::{clockid_t, now_as_duration, timespec_t, ClockID, TIMER_ABSTIME};
|
||||||
use crate::util::{read_val_from_user, write_val_to_user};
|
use crate::util::{read_val_from_user, write_val_to_user};
|
||||||
|
|
||||||
@ -40,14 +39,11 @@ pub fn sys_clock_nanosleep(
|
|||||||
|
|
||||||
let start_time = now_as_duration(&clock_id)?;
|
let start_time = now_as_duration(&clock_id)?;
|
||||||
|
|
||||||
let sigqueue_observer = {
|
|
||||||
// FIXME: sleeping thread can only be interrupted by signals that will call signal handler or terminate
|
// FIXME: sleeping thread can only be interrupted by signals that will call signal handler or terminate
|
||||||
// current process. i.e., the signals that should be ignored will not interrupt sleeping thread.
|
// current process. i.e., the signals that should be ignored will not interrupt sleeping thread.
|
||||||
let sigmask = SigMask::new_full();
|
let pauser = Pauser::new();
|
||||||
SigQueueObserver::new(sigmask)
|
|
||||||
};
|
|
||||||
|
|
||||||
let res = sigqueue_observer.wait_until_interruptible(|| None, Some(&duration));
|
let res = pauser.pause_until_or_timeout(|| None, &duration);
|
||||||
match res {
|
match res {
|
||||||
Err(e) if e.error() == Errno::ETIME => Ok(SyscallReturn::Return(0)),
|
Err(e) if e.error() == Errno::ETIME => Ok(SyscallReturn::Return(0)),
|
||||||
Err(e) if e.error() == Errno::EINTR => {
|
Err(e) if e.error() == Errno::EINTR => {
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
|
|
||||||
|
use crate::events::IoEvents;
|
||||||
use crate::fs::epoll::{EpollCtl, EpollEvent, EpollFile, EpollFlags};
|
use crate::fs::epoll::{EpollCtl, EpollEvent, EpollFile, EpollFlags};
|
||||||
use crate::fs::file_table::FileDescripter;
|
use crate::fs::file_table::FileDescripter;
|
||||||
use crate::fs::utils::{CreationFlags, IoEvents};
|
use crate::fs::utils::CreationFlags;
|
||||||
use crate::log_syscall_entry;
|
use crate::log_syscall_entry;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::util::{read_val_from_user, write_val_to_user};
|
use crate::util::{read_val_from_user, write_val_to_user};
|
||||||
|
@ -1,21 +1,17 @@
|
|||||||
use crate::log_syscall_entry;
|
use crate::log_syscall_entry;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::process::signal::sig_mask::SigMask;
|
use crate::process::signal::Pauser;
|
||||||
use crate::process::signal::SigQueueObserver;
|
|
||||||
|
|
||||||
use super::{SyscallReturn, SYS_PAUSE};
|
use super::{SyscallReturn, SYS_PAUSE};
|
||||||
|
|
||||||
pub fn sys_pause() -> Result<SyscallReturn> {
|
pub fn sys_pause() -> Result<SyscallReturn> {
|
||||||
log_syscall_entry!(SYS_PAUSE);
|
log_syscall_entry!(SYS_PAUSE);
|
||||||
|
|
||||||
let sigqueue_observer = {
|
|
||||||
// FIXME: like sleep, paused thread can only be interrupted by signals that will call signal
|
// FIXME: like sleep, paused thread can only be interrupted by signals that will call signal
|
||||||
// handler or terminate current process
|
// handler or terminate current process
|
||||||
let sigmask = SigMask::new_full();
|
let pauser = Pauser::new();
|
||||||
SigQueueObserver::new(sigmask)
|
|
||||||
};
|
|
||||||
|
|
||||||
sigqueue_observer.wait_until_interruptible(|| None, None)?;
|
pauser.pause_until(|| None)?;
|
||||||
|
|
||||||
unreachable!("[Internal Error] pause should always return EINTR");
|
unreachable!("[Internal Error] pause should always return EINTR");
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
|
|
||||||
|
use crate::events::IoEvents;
|
||||||
use crate::fs::file_table::FileDescripter;
|
use crate::fs::file_table::FileDescripter;
|
||||||
use crate::fs::utils::{IoEvents, Poller};
|
|
||||||
use crate::log_syscall_entry;
|
use crate::log_syscall_entry;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::process::signal::Poller;
|
||||||
use crate::util::{read_val_from_user, write_val_to_user};
|
use crate::util::{read_val_from_user, write_val_to_user};
|
||||||
|
|
||||||
use super::SyscallReturn;
|
use super::SyscallReturn;
|
||||||
@ -91,7 +92,11 @@ pub fn do_poll(poll_fds: &[PollFd], timeout: Option<Duration>) -> Result<usize>
|
|||||||
return Ok(0);
|
return Ok(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
poller.wait_interruptible(timeout.as_ref())?;
|
if let Some(timeout) = timeout.as_ref() {
|
||||||
|
poller.wait_timeout(timeout)?;
|
||||||
|
} else {
|
||||||
|
poller.wait()?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
|
|
||||||
|
use crate::events::IoEvents;
|
||||||
use crate::fs::file_table::FileDescripter;
|
use crate::fs::file_table::FileDescripter;
|
||||||
use crate::fs::utils::IoEvents;
|
|
||||||
use crate::log_syscall_entry;
|
use crate::log_syscall_entry;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::time::timeval_t;
|
use crate::time::timeval_t;
|
||||||
|
Reference in New Issue
Block a user