Skip to content

Commit 0f15bf4

Browse files
MivikWyZ0125AsakuraMizu
authored
feat(syscall): add clone3 support (#122)
Co-authored-by: WyZ0125 <iewyzhu@163.com> Co-authored-by: 朝倉水希 <asakuramizu111@gmail.com>
1 parent 31d0ea2 commit 0f15bf4

File tree

8 files changed

+429
-173
lines changed

8 files changed

+429
-173
lines changed

kernel/src/file/pidfd.rs

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,39 +2,84 @@ use alloc::{
22
borrow::Cow,
33
sync::{Arc, Weak},
44
};
5-
use core::task::Context;
5+
use core::{
6+
sync::atomic::{AtomicBool, Ordering},
7+
task::Context,
8+
};
69

710
use axerrno::{AxError, AxResult};
811
use axpoll::{IoEvents, PollSet, Pollable};
912

10-
use crate::{file::FileLike, task::ProcessData};
13+
use crate::{
14+
file::FileLike,
15+
task::{ProcessData, Thread},
16+
};
1117

1218
pub struct PidFd {
1319
proc_data: Weak<ProcessData>,
1420
exit_event: Arc<PollSet>,
21+
thread_exit: Option<Arc<AtomicBool>>,
22+
23+
non_blocking: AtomicBool,
1524
}
1625
impl PidFd {
17-
pub fn new(proc_data: &Arc<ProcessData>) -> Self {
26+
pub fn new_process(proc_data: &Arc<ProcessData>) -> Self {
1827
Self {
1928
proc_data: Arc::downgrade(proc_data),
2029
exit_event: proc_data.exit_event.clone(),
30+
thread_exit: None,
31+
32+
non_blocking: AtomicBool::new(false),
33+
}
34+
}
35+
36+
pub fn new_thread(thread: &Thread) -> Self {
37+
Self {
38+
proc_data: Arc::downgrade(&thread.proc_data),
39+
exit_event: thread.exit_event.clone(),
40+
thread_exit: Some(thread.exit.clone()),
41+
42+
non_blocking: AtomicBool::new(false),
2143
}
2244
}
2345

2446
pub fn process_data(&self) -> AxResult<Arc<ProcessData>> {
47+
// For threads, the pidfd is invalid once the thread exits, even if its
48+
// process is still alive.
49+
if let Some(thread_exit) = &self.thread_exit
50+
&& thread_exit.load(Ordering::Acquire)
51+
{
52+
return Err(AxError::NoSuchProcess);
53+
}
2554
self.proc_data.upgrade().ok_or(AxError::NoSuchProcess)
2655
}
2756
}
2857
impl FileLike for PidFd {
2958
fn path(&self) -> Cow<'_, str> {
3059
"anon_inode:[pidfd]".into()
3160
}
61+
62+
fn set_nonblocking(&self, nonblocking: bool) -> AxResult {
63+
self.non_blocking.store(nonblocking, Ordering::Release);
64+
Ok(())
65+
}
66+
67+
fn nonblocking(&self) -> bool {
68+
self.non_blocking.load(Ordering::Acquire)
69+
}
3270
}
3371

3472
impl Pollable for PidFd {
3573
fn poll(&self) -> IoEvents {
3674
let mut events = IoEvents::empty();
37-
events.set(IoEvents::IN, self.proc_data.strong_count() > 0);
75+
events.set(
76+
IoEvents::IN,
77+
self.proc_data.strong_count() > 0
78+
&& self
79+
.thread_exit
80+
.as_ref()
81+
.is_none_or(|it| !it.load(Ordering::Acquire)),
82+
);
3883
events
3984
}
4085

kernel/src/syscall/fs/pidfd.rs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,34 @@
11
use axerrno::{AxError, AxResult};
2+
use bitflags::bitflags;
23
use starry_signal::SignalInfo;
34

45
use crate::{
56
file::{FD_TABLE, FileLike, PidFd, add_file_like},
67
syscall::signal::make_queue_signal_info,
7-
task::{get_process_data, send_signal_to_process},
8+
task::{AsThread, get_process_data, get_task, send_signal_to_process},
89
};
910

11+
bitflags! {
12+
#[derive(Debug, Clone, Copy, Default)]
13+
pub struct PidFdFlags: u32 {
14+
const NONBLOCK = 2048;
15+
const THREAD = 128;
16+
}
17+
}
18+
1019
pub fn sys_pidfd_open(pid: u32, flags: u32) -> AxResult<isize> {
1120
debug!("sys_pidfd_open <= pid: {pid}, flags: {flags}");
1221

13-
if flags != 0 {
14-
return Err(AxError::InvalidInput);
15-
}
22+
let flags = PidFdFlags::from_bits(flags).ok_or(AxError::InvalidInput)?;
1623

17-
let task = get_process_data(pid)?;
18-
let fd = PidFd::new(&task);
24+
let fd = if flags.contains(PidFdFlags::THREAD) {
25+
PidFd::new_thread(get_task(pid)?.as_thread())
26+
} else {
27+
PidFd::new_process(&get_process_data(pid)?)
28+
};
29+
if flags.contains(PidFdFlags::NONBLOCK) {
30+
fd.set_nonblocking(true)?;
31+
}
1932

2033
fd.add_to_fd_table(true).map(|fd| fd as _)
2134
}

kernel/src/syscall/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,11 @@ pub fn handle_syscall(uctx: &mut UserContext) {
429429
uctx.arg3(),
430430
uctx.arg4(),
431431
),
432+
Sysno::clone3 => sys_clone3(
433+
uctx,
434+
uctx.arg0() as _, // args_ptr
435+
uctx.arg1() as _, // args_size
436+
),
432437
#[cfg(target_arch = "x86_64")]
433438
Sysno::fork => sys_fork(uctx),
434439
Sysno::exit => sys_exit(uctx.arg0() as _),

0 commit comments

Comments
 (0)