use alloc::format; use crate::c_str::{CStr, CString}; use crate::error::{Errno, ResultExt}; use crate::header::fcntl::{O_CLOEXEC, O_NONBLOCK, O_RDWR}; use crate::header::errno::EFAULT; use crate::header::errno::EINVAL; use crate::platform::{Pal, Sys, types::{c_int, c_uint, uint64_t}}; // cbindgen can't resolve re-exports across modules, so eventfd_t is // defined here directly (the C typedef lives in after_includes in // cbindgen.toml). bits_eventfd still has its own copy for independent // consumers that include only . pub type eventfd_t = uint64_t; pub const EFD_SEMAPHORE: c_int = 1; pub const EFD_CLOEXEC: c_int = 0x80000; pub const EFD_NONBLOCK: c_int = 0x800; #[unsafe(no_mangle)] pub extern "C" fn eventfd(initval: c_uint, flags: c_int) -> c_int { let supported = EFD_CLOEXEC | EFD_NONBLOCK | EFD_SEMAPHORE; if flags & !supported != 0 { return Err::(Errno(EINVAL)).or_minus_one_errno(); } let sem = if flags & EFD_SEMAPHORE != 0 { 1 } else { 0 }; let path = format!("/scheme/event/eventfd/{}/{}", initval, sem); let cpath = match CString::new(path) { Ok(p) => p, Err(_) => return Err::(Errno(EINVAL)).or_minus_one_errno(), }; let mut oflag = O_RDWR; if flags & EFD_CLOEXEC == EFD_CLOEXEC { oflag |= O_CLOEXEC; } if flags & EFD_NONBLOCK == EFD_NONBLOCK { oflag |= O_NONBLOCK; } Sys::open(CStr::borrow(&cpath), oflag, 0).or_minus_one_errno() } #[unsafe(no_mangle)] pub extern "C" fn eventfd_read(fd: c_int, value: *mut eventfd_t) -> c_int { if value.is_null() { return Err::(Errno(EFAULT)).or_minus_one_errno(); } let mut buf = [0u8; 8]; match Sys::read(fd, &mut buf) { Ok(8) => { unsafe { *value = u64::from_ne_bytes(buf); } 0 } _ => -1, } } #[unsafe(no_mangle)] pub extern "C" fn eventfd_write(fd: c_int, value: eventfd_t) -> c_int { let buf = value.to_ne_bytes(); match Sys::write(fd, &buf) { Ok(8) => 0, _ => -1, } }