Skip to content

Commit b4e4c02

Browse files
GodonesBrahmaMantra
authored andcommitted
feat: 增加tokio异步运行时支持 (DragonOS-Community#894)
* fix the EventFdFlags error * feat: support tokio (Single thread version) Fix deadlock issue on closing file. Add function for PipeInode and EventFdInode.
1 parent 25a0da9 commit b4e4c02

File tree

9 files changed

+192
-14
lines changed

9 files changed

+192
-14
lines changed

kernel/src/filesystem/eventfd.rs

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ use crate::filesystem::vfs::syscall::ModeType;
33
use crate::filesystem::vfs::{FilePrivateData, FileSystem, FileType, IndexNode, Metadata};
44
use crate::libs::spinlock::{SpinLock, SpinLockGuard};
55
use crate::libs::wait_queue::WaitQueue;
6-
use crate::net::event_poll::EPollEventType;
6+
use crate::net::event_poll::{EPollEventType, EPollItem, EventPoll, KernelIoctlData};
77
use crate::process::ProcessManager;
88
use crate::syscall::Syscall;
9+
use alloc::collections::LinkedList;
910
use alloc::string::String;
1011
use alloc::sync::Arc;
12+
use alloc::sync::Weak;
1113
use alloc::vec::Vec;
1214
use core::any::Any;
1315
use ida::IdAllocator;
@@ -19,14 +21,14 @@ bitflags! {
1921
pub struct EventFdFlags: u32{
2022
/// Provide semaphore-like semantics for reads from the new
2123
/// file descriptor.
22-
const EFD_SEMAPHORE = 1;
24+
const EFD_SEMAPHORE = 0o1;
2325
/// Set the close-on-exec (FD_CLOEXEC) flag on the new file
2426
/// descriptor
25-
const EFD_CLOEXEC = 2;
27+
const EFD_CLOEXEC = 0o2000000;
2628
/// Set the O_NONBLOCK file status flag on the open file
2729
/// description (see open(2)) referred to by the new file
2830
/// descriptor
29-
const EFD_NONBLOCK = 4;
31+
const EFD_NONBLOCK = 0o0004000;
3032
}
3133
}
3234

@@ -48,15 +50,31 @@ impl EventFd {
4850
pub struct EventFdInode {
4951
eventfd: SpinLock<EventFd>,
5052
wait_queue: WaitQueue,
53+
epitems: SpinLock<LinkedList<Arc<EPollItem>>>,
5154
}
5255

5356
impl EventFdInode {
5457
pub fn new(eventfd: EventFd) -> Self {
5558
EventFdInode {
5659
eventfd: SpinLock::new(eventfd),
5760
wait_queue: WaitQueue::default(),
61+
epitems: SpinLock::new(LinkedList::new()),
5862
}
5963
}
64+
pub fn remove_epoll(&self, epoll: &Weak<SpinLock<EventPoll>>) -> Result<(), SystemError> {
65+
let is_remove = !self
66+
.epitems
67+
.lock_irqsave()
68+
.extract_if(|x| x.epoll().ptr_eq(epoll))
69+
.collect::<Vec<_>>()
70+
.is_empty();
71+
72+
if is_remove {
73+
return Ok(());
74+
}
75+
76+
Err(SystemError::ENOENT)
77+
}
6078
}
6179

6280
impl IndexNode for EventFdInode {
@@ -85,7 +103,7 @@ impl IndexNode for EventFdInode {
85103
_offset: usize,
86104
len: usize,
87105
buf: &mut [u8],
88-
_data: SpinLockGuard<FilePrivateData>,
106+
data: SpinLockGuard<FilePrivateData>,
89107
) -> Result<usize, SystemError> {
90108
if len < 8 {
91109
return Err(SystemError::EINVAL);
@@ -115,6 +133,11 @@ impl IndexNode for EventFdInode {
115133
}
116134
let val_bytes = val.to_ne_bytes();
117135
buf[..8].copy_from_slice(&val_bytes);
136+
137+
let pollflag = EPollEventType::from_bits_truncate(self.poll(&data)? as u32);
138+
// 唤醒epoll中等待的进程
139+
EventPoll::wakeup_epoll(&self.epitems, pollflag)?;
140+
118141
return Ok(8);
119142
}
120143

@@ -131,7 +154,7 @@ impl IndexNode for EventFdInode {
131154
_offset: usize,
132155
len: usize,
133156
buf: &[u8],
134-
_data: SpinLockGuard<FilePrivateData>,
157+
data: SpinLockGuard<FilePrivateData>,
135158
) -> Result<usize, SystemError> {
136159
if len < 8 {
137160
return Err(SystemError::EINVAL);
@@ -157,6 +180,10 @@ impl IndexNode for EventFdInode {
157180
let mut eventfd = self.eventfd.lock();
158181
eventfd.count += val;
159182
self.wait_queue.wakeup_all(None);
183+
184+
let pollflag = EPollEventType::from_bits_truncate(self.poll(&data)? as u32);
185+
// 唤醒epoll中等待的进程
186+
EventPoll::wakeup_epoll(&self.epitems, pollflag)?;
160187
return Ok(8);
161188
}
162189

@@ -187,6 +214,18 @@ impl IndexNode for EventFdInode {
187214
fn resize(&self, _len: usize) -> Result<(), SystemError> {
188215
Ok(())
189216
}
217+
fn kernel_ioctl(
218+
&self,
219+
arg: Arc<dyn KernelIoctlData>,
220+
_data: &FilePrivateData,
221+
) -> Result<usize, SystemError> {
222+
let epitem = arg
223+
.arc_any()
224+
.downcast::<EPollItem>()
225+
.map_err(|_| SystemError::EFAULT)?;
226+
self.epitems.lock().push_back(epitem);
227+
Ok(0)
228+
}
190229
fn fs(&self) -> Arc<dyn FileSystem> {
191230
panic!("EventFd does not have a filesystem")
192231
}

kernel/src/filesystem/vfs/file.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ use alloc::{
88
use log::error;
99
use system_error::SystemError;
1010

11+
use super::{Dirent, FileType, IndexNode, InodeId, Metadata, SpecialNodeData};
12+
use crate::filesystem::eventfd::EventFdInode;
1113
use crate::{
1214
driver::{
1315
base::{block::SeekFrom, device::DevicePrivateData},
@@ -23,8 +25,6 @@ use crate::{
2325
process::{cred::Cred, ProcessManager},
2426
};
2527

26-
use super::{Dirent, FileType, IndexNode, InodeId, Metadata, SpecialNodeData};
27-
2828
/// 文件私有信息的枚举类型
2929
#[derive(Debug, Clone)]
3030
#[allow(dead_code)]
@@ -513,9 +513,19 @@ impl File {
513513
let inode = self.inode.downcast_ref::<SocketInode>().unwrap();
514514
let mut socket = inode.inner();
515515

516-
return socket.remove_epoll(epoll);
516+
socket.remove_epoll(epoll)
517+
}
518+
FileType::Pipe => {
519+
let inode = self.inode.downcast_ref::<LockedPipeInode>().unwrap();
520+
inode.inner().lock().remove_epoll(epoll)
521+
}
522+
_ => {
523+
let inode = self
524+
.inode
525+
.downcast_ref::<EventFdInode>()
526+
.ok_or(SystemError::ENOSYS)?;
527+
inode.remove_epoll(epoll)
517528
}
518-
_ => return Err(SystemError::ENOSYS),
519529
}
520530
}
521531

@@ -643,14 +653,14 @@ impl FileDescriptorVec {
643653
/// ## 参数
644654
///
645655
/// - `fd` 文件描述符序号
646-
pub fn drop_fd(&mut self, fd: i32) -> Result<(), SystemError> {
656+
pub fn drop_fd(&mut self, fd: i32) -> Result<Arc<File>, SystemError> {
647657
self.get_file_by_fd(fd).ok_or(SystemError::EBADF)?;
648658

649659
// 把文件描述符数组对应位置设置为空
650660
let file = self.fds[fd as usize].take().unwrap();
651661

652662
assert!(Arc::strong_count(&file) == 1);
653-
return Ok(());
663+
return Ok(file);
654664
}
655665

656666
#[allow(dead_code)]

kernel/src/filesystem/vfs/syscall.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -522,8 +522,9 @@ impl Syscall {
522522
pub fn close(fd: usize) -> Result<usize, SystemError> {
523523
let binding = ProcessManager::current_pcb().fd_table();
524524
let mut fd_table_guard = binding.write();
525-
526-
fd_table_guard.drop_fd(fd as i32).map(|_| 0)
525+
let _file = fd_table_guard.drop_fd(fd as i32)?;
526+
drop(fd_table_guard);
527+
Ok(0)
527528
}
528529

529530
/// @brief 发送命令到文件描述符对应的设备,

kernel/src/ipc/pipe.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use crate::{
1818
use alloc::{
1919
collections::LinkedList,
2020
sync::{Arc, Weak},
21+
vec::Vec,
2122
};
2223
use system_error::SystemError;
2324

@@ -104,6 +105,21 @@ impl InnerPipeInode {
104105
self.epitems.lock().push_back(epitem);
105106
Ok(())
106107
}
108+
109+
pub fn remove_epoll(&self, epoll: &Weak<SpinLock<EventPoll>>) -> Result<(), SystemError> {
110+
let is_remove = !self
111+
.epitems
112+
.lock_irqsave()
113+
.extract_if(|x| x.epoll().ptr_eq(epoll))
114+
.collect::<Vec<_>>()
115+
.is_empty();
116+
117+
if is_remove {
118+
return Ok(());
119+
}
120+
121+
Err(SystemError::ENOENT)
122+
}
107123
}
108124

109125
impl LockedPipeInode {

user/apps/test_tokio/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/target
2+
Cargo.lock
3+
/install/

user/apps/test_tokio/Cargo.toml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[package]
2+
name = "test_tokio"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
tokio = { version = "1.25", features = [
8+
"macros",
9+
"rt",
10+
"rt-multi-thread",
11+
"net",
12+
"signal",
13+
] }

user/apps/test_tokio/Makefile

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
TOOLCHAIN="+nightly-2024-07-23-x86_64-unknown-linux-gnu"
2+
RUSTFLAGS+=""
3+
4+
ifdef DADK_CURRENT_BUILD_DIR
5+
# 如果是在dadk中编译,那么安装到dadk的安装目录中
6+
INSTALL_DIR = $(DADK_CURRENT_BUILD_DIR)
7+
else
8+
# 如果是在本地编译,那么安装到当前目录下的install目录中
9+
INSTALL_DIR = ./install
10+
endif
11+
12+
ifeq ($(ARCH), x86_64)
13+
export RUST_TARGET=x86_64-unknown-linux-musl
14+
else ifeq ($(ARCH), riscv64)
15+
export RUST_TARGET=riscv64gc-unknown-linux-gnu
16+
else
17+
# 默认为x86_86,用于本地编译
18+
export RUST_TARGET=x86_64-unknown-linux-musl
19+
endif
20+
21+
run:
22+
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --target $(RUST_TARGET)
23+
24+
build:
25+
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --target $(RUST_TARGET)
26+
27+
clean:
28+
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --target $(RUST_TARGET)
29+
30+
test:
31+
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test --target $(RUST_TARGET)
32+
33+
doc:
34+
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) doc --target $(RUST_TARGET)
35+
36+
fmt:
37+
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) fmt
38+
39+
fmt-check:
40+
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) fmt --check
41+
42+
run-release:
43+
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --target $(RUST_TARGET) --release
44+
45+
build-release:
46+
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --target $(RUST_TARGET) --release
47+
48+
clean-release:
49+
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --target $(RUST_TARGET) --release
50+
51+
test-release:
52+
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test --target $(RUST_TARGET) --release
53+
54+
.PHONY: install
55+
install:
56+
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) install --target $(RUST_TARGET) --path . --no-track --root $(INSTALL_DIR) --force

user/apps/test_tokio/src/main.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
use tokio::signal;
2+
3+
async fn say_world() {
4+
println!("world");
5+
}
6+
7+
#[tokio::main(flavor = "current_thread")]
8+
async fn main() {
9+
// Calling `say_world()` does not execute the body of `say_world()`.
10+
let op = say_world();
11+
12+
// This println! comes first
13+
println!("hello");
14+
15+
// Calling `.await` on `op` starts executing `say_world`.
16+
op.await;
17+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "test_tokio",
3+
"version": "0.1.0",
4+
"description": "测试tokio",
5+
"task_type": {
6+
"BuildFromSource": {
7+
"Local": {
8+
"path": "apps/test_tokio"
9+
}
10+
}
11+
},
12+
"depends": [],
13+
"build": {
14+
"build_command": "make install"
15+
},
16+
"clean": {
17+
"clean_command": "make clean"
18+
},
19+
"install": {
20+
"in_dragonos_path": "/"
21+
},
22+
"target_arch": ["x86_64"]
23+
}

0 commit comments

Comments
 (0)