kernel: implement eventfs/eventfd

This commit is contained in:
Matheus
2026-06-18 01:53:59 -03:00
parent 9194741bd8
commit b74f36e984
6 changed files with 305 additions and 21 deletions
+3 -1
View File
@@ -105,6 +105,7 @@ extern syscall_getsockopt
extern syscall_clock_getres extern syscall_clock_getres
extern syscall_setpriority extern syscall_setpriority
extern syscall_sysctl extern syscall_sysctl
extern syscall_eventfd
syscalltab: syscalltab:
dq syscall_print dq syscall_print
dq syscall_mmap dq syscall_mmap
@@ -212,7 +213,8 @@ dq syscall_getsockopt
dq syscall_clock_getres dq syscall_clock_getres
dq syscall_setpriority dq syscall_setpriority
dq syscall_sysctl dq syscall_sysctl
syscallcount equ 106 dq syscall_eventfd
syscallcount equ 107
section .text section .text
global arch_syscall_entry global arch_syscall_entry
; on entry: ; on entry:
+3 -1
View File
@@ -9,7 +9,7 @@
void arch_interrupt_disable(); void arch_interrupt_disable();
void arch_interrupt_enable(); void arch_interrupt_enable();
#define SYSCALL_COUNT 106 #define SYSCALL_COUNT 107
#define LOGSTR(x) arch_e9_puts(x) #define LOGSTR(x) arch_e9_puts(x)
static char *name[] = { static char *name[] = {
@@ -119,6 +119,7 @@ static char *name[] = {
"clock_getres", "clock_getres",
"setpriority", "setpriority",
"sysctl", "sysctl",
"eventfd",
}; };
static char *args[] = { static char *args[] = {
@@ -228,6 +229,7 @@ static char *args[] = {
"clockid %d timespec %p", // clock_getres "clockid %d timespec %p", // clock_getres
"which %d who %d prio %d", // setpriority "which %d who %d prio %d", // setpriority
"name %p name_len %lu oldp %p old_size %p newp %p new_size %lu", // sysctl "name %p name_len %lu oldp %p old_size %p newp %p new_size %lu", // sysctl
"initval %lu flags %x", //eventfd
}; };
#endif #endif
+219
View File
@@ -0,0 +1,219 @@
#include <kernel/vfs.h>
#include <kernel/slab.h>
#include <logging.h>
#include <errno.h>
#include <kernel/poll.h>
#include <kernel/init.h>
#include <kernel/eventfs.h>
#define EVENT_COUNTER_MAX 0xfffffffffffffffelu
typedef struct {
vnode_t vnode;
pollheader_t pollheader;
uint64_t counter;
bool semaphore;
} event_node_t;
static scache_t *node_cache;
int eventfs_close(vnode_t *node, int flags, cred_t *cred) {
return 0; // not needed
}
static int internal_poll(event_node_t *event_node, polldata_t *data, int events, size_t write_limit) {
int revents = 0;
if ((events & POLLIN) && event_node->counter)
revents |= POLLIN;
if ((events & POLLOUT) && event_node->counter <= write_limit)
revents |= POLLOUT;
if (data && !revents)
poll_add(&event_node->pollheader, data, events);
return revents;
}
static int internal_poll_wait(event_node_t *event_node, int event, bool non_blocking, size_t write_limit) {
for (;;) {
polldesc_t desc = {0};
int error = poll_initdesc(&desc, 1);
if (error)
return error;
int revents = internal_poll(event_node, &desc.data[0], event, write_limit);
if (revents) {
poll_leave(&desc);
poll_destroydesc(&desc);
break;
}
if (non_blocking) {
poll_leave(&desc);
poll_destroydesc(&desc);
return EAGAIN;
}
MUTEX_RELEASE(&event_node->vnode.lock);
error = poll_dowait(&desc, 0);
poll_leave(&desc);
poll_destroydesc(&desc);
MUTEX_ACQUIRE(&event_node->vnode.lock);
if (error)
return error;
}
return 0;
}
int eventfs_read(vnode_t *node, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *bytes_read, cred_t *cred) {
event_node_t *event_node = (event_node_t *)node;
if (size < 8)
return EINVAL;
MUTEX_ACQUIRE(&node->lock);
int error = internal_poll_wait(event_node, POLLIN, flags & V_FFLAGS_NONBLOCKING, 0);
if (error)
goto leave;
uint64_t return_value = event_node->semaphore ? 1 : event_node->counter;
error = iovec_iterator_copy_from_buffer(iovec_iterator, &return_value, 8);
if (error)
goto leave;
event_node->counter = event_node->semaphore ? (event_node->counter - 1) : 0;
*bytes_read = 8;
poll_event(&event_node->pollheader, POLLOUT);
leave:
MUTEX_RELEASE(&node->lock);
return error;
}
int eventfs_write(vnode_t *node, iovec_iterator_t *iovec_iterator, size_t size, uintmax_t offset, int flags, size_t *bytes_written, cred_t *cred) {
event_node_t *event_node = (event_node_t *)node;
if (size < 8)
return EINVAL;
uint64_t value_to_write;
int error = iovec_iterator_copy_to_buffer(iovec_iterator, &value_to_write, 8);
if (error)
return error;
if (value_to_write > EVENT_COUNTER_MAX)
return EINVAL;
MUTEX_ACQUIRE(&node->lock);
error = internal_poll_wait(event_node, POLLOUT, flags & V_FFLAGS_NONBLOCKING, EVENT_COUNTER_MAX - value_to_write);
if (error)
goto leave;
event_node->counter += value_to_write;
__assert(event_node->counter <= EVENT_COUNTER_MAX);
poll_event(&event_node->pollheader, POLLIN);
*bytes_written = 8;
leave:
MUTEX_RELEASE(&node->lock);
return error;
}
int eventfs_poll(vnode_t *node, polldata_t *data, int events) {
MUTEX_ACQUIRE(&node->lock);
int revents = internal_poll((event_node_t *)node, data, events, EVENT_COUNTER_MAX - 1);
MUTEX_RELEASE(&node->lock);
return revents;
}
static vops_t vnops;
int eventfs_inactive(vnode_t *node) {
event_node_t *event_node = (event_node_t *)node;
VOP_INIT(&event_node->vnode, &vnops, 0, V_TYPE_CHDEV, NULL);
POLL_INITHEADER(&event_node->pollheader);
slab_free(node_cache, node);
return 0;
}
static int eventfs_lock(vnode_t *) {
return 0;
}
static int eventfs_unlock(vnode_t *) {
return 0;
}
static int eventfs_advlock(vnode_t *node, int op, advlock_t *advlock) {
return vfs_advlock(node, op, advlock);
}
static int eventfs_enodev() {
return ENODEV;
}
static vops_t vnops = {
.create = eventfs_enodev,
.open = eventfs_enodev,
.close = eventfs_close,
.getattr = eventfs_enodev,
.setattr = eventfs_enodev,
.lookup = eventfs_enodev,
.poll = eventfs_poll,
.read = eventfs_read,
.write = eventfs_write,
.access = eventfs_enodev,
.unlink = eventfs_enodev,
.link = eventfs_enodev,
.symlink = eventfs_enodev,
.readlink = eventfs_enodev,
.inactive = eventfs_inactive,
.mmap = eventfs_enodev,
.munmap = eventfs_enodev,
.getdents = eventfs_enodev,
.resize = eventfs_enodev,
.rename = eventfs_enodev,
.ioctl = eventfs_enodev,
.putpage = eventfs_enodev,
.getpage = eventfs_enodev,
.sync = eventfs_enodev,
.advlock = eventfs_advlock,
.lock = eventfs_lock,
.unlock = eventfs_unlock
};
static bool ctor(scache_t *cache, void *obj) {
event_node_t *node = obj;
VOP_INIT(&node->vnode, &vnops, 0, V_TYPE_CHDEV, NULL);
POLL_INITHEADER(&node->pollheader);
return true;
}
void eventfs_init() {
node_cache = slab_newcache(sizeof(event_node_t), 0, ctor, NULL);
__assert(node_cache);
}
INIT_ROUTINE_DEFINE(eventfs, INIT_ROUTINE_FLAGS_NONE, eventfs_init, bsp_early);
int eventfs_create_node(vnode_t **vnodep, size_t initval, bool semaphore) {
event_node_t *event_node = slab_allocate(node_cache);
if (event_node == NULL)
return ENOMEM;
event_node->counter = initval;
event_node->semaphore = semaphore;
*vnodep = &event_node->vnode;
return 0;
}
+8
View File
@@ -0,0 +1,8 @@
#ifndef _EVENTFS_H
#define _EVENTFS_H
#include <kernel/vfs.h>
int eventfs_create_node(vnode_t **vnodep, size_t initval, bool semaphore);
#endif
+40
View File
@@ -0,0 +1,40 @@
#include <kernel/syscalls.h>
#include <kernel/eventfs.h>
#define EFD_CLOEXEC O_CLOEXEC
#define EFD_NONBLOCK O_NONBLOCK
#define EFD_SEMAPHORE 1
#define KNOWN_FLAGS (EFD_CLOEXEC | EFD_NONBLOCK | EFD_SEMAPHORE)
syscallret_t syscall_eventfd(context_t *, size_t initval, int flags) {
syscallret_t ret = {
.ret = -1
};
if (flags & ~KNOWN_FLAGS) {
ret.errno = EINVAL;
return ret;
}
vnode_t *vnode;
ret.errno = eventfs_create_node(&vnode, initval, flags & EFD_SEMAPHORE);
if (ret.errno)
return ret;
file_t *file;
int fd;
ret.errno = fd_new((flags & EFD_CLOEXEC) ? O_CLOEXEC : 0, &file, &fd);
if (ret.errno) {
VOP_RELEASE(vnode);
return ret;
}
file->vnode = vnode;
file->flags = FILE_WRITE | FILE_READ | ((flags & EFD_NONBLOCK) ? O_NONBLOCK : 0);
file->offset = 0;
file->mode = 0666;
ret.ret = fd;
return ret;
}
+32 -19
View File
@@ -452,7 +452,7 @@ index a86353f..3e1a18c 100644
return error ? -1 : ret; return error ? -1 : ret;
} }
diff --git mlibc-clean/sysdeps/astral/generic/generic.cpp mlibc-workdir/sysdeps/astral/generic/generic.cpp diff --git mlibc-clean/sysdeps/astral/generic/generic.cpp mlibc-workdir/sysdeps/astral/generic/generic.cpp
index 3b04372..b7a8ab7 100644 index 3b04372..5324a35 100644
--- mlibc-clean/sysdeps/astral/generic/generic.cpp --- mlibc-clean/sysdeps/astral/generic/generic.cpp
+++ mlibc-workdir/sysdeps/astral/generic/generic.cpp +++ mlibc-workdir/sysdeps/astral/generic/generic.cpp
@@ -1,7 +1,9 @@ @@ -1,7 +1,9 @@
@@ -497,7 +497,7 @@ index 3b04372..b7a8ab7 100644
namespace mlibc { namespace mlibc {
int Sysdeps<SetGroups>::operator()(size_t size, const gid_t *list) { int Sysdeps<SetGroups>::operator()(size_t size, const gid_t *list) {
@@ -31,14 +56,313 @@ namespace mlibc { @@ -31,15 +56,324 @@ namespace mlibc {
return 0; return 0;
} }
@@ -627,9 +627,9 @@ index 3b04372..b7a8ab7 100644
+ int Sysdeps<GetCurrentStackInfo>::operator()(void **stack_base, size_t *stack_size) { + int Sysdeps<GetCurrentStackInfo>::operator()(void **stack_base, size_t *stack_size) {
+ *stack_size = 1024 * 1024 * 4; + *stack_size = 1024 * 1024 * 4;
+ *stack_base = (void *)(0x0000800000000000 - *stack_size); + *stack_base = (void *)(0x0000800000000000 - *stack_size);
+ return 0; return 0;
+ } }
+
+#ifndef MLIBC_BUILDING_RTLD +#ifndef MLIBC_BUILDING_RTLD
+ int Sysdeps<Getifaddrs>::operator()(struct ifaddrs **out) { + int Sysdeps<Getifaddrs>::operator()(struct ifaddrs **out) {
+ struct ifaddrs *list = nullptr; + struct ifaddrs *list = nullptr;
@@ -804,19 +804,30 @@ index 3b04372..b7a8ab7 100644
+ *out = arr; + *out = arr;
+ freeifaddrs(ifaddrs); + freeifaddrs(ifaddrs);
+ +
return 0; + return 0;
} + }
+#endif +#endif
+ +
+ int Sysdeps<EventfdCreate>::operator()(unsigned int initval, int flags, int *fd) {
+ long ret;
+ int error = syscall(SYSCALL_EVENTFD, &ret, initval, flags);
+ if (error)
+ return error;
+
+ *fd = ret;
+ return 0;
+ }
+
+ int Sysdeps<GetSockopt>::operator()(int fd, int layer, int number, + int Sysdeps<GetSockopt>::operator()(int fd, int layer, int number,
+ void *__restrict buffer, socklen_t *__restrict size) { + void *__restrict buffer, socklen_t *__restrict size) {
+ long ret; + long ret;
+ return syscall(SYSCALL_GETSOCKOPT, &ret, fd, layer, number, (uint64_t)buffer, (uint64_t)size); + return syscall(SYSCALL_GETSOCKOPT, &ret, fd, layer, number, (uint64_t)buffer, (uint64_t)size);
+ } + }
+
int Sysdeps<InetConfigured>::operator()(bool *ipv4, bool *ipv6) { int Sysdeps<InetConfigured>::operator()(bool *ipv4, bool *ipv6) {
// there is no ipv6 support in the kernel currently and no way of checking for configured interfaces // there is no ipv6 support in the kernel currently and no way of checking for configured interfaces
@@ -47,6 +371,71 @@ namespace mlibc { *ipv4 = true;
@@ -47,6 +381,71 @@ namespace mlibc {
return 0; return 0;
} }
@@ -888,7 +899,7 @@ index 3b04372..b7a8ab7 100644
int Sysdeps<Readv>::operator()(int fd, const struct iovec *iovs, int iovc, ssize_t *bytes_read) { int Sysdeps<Readv>::operator()(int fd, const struct iovec *iovs, int iovc, ssize_t *bytes_read) {
long r; long r;
int error = syscall(SYSCALL_READV, &r, fd, (uint64_t)iovs, iovc); int error = syscall(SYSCALL_READV, &r, fd, (uint64_t)iovs, iovc);
@@ -86,6 +475,11 @@ namespace mlibc { @@ -86,6 +485,11 @@ namespace mlibc {
return e; return e;
} }
@@ -900,7 +911,7 @@ index 3b04372..b7a8ab7 100644
int Sysdeps<Shutdown>::operator()(int sockfd, int how) { int Sysdeps<Shutdown>::operator()(int sockfd, int how) {
long ret; long ret;
return syscall(SYSCALL_SHUTDOWN, &ret, sockfd, how); return syscall(SYSCALL_SHUTDOWN, &ret, sockfd, how);
@@ -487,8 +881,15 @@ namespace mlibc { @@ -487,8 +891,15 @@ namespace mlibc {
return err; return err;
} }
@@ -916,7 +927,7 @@ index 3b04372..b7a8ab7 100644
return syscall(SYSCALL_SETSOCKOPT, &ret, fd, layer, number, (uint64_t)buffer, size); return syscall(SYSCALL_SETSOCKOPT, &ret, fd, layer, number, (uint64_t)buffer, size);
} }
@@ -511,6 +912,11 @@ namespace mlibc { @@ -511,6 +922,11 @@ namespace mlibc {
return err; return err;
} }
@@ -928,7 +939,7 @@ index 3b04372..b7a8ab7 100644
int Sysdeps<Renameat>::operator()(int olddirfd, const char *old_path, int newdirfd, const char *new_path) { int Sysdeps<Renameat>::operator()(int olddirfd, const char *old_path, int newdirfd, const char *new_path) {
long ret; long ret;
return syscall(SYSCALL_RENAMEAT, &ret, olddirfd, (uint64_t)old_path, newdirfd, (uint64_t)new_path); return syscall(SYSCALL_RENAMEAT, &ret, olddirfd, (uint64_t)old_path, newdirfd, (uint64_t)new_path);
@@ -562,6 +968,16 @@ namespace mlibc { @@ -562,6 +978,16 @@ namespace mlibc {
return sysdep<Ioctl>(fd, TCSETS, (void *)attr, &res); return sysdep<Ioctl>(fd, TCSETS, (void *)attr, &res);
} }
@@ -945,7 +956,7 @@ index 3b04372..b7a8ab7 100644
int Sysdeps<Poll>::operator()(struct pollfd *fds, nfds_t count, int timeout, int *num_events) { int Sysdeps<Poll>::operator()(struct pollfd *fds, nfds_t count, int timeout, int *num_events) {
long ret; long ret;
long error = syscall(SYSCALL_POLL, &ret, (uint64_t)fds, count, timeout); long error = syscall(SYSCALL_POLL, &ret, (uint64_t)fds, count, timeout);
@@ -932,4 +1348,13 @@ namespace mlibc { @@ -932,4 +1358,13 @@ namespace mlibc {
*nanos = ts.tv_nsec; *nanos = ts.tv_nsec;
return err; return err;
} }
@@ -982,10 +993,10 @@ index 7e4f2a1..ecc2677 100644
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
diff --git mlibc-clean/sysdeps/astral/include/astral/syscall.h mlibc-workdir/sysdeps/astral/include/astral/syscall.h diff --git mlibc-clean/sysdeps/astral/include/astral/syscall.h mlibc-workdir/sysdeps/astral/include/astral/syscall.h
index a6c4067..160a140 100644 index a6c4067..9040d45 100644
--- mlibc-clean/sysdeps/astral/include/astral/syscall.h --- mlibc-clean/sysdeps/astral/include/astral/syscall.h
+++ mlibc-workdir/sysdeps/astral/include/astral/syscall.h +++ mlibc-workdir/sysdeps/astral/include/astral/syscall.h
@@ -103,6 +103,13 @@ @@ -103,6 +103,14 @@
#define SYSCALL_SYSINFO 96 #define SYSCALL_SYSINFO 96
#define SYSCALL_WRITEV 97 #define SYSCALL_WRITEV 97
#define SYSCALL_READV 98 #define SYSCALL_READV 98
@@ -996,6 +1007,7 @@ index a6c4067..160a140 100644
+#define SYSCALL_CLOCK_GETRES 103 +#define SYSCALL_CLOCK_GETRES 103
+#define SYSCALL_SETPRIORITY 104 +#define SYSCALL_SETPRIORITY 104
+#define SYSCALL_SYSCTL 105 +#define SYSCALL_SYSCTL 105
+#define SYSCALL_EVENTFD 106
#ifndef __MLIBC_ABI_ONLY #ifndef __MLIBC_ABI_ONLY
@@ -1062,7 +1074,7 @@ index 0000000..161f634
+ +
+#endif /* _ASTRAL_SYSCTL_H */ +#endif /* _ASTRAL_SYSCTL_H */
diff --git mlibc-clean/sysdeps/astral/include/mlibc/sysdeps.hpp mlibc-workdir/sysdeps/astral/include/mlibc/sysdeps.hpp diff --git mlibc-clean/sysdeps/astral/include/mlibc/sysdeps.hpp mlibc-workdir/sysdeps/astral/include/mlibc/sysdeps.hpp
index ce91084..54ee08e 100644 index ce91084..503110a 100644
--- mlibc-clean/sysdeps/astral/include/mlibc/sysdeps.hpp --- mlibc-clean/sysdeps/astral/include/mlibc/sysdeps.hpp
+++ mlibc-workdir/sysdeps/astral/include/mlibc/sysdeps.hpp +++ mlibc-workdir/sysdeps/astral/include/mlibc/sysdeps.hpp
@@ -7,8 +7,30 @@ namespace mlibc { @@ -7,8 +7,30 @@ namespace mlibc {
@@ -1121,7 +1133,7 @@ index ce91084..54ee08e 100644
Poll, Poll,
Ppoll, Ppoll,
Pselect, Pselect,
@@ -135,7 +161,10 @@ struct AstralSysdepTags : @@ -135,7 +161,11 @@ struct AstralSysdepTags :
VmUnmap, VmUnmap,
Isatty, Isatty,
ClockGet, ClockGet,
@@ -1129,7 +1141,8 @@ index ce91084..54ee08e 100644
+ ClockGetres, + ClockGetres,
+ PrepareStack, + PrepareStack,
+ SetPriority, + SetPriority,
+ GetCurrentStackInfo + GetCurrentStackInfo,
+ EventfdCreate
{}; {};
template<typename Tag> template<typename Tag>