Kernel: Implement linux's eventfd
This commit is contained in:
parent
a49588dbc7
commit
c1a424a635
|
|
@ -0,0 +1,52 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <kernel/FS/Inode.h>
|
||||||
|
|
||||||
|
namespace Kernel
|
||||||
|
{
|
||||||
|
|
||||||
|
class EventFD final : public Inode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static BAN::ErrorOr<BAN::RefPtr<Inode>> create(uint64_t initval, bool semaphore);
|
||||||
|
|
||||||
|
ino_t ino() const override { return 0; }
|
||||||
|
Mode mode() const override { return { Mode::IFCHR | Mode::IRUSR | Mode::IWUSR }; }
|
||||||
|
nlink_t nlink() const override { return ref_count(); }
|
||||||
|
uid_t uid() const override { return 0; }
|
||||||
|
gid_t gid() const override { return 0; }
|
||||||
|
off_t size() const override { return 0; }
|
||||||
|
timespec atime() const override { return {}; }
|
||||||
|
timespec mtime() const override { return {}; }
|
||||||
|
timespec ctime() const override { return {}; }
|
||||||
|
blksize_t blksize() const override { return 8; }
|
||||||
|
blkcnt_t blocks() const override { return 0; }
|
||||||
|
dev_t dev() const override { return 0; }
|
||||||
|
dev_t rdev() const override { return 0; }
|
||||||
|
|
||||||
|
const FileSystem* filesystem() const override { return nullptr; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
||||||
|
BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
||||||
|
BAN::ErrorOr<void> fsync_impl() final override { return {}; }
|
||||||
|
|
||||||
|
bool can_read_impl() const override { return m_value > 0; }
|
||||||
|
bool can_write_impl() const override { return m_value < UINT64_MAX - 1; }
|
||||||
|
bool has_error_impl() const override { return false; }
|
||||||
|
bool has_hungup_impl() const override { return false; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
EventFD(uint64_t initval, bool is_semaphore)
|
||||||
|
: m_is_semaphore(is_semaphore)
|
||||||
|
, m_value(initval)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const bool m_is_semaphore;
|
||||||
|
uint64_t m_value;
|
||||||
|
|
||||||
|
ThreadBlocker m_thread_blocker;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -147,6 +147,8 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event* event);
|
BAN::ErrorOr<long> sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event* event);
|
||||||
BAN::ErrorOr<long> sys_epoll_pwait2(int epfd, struct epoll_event* events, int maxevents, const struct timespec* timeout, const sigset_t* sigmask);
|
BAN::ErrorOr<long> sys_epoll_pwait2(int epfd, struct epoll_event* events, int maxevents, const struct timespec* timeout, const sigset_t* sigmask);
|
||||||
|
|
||||||
|
BAN::ErrorOr<long> sys_eventfd(unsigned int initval_hi, int flags);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_pipe(int fildes[2]);
|
BAN::ErrorOr<long> sys_pipe(int fildes[2]);
|
||||||
BAN::ErrorOr<long> sys_dup2(int fildes, int fildes2);
|
BAN::ErrorOr<long> sys_dup2(int fildes, int fildes2);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
#include <kernel/FS/EventFD.h>
|
||||||
|
|
||||||
|
#include <sys/epoll.h>
|
||||||
|
|
||||||
|
namespace Kernel
|
||||||
|
{
|
||||||
|
|
||||||
|
BAN::ErrorOr<BAN::RefPtr<Inode>> EventFD::create(uint64_t initval, bool semaphore)
|
||||||
|
{
|
||||||
|
auto* eventfd_ptr = new EventFD(initval, semaphore);
|
||||||
|
if (eventfd_ptr == nullptr)
|
||||||
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
|
return BAN::RefPtr<Inode>(BAN::RefPtr<EventFD>::adopt(eventfd_ptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<size_t> EventFD::read_impl(off_t, BAN::ByteSpan buffer)
|
||||||
|
{
|
||||||
|
if (buffer.size() < sizeof(uint64_t))
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
|
while (m_value == 0)
|
||||||
|
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex));
|
||||||
|
|
||||||
|
const uint64_t read_value = m_is_semaphore ? 1 : m_value;
|
||||||
|
m_value -= read_value;
|
||||||
|
|
||||||
|
buffer.as<uint64_t>() = read_value;
|
||||||
|
|
||||||
|
epoll_notify(EPOLLOUT);
|
||||||
|
|
||||||
|
return sizeof(uint64_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<size_t> EventFD::write_impl(off_t, BAN::ConstByteSpan buffer)
|
||||||
|
{
|
||||||
|
if (buffer.size() < sizeof(uint64_t))
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
|
const uint64_t write_value = buffer.as<const uint64_t>();
|
||||||
|
if (write_value == UINT64_MAX)
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
|
while (m_value + write_value < m_value)
|
||||||
|
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex));
|
||||||
|
|
||||||
|
m_value += write_value;
|
||||||
|
|
||||||
|
if (m_value > 0)
|
||||||
|
epoll_notify(EPOLLIN);
|
||||||
|
|
||||||
|
return sizeof(uint64_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include <kernel/ELF.h>
|
#include <kernel/ELF.h>
|
||||||
#include <kernel/Epoll.h>
|
#include <kernel/Epoll.h>
|
||||||
#include <kernel/FS/DevFS/FileSystem.h>
|
#include <kernel/FS/DevFS/FileSystem.h>
|
||||||
|
#include <kernel/FS/EventFD.h>
|
||||||
#include <kernel/FS/ProcFS/FileSystem.h>
|
#include <kernel/FS/ProcFS/FileSystem.h>
|
||||||
#include <kernel/FS/VirtualFileSystem.h>
|
#include <kernel/FS/VirtualFileSystem.h>
|
||||||
#include <kernel/IDT.h>
|
#include <kernel/IDT.h>
|
||||||
|
|
@ -28,6 +29,7 @@
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/banan-os.h>
|
#include <sys/banan-os.h>
|
||||||
|
#include <sys/eventfd.h>
|
||||||
#include <sys/futex.h>
|
#include <sys/futex.h>
|
||||||
#include <sys/sysmacros.h>
|
#include <sys/sysmacros.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
@ -2160,6 +2162,27 @@ namespace Kernel
|
||||||
return TRY(static_cast<Epoll*>(epoll_inode.ptr())->wait(BAN::Span<epoll_event>(events, maxevents), waketime_ns));
|
return TRY(static_cast<Epoll*>(epoll_inode.ptr())->wait(BAN::Span<epoll_event>(events, maxevents), waketime_ns));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<long> Process::sys_eventfd(unsigned int initval, int flags)
|
||||||
|
{
|
||||||
|
if (flags & ~(EFD_CLOEXEC | EFD_NONBLOCK | EFD_SEMAPHORE))
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
|
int oflags = 0;
|
||||||
|
if (flags & EFD_CLOEXEC)
|
||||||
|
oflags |= O_CLOEXEC;
|
||||||
|
if (flags & EFD_NONBLOCK)
|
||||||
|
oflags |= O_NONBLOCK;
|
||||||
|
|
||||||
|
const bool is_semaphore = !!(flags & EFD_SEMAPHORE);
|
||||||
|
|
||||||
|
return TRY(m_open_file_descriptors.open(
|
||||||
|
VirtualFileSystem::File {
|
||||||
|
TRY(EventFD::create(initval, is_semaphore)),
|
||||||
|
"<eventfd>"_sv
|
||||||
|
}, oflags
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_pipe(int user_fildes[2])
|
BAN::ErrorOr<long> Process::sys_pipe(int user_fildes[2])
|
||||||
{
|
{
|
||||||
int fildes[2];
|
int fildes[2];
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
#ifndef _SYS_EVENTFD_H
|
||||||
|
#define _SYS_EVENTFD_H 1
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
#define EFD_CLOEXEC 0x1
|
||||||
|
#define EFD_NONBLOCK 0x2
|
||||||
|
#define EFD_SEMAPHORE 0x4
|
||||||
|
|
||||||
|
int eventfd(unsigned int initval, int flags);
|
||||||
|
|
||||||
|
__END_DECLS
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -119,6 +119,7 @@ __BEGIN_DECLS
|
||||||
O(SYS_GETGROUPS, getgroups) \
|
O(SYS_GETGROUPS, getgroups) \
|
||||||
O(SYS_SETGROUPS, setgroups) \
|
O(SYS_SETGROUPS, setgroups) \
|
||||||
O(SYS_CHROOT, chroot) \
|
O(SYS_CHROOT, chroot) \
|
||||||
|
O(SYS_EVENTFD, eventfd) \
|
||||||
|
|
||||||
enum Syscall
|
enum Syscall
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include <sys/eventfd.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int eventfd(unsigned int initval, int flags)
|
||||||
|
{
|
||||||
|
return syscall(SYS_EVENTFD, initval, flags);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue