Skip to content

Commit

Permalink
add eventfd syscall
Browse files Browse the repository at this point in the history
  • Loading branch information
Godones committed Jul 23, 2024
1 parent a5b04fc commit 8708069
Show file tree
Hide file tree
Showing 12 changed files with 336 additions and 18 deletions.
4 changes: 3 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ initramfs:
user:
@echo "Building user apps"
@make all -C ./user/apps
@make all -C ./user/c_apps ARCH=riscv64
@echo "Building user apps done"

sdcard:$(FS) mount testelf user initramfs
Expand Down
12 changes: 11 additions & 1 deletion kernel/src/fs/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use constants::{
use gmanager::ManagerError;
use log::{info, warn};
use syscall_table::syscall_func;
use vfs::{kfile::KernelFile, system_root_fs};
use vfs::{eventfd::eventfd, kfile::KernelFile, system_root_fs};
use vfscore::{
path::VfsPath,
utils::{VfsFileStat, VfsFsStat, VfsNodeType, VfsRenameFlag},
Expand Down Expand Up @@ -713,3 +713,13 @@ pub fn copy_file_range(
info!("sys_copy_file_range: write {} bytes to out_file", w);
Ok(w as _)
}

#[syscall_func(19)]
pub fn sys_eventfd2(init_val: u32, flags: u32) -> AlienResult<isize> {
let eventfd_file = eventfd(init_val, flags)?;
let task = current_task().unwrap();
let fd = task
.add_file(eventfd_file)
.map_err(|_| LinuxErrno::EMFILE)?;
Ok(fd as isize)
}
5 changes: 0 additions & 5 deletions kernel/src/mm/elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,11 @@ pub struct ELFInfo {
}

pub trait ELFReader {
fn build_elf(&mut self) -> Result<ELFInfo, ELFError>;
fn relocate_dyn(&self, bias: usize) -> Result<Vec<(usize, usize)>, ELFError>;
fn relocate_plt(&self, bias: usize) -> Result<Vec<(usize, usize)>, ELFError>;
}

impl ELFReader for ElfFile<'_> {
fn build_elf(&mut self) -> Result<ELFInfo, ELFError> {
Err(ELFError::NotSupported)
}

fn relocate_dyn(&self, bias: usize) -> Result<Vec<(usize, usize)>, ELFError> {
let mut res = vec![];
let data = self
Expand Down
1 change: 1 addition & 0 deletions kernel/src/task/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ pub struct TaskInner {
pub signal_handlers: Arc<Mutex<SignalHandlers>>,
/// 接收信号的结构。每个线程中一定是独特的,而上面的 handler 可能是共享的
pub signal_receivers: Arc<Mutex<SignalReceivers>>,
#[allow(unused)]
/// 子线程初始化时,存放 tid 的地址。当且仅当创建时包含 CLONE_CHILD_SETTID 才非0
pub set_child_tid: usize,
/// 子线程初始化时,将这个地址清空;子线程退出时,触发这里的 futex。
Expand Down
23 changes: 12 additions & 11 deletions subsystems/platform/src/starfive2_riscv/config.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
pub const CLOCK_FREQ: usize = 400_0000;
pub const BLOCK_CACHE_FRAMES: usize = 1024 * 4 * 4;
pub const HEAP_SIZE: usize = 0x40_00000;

/// vf2的设备地址空间
pub const MMIO: &[(usize, usize)] = &[
(0x17040000, 0x10000), // RTC
(0xc000000, 0x4000000), //PLIC
(0x00_1000_0000, 0x10000), // UART
];
pub const CLOCK_FREQ: usize = 400_0000;
pub const BLOCK_CACHE_FRAMES: usize = 1024 * 4 * 4;
pub const HEAP_SIZE: usize = 0x40_00000;

/// vf2的设备地址空间
pub const MMIO: &[(usize, usize)] = &[
(0x17040000, 0x10000), // RTC
(0xc000000, 0x4000000), //PLIC
(0x1000_0000, 0x10000), // UART
(0x16020000, 0x10000), // sdio1
];
2 changes: 2 additions & 0 deletions subsystems/vfs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ constants = { path = "../constants" }
interrupt = { path = "../interrupt" }
platform = { path = "../platform" }
mem = { path = "../mem" }
shim = { path = "../shim" }

bitflags = "1.3"
downcast-rs = { version = "1.2.0", default-features = false }
vfscore = { git = "https://github.com/os-module/rvfs.git", features = [
"linux_error",
Expand Down
168 changes: 168 additions & 0 deletions subsystems/vfs/src/eventfd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
use alloc::{collections::VecDeque, sync::Arc};
use core::{fmt::Debug, sync::atomic::AtomicU32};

use bitflags::bitflags;
use constants::{io::SeekFrom, AlienError, AlienResult};
use ksync::Mutex;
use shim::KTask;
use vfscore::{dentry::VfsDentry, inode::VfsInode, utils::VfsFileStat};

use crate::kfile::File;

static EVENTFD_ID: AtomicU32 = AtomicU32::new(0);

bitflags! {
pub struct EventFdFlags: u32{
const EFD_SEMAPHORE = 1;
const EFD_CLOEXEC = 2;
const EFD_NONBLOCK = 4;
}
}

#[derive(Debug)]
pub struct EventFd {
count: u64,
flags: EventFdFlags,
#[allow(unused)]
id: u32,
}

impl EventFd {
pub fn new(count: u64, flags: EventFdFlags, id: u32) -> Self {
EventFd { count, flags, id }
}
}

pub struct EventFdInode {
eventfd: Mutex<EventFd>,
wait_queue: Mutex<VecDeque<Arc<dyn KTask>>>,
}

impl Debug for EventFdInode {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("EventFdInode")
.field("eventfd", &self.eventfd)
.finish()
}
}

impl EventFdInode {
pub fn new(eventfd: EventFd) -> Self {
EventFdInode {
eventfd: Mutex::new(eventfd),
wait_queue: Mutex::new(VecDeque::new()),
}
}
}

impl File for EventFdInode {
fn read(&self, buf: &mut [u8]) -> AlienResult<usize> {
if buf.len() < 8 {
return Err(AlienError::EINVAL);
}
let mut val = loop {
let val = self.eventfd.lock().count;
if val != 0 {
break val;
}
if self
.eventfd
.lock()
.flags
.contains(EventFdFlags::EFD_NONBLOCK)
{
return Err(AlienError::EAGAIN);
}
let task = shim::take_current_task().unwrap();
task.to_wait();
self.wait_queue.lock().push_back(task.clone());
shim::schedule_now(task); // yield current task
};
let mut eventfd = self.eventfd.lock();
if eventfd.flags.contains(EventFdFlags::EFD_SEMAPHORE) {
eventfd.count -= 1;
val = 1;
} else {
eventfd.count = 0;
}
let val_bytes = val.to_ne_bytes();
buf[..8].copy_from_slice(&val_bytes);
return Ok(8);
}
fn write(&self, buf: &[u8]) -> AlienResult<usize> {
if buf.len() < 8 {
return Err(AlienError::EINVAL);
}
let val = u64::from_ne_bytes(buf[..8].try_into().unwrap());
if val == u64::MAX {
return Err(AlienError::EINVAL);
}
loop {
let eventfd = self.eventfd.lock();
if u64::MAX - eventfd.count > val {
break;
}
// block until a read() is performed on the
// file descriptor, or fails with the error EAGAIN if the
// file descriptor has been made nonblocking.
if eventfd.flags.contains(EventFdFlags::EFD_NONBLOCK) {
return Err(AlienError::EAGAIN);
}
drop(eventfd);
// self.wait_queue.sleep();
let task = shim::take_current_task().unwrap();
task.to_wait();
self.wait_queue.lock().push_back(task.clone());
shim::schedule_now(task); // yield current task
}
let mut eventfd = self.eventfd.lock();
eventfd.count += val;
while let Some(task) = self.wait_queue.lock().pop_front() {
task.to_wakeup();
shim::put_task(task);
}
return Ok(8);
}
fn read_at(&self, _offset: u64, buf: &mut [u8]) -> AlienResult<usize> {
self.read(buf)
}
fn write_at(&self, _offset: u64, _buf: &[u8]) -> AlienResult<usize> {
self.write(_buf)
}

fn seek(&self, _pos: SeekFrom) -> AlienResult<u64> {
Err(AlienError::ENOSYS)
}

fn get_attr(&self) -> AlienResult<VfsFileStat> {
Err(AlienError::ENOSYS)
}

fn dentry(&self) -> Arc<dyn VfsDentry> {
panic!("EventFdInode::dentry() is not implemented")
}

fn inode(&self) -> Arc<dyn VfsInode> {
panic!("EventFdInode::inode() is not implemented")
}

fn is_readable(&self) -> bool {
true
}

fn is_writable(&self) -> bool {
true
}

fn is_append(&self) -> bool {
true
}
}

pub fn eventfd(init_val: u32, flags: u32) -> AlienResult<Arc<dyn File>> {
let flags = EventFdFlags::from_bits(flags).ok_or(AlienError::EINVAL)?;
let id = EVENTFD_ID.fetch_add(1, core::sync::atomic::Ordering::Relaxed);
let eventfd = EventFd::new(init_val as u64, flags, id);
let inode = Arc::new(EventFdInode::new(eventfd));
Ok(inode)
}
1 change: 1 addition & 0 deletions subsystems/vfs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use vfscore::{dentry::VfsDentry, fstype::VfsFsType, path::VfsPath, utils::VfsTim

use crate::dev::DevFsProviderImpl;
pub mod dev;
pub mod eventfd;
#[cfg(feature = "ext")]
mod extffi;
mod initrd;
Expand Down
55 changes: 55 additions & 0 deletions user/c_apps/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
### C template
# Prerequisites
*.d

# Object files
*.o
*.ko
*.obj
*.elf

# Linker output
*.ilk
*.map
*.exp

# Precompiled Headers
*.gch
*.pch

# Libraries
*.lib
*.a
*.la
*.lo

# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib

# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex

# Debug files
*.dSYM/
*.su
*.idb
*.pdb

# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf

eventfd_test
26 changes: 26 additions & 0 deletions user/c_apps/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
ifeq ($(ARCH), x86_64)
CROSS_COMPILE=x86_64-linux-musl-
else ifeq ($(ARCH), riscv64)
CROSS_COMPILE=riscv64-linux-musl-
endif


FSMOUNT := ../../diskfs
CC=$(CROSS_COMPILE)gcc


all:build
@$(foreach file, $(BUILD_LIST), (sudo cp $(file) $(FSMOUNT)/$(dir););)

build:
@echo "Building C apps"
$(foreach file, $(BUILD_LIST), $(CC) -static -o $(file) $(file).c;)

clean:
$(foreach file, $(BUILD_LIST), rm $(file);)

BUILD_LIST := \
eventfd_test \


.PHONY: install clean all
Loading

0 comments on commit 8708069

Please sign in to comment.