Kernel/LibC: Implement basic epoll
This implementation is on top of inodes instead of fds as linux does it. If I start finding ports/software that relies on epoll allowing duplicate inodes, I will do what linux does. I'm probably missing multiple epoll_notify's which may cause hangs but the system seems to work fine :dd:
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class DebugDevice : public CharacterDevice
|
||||
class DebugDevice final : public CharacterDevice
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<DebugDevice>> create(mode_t, uid_t, gid_t);
|
||||
@@ -24,6 +24,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hangup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
const dev_t m_rdev;
|
||||
|
||||
@@ -38,6 +38,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hangup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
FramebufferDevice(mode_t mode, uid_t uid, gid_t gid, dev_t rdev, paddr_t paddr, uint32_t width, uint32_t height, uint32_t pitch, uint8_t bpp);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class NullDevice : public CharacterDevice
|
||||
class NullDevice final : public CharacterDevice
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<NullDevice>> create(mode_t, uid_t, gid_t);
|
||||
@@ -26,6 +26,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hangup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
const dev_t m_rdev;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class RandomDevice : public CharacterDevice
|
||||
class RandomDevice final : public CharacterDevice
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<RandomDevice>> create(mode_t, uid_t, gid_t);
|
||||
@@ -24,6 +24,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hangup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
const dev_t m_rdev;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class ZeroDevice : public CharacterDevice
|
||||
class ZeroDevice final : public CharacterDevice
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<ZeroDevice>> create(mode_t, uid_t, gid_t);
|
||||
@@ -24,6 +24,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hangup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
const dev_t m_rdev;
|
||||
|
||||
68
kernel/include/kernel/Epoll.h
Normal file
68
kernel/include/kernel/Epoll.h
Normal file
@@ -0,0 +1,68 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/CircularQueue.h>
|
||||
#include <BAN/HashMap.h>
|
||||
#include <BAN/HashSet.h>
|
||||
#include <kernel/FS/Inode.h>
|
||||
|
||||
#include <sys/epoll.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class Epoll final : public Inode
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<Epoll>> create();
|
||||
~Epoll();
|
||||
|
||||
BAN::ErrorOr<void> ctl(int op, BAN::RefPtr<Inode> inode, epoll_event event);
|
||||
BAN::ErrorOr<size_t> wait(BAN::Span<epoll_event> events, uint64_t waketime_ns);
|
||||
|
||||
void notify(BAN::RefPtr<Inode> inode, uint32_t event);
|
||||
|
||||
private:
|
||||
Epoll() = default;
|
||||
|
||||
public:
|
||||
ino_t ino() const override { return 0; }
|
||||
Mode mode() const override { return { Mode::IRUSR | Mode::IWUSR }; }
|
||||
nlink_t nlink() const override { return 0; }
|
||||
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 PAGE_SIZE; }
|
||||
blkcnt_t blocks() const override { return 0; }
|
||||
dev_t dev() const override { return 0; }
|
||||
dev_t rdev() const override { return 0; }
|
||||
|
||||
bool is_epoll() const override { return true; }
|
||||
|
||||
const FileSystem* filesystem() const override { return nullptr; }
|
||||
|
||||
bool can_read_impl() const override { return false; }
|
||||
bool can_write_impl() const override { return false; }
|
||||
bool has_error_impl() const override { return false; }
|
||||
bool has_hangup_impl() const override { return false; }
|
||||
|
||||
BAN::ErrorOr<void> fsync_impl() override { return {}; }
|
||||
|
||||
private:
|
||||
struct InodeRefPtrHash
|
||||
{
|
||||
BAN::hash_t operator()(const BAN::RefPtr<Inode>& inode)
|
||||
{
|
||||
return BAN::hash<const Inode*>()(inode.ptr());
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
ThreadBlocker m_thread_blocker;
|
||||
BAN::HashMap<BAN::RefPtr<Inode>, uint32_t, InodeRefPtrHash> m_ready_events;
|
||||
BAN::HashMap<BAN::RefPtr<Inode>, epoll_event, InodeRefPtrHash> m_listening_events;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -51,6 +51,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hangup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
// Returns maximum number of data blocks in use
|
||||
|
||||
@@ -49,6 +49,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hangup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
FATInode(FATFS& fs, const FAT::DirectoryEntry& entry, ino_t ino, uint32_t block_count)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/ByteSpan.h>
|
||||
#include <BAN/LinkedList.h>
|
||||
#include <BAN/RefPtr.h>
|
||||
#include <BAN/String.h>
|
||||
#include <BAN/StringView.h>
|
||||
@@ -19,9 +20,8 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class FileSystem;
|
||||
|
||||
class FileBackedRegion;
|
||||
class FileSystem;
|
||||
class SharedFileData;
|
||||
|
||||
class Inode : public BAN::RefCounted<Inode>
|
||||
@@ -85,6 +85,7 @@ namespace Kernel
|
||||
virtual dev_t rdev() const = 0;
|
||||
|
||||
virtual bool is_device() const { return false; }
|
||||
virtual bool is_epoll() const { return false; }
|
||||
virtual bool is_pipe() const { return false; }
|
||||
virtual bool is_tty() const { return false; }
|
||||
|
||||
@@ -123,9 +124,14 @@ namespace Kernel
|
||||
bool can_read() const;
|
||||
bool can_write() const;
|
||||
bool has_error() const;
|
||||
bool has_hangup() const;
|
||||
|
||||
BAN::ErrorOr<long> ioctl(int request, void* arg);
|
||||
|
||||
BAN::ErrorOr<void> add_epoll(class Epoll*);
|
||||
void del_epoll(class Epoll*);
|
||||
void epoll_notify(uint32_t event);
|
||||
|
||||
protected:
|
||||
// Directory API
|
||||
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
@@ -160,6 +166,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const = 0;
|
||||
virtual bool can_write_impl() const = 0;
|
||||
virtual bool has_error_impl() const = 0;
|
||||
virtual bool has_hangup_impl() const = 0;
|
||||
|
||||
virtual BAN::ErrorOr<long> ioctl_impl(int, void*) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
|
||||
@@ -168,6 +175,7 @@ namespace Kernel
|
||||
|
||||
private:
|
||||
BAN::WeakPtr<SharedFileData> m_shared_region;
|
||||
BAN::LinkedList<class Epoll*> m_epolls;
|
||||
friend class FileBackedRegion;
|
||||
friend class OpenFileDescriptorSet;
|
||||
friend class SharedFileData;
|
||||
|
||||
@@ -40,6 +40,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return m_buffer_size > 0; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hangup_impl() const override { return m_writing_count == 0; }
|
||||
|
||||
private:
|
||||
Pipe(const Credentials&);
|
||||
|
||||
@@ -47,6 +47,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hangup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
ProcROProcessInode(Process&, size_t (Process::*)(off_t, BAN::ByteSpan) const, TmpFileSystem&, const TmpInodeInfo&);
|
||||
@@ -72,6 +73,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hangup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
ProcROInode(size_t (*callback)(off_t, BAN::ByteSpan), TmpFileSystem&, const TmpInodeInfo&);
|
||||
|
||||
@@ -80,6 +80,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hangup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
TmpFileInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
|
||||
@@ -102,6 +103,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hangup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
TmpSocketInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
|
||||
@@ -123,6 +125,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hangup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
TmpSymlinkInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
|
||||
@@ -153,6 +156,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hangup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
template<TmpFuncs::for_each_valid_entry_callback F>
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Kernel
|
||||
bool can_read_impl() const override { SpinLockGuard _(m_event_lock); return m_event_count > 0; }
|
||||
bool can_write_impl() const override { return false; }
|
||||
bool has_error_impl() const override { return false; }
|
||||
|
||||
bool has_hangup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
BAN::ErrorOr<size_t> read_non_block(BAN::ByteSpan);
|
||||
@@ -64,7 +64,7 @@ namespace Kernel
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<KeyboardDevice>> create(mode_t mode, uid_t uid, gid_t gid);
|
||||
|
||||
void notify() { m_thread_blocker.unblock(); }
|
||||
void notify();
|
||||
|
||||
private:
|
||||
KeyboardDevice(mode_t mode, uid_t uid, gid_t gid);
|
||||
@@ -73,6 +73,7 @@ namespace Kernel
|
||||
bool can_read_impl() const override;
|
||||
bool can_write_impl() const override { return false; }
|
||||
bool has_error_impl() const override { return false; }
|
||||
bool has_hangup_impl() const override { return false; }
|
||||
|
||||
BAN::StringView name() const final override { return m_name; }
|
||||
dev_t rdev() const final override { return m_rdev; }
|
||||
@@ -90,7 +91,7 @@ namespace Kernel
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<MouseDevice>> create(mode_t mode, uid_t uid, gid_t gid);
|
||||
|
||||
void notify() { m_thread_blocker.unblock(); }
|
||||
void notify();
|
||||
|
||||
private:
|
||||
MouseDevice(mode_t mode, uid_t uid, gid_t gid);
|
||||
@@ -99,6 +100,7 @@ namespace Kernel
|
||||
bool can_read_impl() const override;
|
||||
bool can_write_impl() const override { return false; }
|
||||
bool has_error_impl() const override { return false; }
|
||||
bool has_hangup_impl() const override { return false; }
|
||||
|
||||
BAN::StringView name() const final override { return m_name; }
|
||||
dev_t rdev() const final override { return m_rdev; }
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace Kernel
|
||||
virtual bool link_up() override { return m_link_up; }
|
||||
virtual int link_speed() override;
|
||||
|
||||
virtual size_t payload_mtu() const { return E1000_RX_BUFFER_SIZE - sizeof(EthernetHeader); }
|
||||
virtual size_t payload_mtu() const override { return E1000_RX_BUFFER_SIZE - sizeof(EthernetHeader); }
|
||||
|
||||
virtual void handle_irq() final override;
|
||||
|
||||
@@ -50,6 +50,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hangup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
BAN::ErrorOr<void> read_mac_address();
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace Kernel
|
||||
bool can_read_impl() const override { return false; }
|
||||
bool can_write_impl() const override { return false; }
|
||||
bool has_error_impl() const override { return false; }
|
||||
bool has_hangup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
SpinLock m_buffer_lock;
|
||||
|
||||
@@ -36,6 +36,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hangup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
BAN::ErrorOr<void> reset();
|
||||
|
||||
@@ -67,6 +67,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override;
|
||||
virtual bool can_write_impl() const override;
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hangup_impl() const override;
|
||||
|
||||
private:
|
||||
enum class State
|
||||
|
||||
@@ -40,6 +40,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return !m_packets.empty(); }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hangup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
UDPSocket(NetworkLayer&, const Socket::Info&);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/CircularQueue.h>
|
||||
#include <BAN/Queue.h>
|
||||
#include <BAN/WeakPtr.h>
|
||||
#include <kernel/FS/Socket.h>
|
||||
@@ -28,6 +29,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override;
|
||||
virtual bool can_write_impl() const override;
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hangup_impl() const override;
|
||||
|
||||
private:
|
||||
UnixDomainSocket(Socket::Type, const Socket::Info&);
|
||||
@@ -48,7 +50,7 @@ namespace Kernel
|
||||
mutable BAN::Atomic<bool> target_closed { false };
|
||||
BAN::WeakPtr<UnixDomainSocket> connection;
|
||||
BAN::Queue<BAN::RefPtr<UnixDomainSocket>> pending_connections;
|
||||
ThreadBlocker pending_thread_blocker;
|
||||
ThreadBlocker pending_thread_blocker;
|
||||
SpinLock pending_lock;
|
||||
};
|
||||
|
||||
@@ -67,7 +69,7 @@ namespace Kernel
|
||||
size_t m_packet_size_total { 0 };
|
||||
BAN::UniqPtr<VirtualRange> m_packet_buffer;
|
||||
SpinLock m_packet_lock;
|
||||
ThreadBlocker m_packet_thread_blocker;
|
||||
ThreadBlocker m_packet_thread_blocker;
|
||||
|
||||
friend class BAN::RefPtr<UnixDomainSocket>;
|
||||
};
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include <sys/time.h>
|
||||
#include <termios.h>
|
||||
|
||||
struct epoll_event;
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
@@ -130,6 +132,10 @@ namespace Kernel
|
||||
|
||||
BAN::ErrorOr<long> sys_pselect(sys_pselect_t* arguments);
|
||||
|
||||
BAN::ErrorOr<long> sys_epoll_create1(int flags);
|
||||
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_pipe(int fildes[2]);
|
||||
BAN::ErrorOr<long> sys_dup2(int fildes, int fildes2);
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hangup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
NVMeController(PCI::Device& pci_device);
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Kernel
|
||||
virtual uint64_t total_size() const override { return m_block_size * m_block_count; }
|
||||
|
||||
virtual dev_t rdev() const override { return m_rdev; }
|
||||
virtual BAN::StringView name() const { return m_name; }
|
||||
virtual BAN::StringView name() const override { return m_name; }
|
||||
|
||||
private:
|
||||
NVMeNamespace(NVMeController&, uint32_t ns_index, uint32_t nsid, uint64_t block_count, uint32_t block_size);
|
||||
|
||||
@@ -53,6 +53,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hangup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
const dev_t m_rdev;
|
||||
|
||||
@@ -47,6 +47,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hangup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
Mutex m_mutex;
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace Kernel
|
||||
bool can_read_impl() const override { SpinLockGuard _(m_buffer_lock); return m_buffer_size > 0; }
|
||||
bool can_write_impl() const override { SpinLockGuard _(m_buffer_lock); return m_buffer_size < m_buffer->size(); }
|
||||
bool has_error_impl() const override { return false; }
|
||||
bool has_hangup_impl() const override { return !m_slave.valid(); }
|
||||
|
||||
BAN::ErrorOr<long> ioctl_impl(int, void*) override;
|
||||
|
||||
@@ -63,6 +64,8 @@ namespace Kernel
|
||||
protected:
|
||||
bool putchar_impl(uint8_t ch) override;
|
||||
|
||||
bool has_hangup_impl() const override { return !m_master.valid(); }
|
||||
|
||||
BAN::ErrorOr<long> ioctl_impl(int, void*) override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -54,6 +54,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return m_output.flush; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hangup_impl() const override { return false; }
|
||||
|
||||
protected:
|
||||
TTY(mode_t mode, uid_t uid, gid_t gid);
|
||||
|
||||
Reference in New Issue
Block a user