Kernel: Remove the big inode lock
This moves locking to the inodes themselves which allows reducing lock times significantly. Main inodes (ext2 and tmpfs) still do contain a single big mutex that gets locked during operations but now we have the architecture to optimize these.
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <BAN/HashMap.h>
|
#include <BAN/HashMap.h>
|
||||||
#include <kernel/FS/Inode.h>
|
#include <kernel/FS/Inode.h>
|
||||||
|
#include <kernel/Lock/Mutex.h>
|
||||||
|
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
|
|
||||||
@@ -90,6 +91,7 @@ namespace Kernel
|
|||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Mutex m_mutex;
|
||||||
ThreadBlocker m_thread_blocker;
|
ThreadBlocker m_thread_blocker;
|
||||||
SpinLock m_ready_lock;
|
SpinLock m_ready_lock;
|
||||||
BAN::HashMap<BAN::RefPtr<Inode>, uint32_t> m_ready_events;
|
BAN::HashMap<BAN::RefPtr<Inode>, uint32_t> m_ready_events;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <kernel/FS/Inode.h>
|
#include <kernel/FS/Inode.h>
|
||||||
|
#include <kernel/Lock/Mutex.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
@@ -44,8 +45,9 @@ namespace Kernel
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
const bool m_is_semaphore;
|
const bool m_is_semaphore;
|
||||||
uint64_t m_value;
|
BAN::Atomic<uint64_t> m_value;
|
||||||
|
|
||||||
|
Mutex m_mutex;
|
||||||
ThreadBlocker m_thread_blocker;
|
ThreadBlocker m_thread_blocker;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <BAN/StringView.h>
|
#include <BAN/StringView.h>
|
||||||
#include <kernel/FS/Ext2/Definitions.h>
|
#include <kernel/FS/Ext2/Definitions.h>
|
||||||
#include <kernel/FS/Inode.h>
|
#include <kernel/FS/Inode.h>
|
||||||
|
#include <kernel/Lock/Mutex.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
@@ -110,6 +111,9 @@ namespace Kernel
|
|||||||
Ext2::Inode m_inode;
|
Ext2::Inode m_inode;
|
||||||
const uint32_t m_ino;
|
const uint32_t m_ino;
|
||||||
|
|
||||||
|
// TODO: try to reduce locking or replace this with rwlock(?)
|
||||||
|
Mutex m_lock;
|
||||||
|
|
||||||
friend class Ext2FS;
|
friend class Ext2FS;
|
||||||
friend class BAN::RefPtr<Ext2Inode>;
|
friend class BAN::RefPtr<Ext2Inode>;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
|
|
||||||
#include <kernel/Credentials.h>
|
#include <kernel/Credentials.h>
|
||||||
#include <kernel/Debug.h>
|
#include <kernel/Debug.h>
|
||||||
#include <kernel/Lock/Mutex.h>
|
|
||||||
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
@@ -183,11 +182,10 @@ namespace Kernel
|
|||||||
|
|
||||||
virtual BAN::ErrorOr<long> ioctl_impl(int, void*) { return BAN::Error::from_errno(ENOTSUP); }
|
virtual BAN::ErrorOr<long> ioctl_impl(int, void*) { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
|
|
||||||
protected:
|
|
||||||
mutable PriorityMutex m_mutex;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
SpinLock m_shared_region_lock;
|
||||||
BAN::WeakPtr<SharedFileData> m_shared_region;
|
BAN::WeakPtr<SharedFileData> m_shared_region;
|
||||||
|
|
||||||
SpinLock m_epoll_lock;
|
SpinLock m_epoll_lock;
|
||||||
BAN::LinkedList<class Epoll*> m_epolls;
|
BAN::LinkedList<class Epoll*> m_epolls;
|
||||||
friend class Epoll;
|
friend class Epoll;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <BAN/Array.h>
|
|
||||||
#include <kernel/FS/Inode.h>
|
#include <kernel/FS/Inode.h>
|
||||||
|
#include <kernel/Lock/Mutex.h>
|
||||||
#include <kernel/Memory/ByteRingBuffer.h>
|
#include <kernel/Memory/ByteRingBuffer.h>
|
||||||
#include <kernel/ThreadBlocker.h>
|
#include <kernel/ThreadBlocker.h>
|
||||||
|
|
||||||
@@ -53,6 +53,8 @@ namespace Kernel
|
|||||||
timespec m_atime {};
|
timespec m_atime {};
|
||||||
timespec m_mtime {};
|
timespec m_mtime {};
|
||||||
timespec m_ctime {};
|
timespec m_ctime {};
|
||||||
|
|
||||||
|
Mutex m_mutex;
|
||||||
ThreadBlocker m_thread_blocker;
|
ThreadBlocker m_thread_blocker;
|
||||||
|
|
||||||
BAN::UniqPtr<ByteRingBuffer> m_buffer;
|
BAN::UniqPtr<ByteRingBuffer> m_buffer;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <BAN/Optional.h>
|
#include <BAN/Optional.h>
|
||||||
#include <kernel/FS/Inode.h>
|
#include <kernel/FS/Inode.h>
|
||||||
#include <kernel/FS/TmpFS/Definitions.h>
|
#include <kernel/FS/TmpFS/Definitions.h>
|
||||||
|
#include <kernel/Lock/Mutex.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
@@ -53,22 +54,25 @@ namespace Kernel
|
|||||||
virtual BAN::ErrorOr<void> fsync_impl() override { return {}; }
|
virtual BAN::ErrorOr<void> fsync_impl() override { return {}; }
|
||||||
|
|
||||||
void sync();
|
void sync();
|
||||||
virtual BAN::ErrorOr<void> prepare_unlink() { return {}; };
|
virtual BAN::ErrorOr<void> prepare_unlink_no_lock() { return {}; };
|
||||||
|
|
||||||
void free_all_blocks();
|
void free_all_blocks();
|
||||||
void free_indirect_blocks(size_t block, uint32_t depth);
|
void free_indirect_blocks_no_lock(size_t block, uint32_t depth);
|
||||||
|
|
||||||
BAN::Optional<size_t> block_index(size_t data_block_index);
|
BAN::Optional<size_t> block_index(size_t data_block_index);
|
||||||
BAN::Optional<size_t> block_index_from_indirect(size_t block, size_t index, uint32_t depth);
|
BAN::Optional<size_t> block_index_from_indirect_no_lock(size_t block, size_t index, uint32_t depth);
|
||||||
|
|
||||||
BAN::ErrorOr<size_t> block_index_with_allocation(size_t data_block_index);
|
BAN::ErrorOr<size_t> block_index_with_allocation(size_t data_block_index);
|
||||||
BAN::ErrorOr<size_t> block_index_from_indirect_with_allocation(size_t& block, size_t index, uint32_t depth);
|
BAN::ErrorOr<size_t> block_index_from_indirect_with_allocation_no_lock(size_t& block, size_t index, uint32_t depth);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TmpFileSystem& m_fs;
|
TmpFileSystem& m_fs;
|
||||||
TmpInodeInfo m_inode_info;
|
TmpInodeInfo m_inode_info;
|
||||||
const ino_t m_ino;
|
const ino_t m_ino;
|
||||||
|
|
||||||
|
// TODO: try to reduce locking or replace this with rwlock(?)
|
||||||
|
Mutex m_lock;
|
||||||
|
|
||||||
// has to be able to increase link count
|
// has to be able to increase link count
|
||||||
friend class TmpDirectoryInode;
|
friend class TmpDirectoryInode;
|
||||||
};
|
};
|
||||||
@@ -149,7 +153,7 @@ namespace Kernel
|
|||||||
protected:
|
protected:
|
||||||
TmpDirectoryInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
|
TmpDirectoryInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
|
||||||
|
|
||||||
virtual BAN::ErrorOr<void> prepare_unlink() override;
|
virtual BAN::ErrorOr<void> prepare_unlink_no_lock() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) override final;
|
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) override final;
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ namespace Kernel
|
|||||||
uint32_t lock_depth() const override { return m_lock_depth; }
|
uint32_t lock_depth() const override { return m_lock_depth; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SpinLock& m_lock;
|
Lock& m_lock;
|
||||||
uint32_t m_lock_depth { 0 };
|
uint32_t m_lock_depth { 0 };
|
||||||
InterruptState m_state;
|
InterruptState m_state;
|
||||||
const pid_t m_locker;
|
const pid_t m_locker;
|
||||||
|
|||||||
@@ -181,6 +181,7 @@ namespace Kernel
|
|||||||
|
|
||||||
uint64_t m_time_wait_start_ms { 0 };
|
uint64_t m_time_wait_start_ms { 0 };
|
||||||
|
|
||||||
|
mutable Mutex m_mutex;
|
||||||
ThreadBlocker m_thread_blocker;
|
ThreadBlocker m_thread_blocker;
|
||||||
|
|
||||||
RecvWindowInfo m_recv_window;
|
RecvWindowInfo m_recv_window;
|
||||||
|
|||||||
@@ -66,9 +66,12 @@ namespace Kernel
|
|||||||
SpinLock m_packet_lock;
|
SpinLock m_packet_lock;
|
||||||
ThreadBlocker m_packet_thread_blocker;
|
ThreadBlocker m_packet_thread_blocker;
|
||||||
|
|
||||||
|
SpinLock m_peer_address_lock;
|
||||||
sockaddr_storage m_peer_address {};
|
sockaddr_storage m_peer_address {};
|
||||||
socklen_t m_peer_address_len { 0 };
|
socklen_t m_peer_address_len { 0 };
|
||||||
|
|
||||||
|
Mutex m_bind_lock;
|
||||||
|
|
||||||
friend class BAN::RefPtr<UDPSocket>;
|
friend class BAN::RefPtr<UDPSocket>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -43,15 +43,16 @@ namespace Kernel
|
|||||||
UnixDomainSocket(Socket::Type, const Socket::Info&);
|
UnixDomainSocket(Socket::Type, const Socket::Info&);
|
||||||
~UnixDomainSocket();
|
~UnixDomainSocket();
|
||||||
|
|
||||||
bool is_bound() const { return !m_bound_file.canonical_path.empty(); }
|
bool is_bound() const;
|
||||||
bool is_bound_to_unused() const { return !m_bound_file.inode; }
|
bool is_bound_to_unused() const;
|
||||||
|
BAN::ErrorOr<void> bind_to_unused_if_not_bound();
|
||||||
|
|
||||||
bool is_streaming() const;
|
bool is_streaming() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct ConnectionInfo
|
struct ConnectionInfo
|
||||||
{
|
{
|
||||||
bool listening { false };
|
BAN::Atomic<bool> listening { false };
|
||||||
BAN::Atomic<bool> connection_done { false };
|
BAN::Atomic<bool> connection_done { false };
|
||||||
mutable BAN::Atomic<bool> target_closed { false };
|
mutable BAN::Atomic<bool> target_closed { false };
|
||||||
BAN::WeakPtr<UnixDomainSocket> connection;
|
BAN::WeakPtr<UnixDomainSocket> connection;
|
||||||
@@ -62,6 +63,7 @@ namespace Kernel
|
|||||||
|
|
||||||
struct ConnectionlessInfo
|
struct ConnectionlessInfo
|
||||||
{
|
{
|
||||||
|
SpinLock lock;
|
||||||
BAN::String peer_address;
|
BAN::String peer_address;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -76,7 +78,9 @@ namespace Kernel
|
|||||||
BAN::ErrorOr<size_t> add_packet(const msghdr&, PacketInfo&&, bool dont_block);
|
BAN::ErrorOr<size_t> add_packet(const msghdr&, PacketInfo&&, bool dont_block);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Socket::Type m_socket_type;
|
const Socket::Type m_socket_type;
|
||||||
|
|
||||||
|
mutable Mutex m_bind_mutex;
|
||||||
VirtualFileSystem::File m_bound_file;
|
VirtualFileSystem::File m_bound_file;
|
||||||
|
|
||||||
BAN::Variant<ConnectionInfo, ConnectionlessInfo> m_info;
|
BAN::Variant<ConnectionInfo, ConnectionlessInfo> m_info;
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ namespace Kernel
|
|||||||
bool putchar_impl(uint8_t ch) override;
|
bool putchar_impl(uint8_t ch) override;
|
||||||
|
|
||||||
bool can_write_impl() const override;
|
bool can_write_impl() const override;
|
||||||
bool has_hungup_impl() const override { return !m_master.valid(); }
|
bool has_hungup_impl() const override { return master_has_closed(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PseudoTerminalSlave(BAN::String&& name, uint32_t number, mode_t, uid_t, gid_t);
|
PseudoTerminalSlave(BAN::String&& name, uint32_t number, mode_t, uid_t, gid_t);
|
||||||
|
|||||||
@@ -46,12 +46,14 @@ namespace Kernel
|
|||||||
|
|
||||||
static void keyboard_task(void*);
|
static void keyboard_task(void*);
|
||||||
static void initialize_devices();
|
static void initialize_devices();
|
||||||
|
|
||||||
|
bool should_receive_input() const { return m_tty_ctrl.receive_input; }
|
||||||
|
void on_key_event(LibInput::RawKeyEvent);
|
||||||
void on_key_event(LibInput::KeyEvent);
|
void on_key_event(LibInput::KeyEvent);
|
||||||
void handle_input_byte(uint8_t);
|
void handle_input_byte(uint8_t);
|
||||||
|
|
||||||
void get_termios(termios* termios) { *termios = m_termios; }
|
void get_termios(termios*);
|
||||||
// FIXME: validate termios
|
BAN::ErrorOr<void> set_termios(const termios*);
|
||||||
BAN::ErrorOr<void> set_termios(const termios* termios) { m_termios = *termios; return {}; }
|
|
||||||
|
|
||||||
virtual bool is_tty() const override { return true; }
|
virtual bool is_tty() const override { return true; }
|
||||||
|
|
||||||
@@ -85,9 +87,6 @@ namespace Kernel
|
|||||||
bool putchar(uint8_t ch);
|
bool putchar(uint8_t ch);
|
||||||
void do_backspace();
|
void do_backspace();
|
||||||
|
|
||||||
protected:
|
|
||||||
termios m_termios;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const dev_t m_rdev;
|
const dev_t m_rdev;
|
||||||
|
|
||||||
@@ -95,23 +94,27 @@ namespace Kernel
|
|||||||
|
|
||||||
struct tty_ctrl_t
|
struct tty_ctrl_t
|
||||||
{
|
{
|
||||||
bool draw_graphics { true };
|
BAN::Atomic<bool> draw_graphics { true };
|
||||||
bool receive_input { true };
|
BAN::Atomic<bool> receive_input { true };
|
||||||
ThreadBlocker thread_blocker;
|
|
||||||
};
|
};
|
||||||
tty_ctrl_t m_tty_ctrl;
|
tty_ctrl_t m_tty_ctrl;
|
||||||
|
|
||||||
struct Buffer
|
struct Buffer
|
||||||
{
|
{
|
||||||
BAN::UniqPtr<ByteRingBuffer> buffer;
|
BAN::UniqPtr<ByteRingBuffer> buffer;
|
||||||
bool flush { false };
|
BAN::Atomic<bool> flush { false };
|
||||||
ThreadBlocker thread_blocker;
|
ThreadBlocker thread_blocker;
|
||||||
};
|
};
|
||||||
Buffer m_output;
|
Buffer m_output;
|
||||||
|
|
||||||
winsize m_winsize {};
|
winsize m_winsize {};
|
||||||
|
|
||||||
|
SpinLock m_termios_lock;
|
||||||
|
termios m_termios;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
Mutex m_mutex;
|
||||||
|
|
||||||
RecursiveSpinLock m_write_lock;
|
RecursiveSpinLock m_write_lock;
|
||||||
ThreadBlocker m_write_blocker;
|
ThreadBlocker m_write_blocker;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -62,8 +62,8 @@ namespace Kernel
|
|||||||
Mutex m_command_mutex;
|
Mutex m_command_mutex;
|
||||||
|
|
||||||
BAN::Atomic<bool> m_has_initialized_leds { false };
|
BAN::Atomic<bool> m_has_initialized_leds { false };
|
||||||
uint8_t m_led_state { 0b0001 };
|
BAN::Atomic<uint8_t> m_led_state { 0b0001 };
|
||||||
uint8_t m_rumble_strength { 0x00 };
|
BAN::Atomic<uint8_t> m_rumble_strength { 0x00 };
|
||||||
|
|
||||||
friend class BAN::RefPtr<USBJoystick>;
|
friend class BAN::RefPtr<USBJoystick>;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ namespace Kernel::ACPI
|
|||||||
m_last_value = target_conv.value().as.integer.value;
|
m_last_value = target_conv.value().as.integer.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto target_str = TRY(BAN::String::formatted("{}", m_last_value));
|
auto target_str = TRY(BAN::String::formatted("{}", m_last_value.load()));
|
||||||
|
|
||||||
if (static_cast<size_t>(offset) >= target_str.size())
|
if (static_cast<size_t>(offset) >= target_str.size())
|
||||||
return 0;
|
return 0;
|
||||||
@@ -67,8 +67,8 @@ namespace Kernel::ACPI
|
|||||||
return ncopy;
|
return ncopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override { return BAN::Error::from_errno(EINVAL); }
|
BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override { return BAN::Error::from_errno(EINVAL); }
|
||||||
BAN::ErrorOr<void> truncate_impl(size_t) override { return BAN::Error::from_errno(EINVAL); }
|
BAN::ErrorOr<void> truncate_impl(size_t) override { return BAN::Error::from_errno(EINVAL); }
|
||||||
|
|
||||||
bool can_read_impl() const override { return true; }
|
bool can_read_impl() const override { return true; }
|
||||||
bool can_write_impl() const override { return false; }
|
bool can_write_impl() const override { return false; }
|
||||||
@@ -90,8 +90,8 @@ namespace Kernel::ACPI
|
|||||||
AML::NameString m_method_name;
|
AML::NameString m_method_name;
|
||||||
size_t m_result_index;
|
size_t m_result_index;
|
||||||
|
|
||||||
uint64_t m_last_read_ms = 0;
|
BAN::Atomic<uint64_t> m_last_read_ms = 0;
|
||||||
uint64_t m_last_value = 0;
|
BAN::Atomic<uint64_t> m_last_value = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
BAN::ErrorOr<void> BatterySystem::initialize(AML::Namespace& acpi_namespace)
|
BAN::ErrorOr<void> BatterySystem::initialize(AML::Namespace& acpi_namespace)
|
||||||
|
|||||||
@@ -153,8 +153,6 @@ namespace Kernel
|
|||||||
REMOVE_IT();
|
REMOVE_IT();
|
||||||
|
|
||||||
{
|
{
|
||||||
LockGuard inode_locker(inode->m_mutex);
|
|
||||||
|
|
||||||
#define CHECK_EVENT_BIT(mask, func) \
|
#define CHECK_EVENT_BIT(mask, func) \
|
||||||
if ((events & mask) && !inode->func()) \
|
if ((events & mask) && !inode->func()) \
|
||||||
events &= ~mask;
|
events &= ~mask;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include <kernel/FS/EventFD.h>
|
#include <kernel/FS/EventFD.h>
|
||||||
|
#include <kernel/Lock/LockGuard.h>
|
||||||
|
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
|
|
||||||
@@ -18,16 +19,20 @@ namespace Kernel
|
|||||||
if (buffer.size() < sizeof(uint64_t))
|
if (buffer.size() < sizeof(uint64_t))
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
|
LockGuard _(m_mutex);
|
||||||
|
|
||||||
while (m_value == 0)
|
while (m_value == 0)
|
||||||
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex));
|
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex));
|
||||||
|
|
||||||
const uint64_t read_value = m_is_semaphore ? 1 : m_value;
|
const uint64_t read_value = m_is_semaphore ? 1 : m_value.load();
|
||||||
m_value -= read_value;
|
m_value -= read_value;
|
||||||
|
|
||||||
buffer.as<uint64_t>() = read_value;
|
buffer.as<uint64_t>() = read_value;
|
||||||
|
|
||||||
epoll_notify(EPOLLOUT);
|
epoll_notify(EPOLLOUT);
|
||||||
|
|
||||||
|
m_thread_blocker.unblock();
|
||||||
|
|
||||||
return sizeof(uint64_t);
|
return sizeof(uint64_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,6 +45,8 @@ namespace Kernel
|
|||||||
if (write_value == UINT64_MAX)
|
if (write_value == UINT64_MAX)
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
|
LockGuard _(m_mutex);
|
||||||
|
|
||||||
while (m_value + write_value < m_value)
|
while (m_value + write_value < m_value)
|
||||||
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex));
|
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex));
|
||||||
|
|
||||||
@@ -48,6 +55,8 @@ namespace Kernel
|
|||||||
if (m_value > 0)
|
if (m_value > 0)
|
||||||
epoll_notify(EPOLLIN);
|
epoll_notify(EPOLLIN);
|
||||||
|
|
||||||
|
m_thread_blocker.unblock();
|
||||||
|
|
||||||
return sizeof(uint64_t);
|
return sizeof(uint64_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,8 @@ namespace Kernel
|
|||||||
const uint32_t inode_blocks_per_fs_block = blksize() / 512;
|
const uint32_t inode_blocks_per_fs_block = blksize() / 512;
|
||||||
const uint32_t indices_per_fs_block = blksize() / sizeof(uint32_t);
|
const uint32_t indices_per_fs_block = blksize() / sizeof(uint32_t);
|
||||||
|
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
if (block == 0 && !allocate)
|
if (block == 0 && !allocate)
|
||||||
return BAN::Optional<uint32_t>();
|
return BAN::Optional<uint32_t>();
|
||||||
|
|
||||||
@@ -115,6 +117,8 @@ namespace Kernel
|
|||||||
const uint32_t inode_blocks_per_fs_block = blksize() / 512;
|
const uint32_t inode_blocks_per_fs_block = blksize() / 512;
|
||||||
const uint32_t indices_per_block = blksize() / sizeof(uint32_t);
|
const uint32_t indices_per_block = blksize() / sizeof(uint32_t);
|
||||||
|
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
if (data_block_index < 12)
|
if (data_block_index < 12)
|
||||||
{
|
{
|
||||||
if (m_inode.block[data_block_index] != 0)
|
if (m_inode.block[data_block_index] != 0)
|
||||||
@@ -152,6 +156,9 @@ namespace Kernel
|
|||||||
BAN::ErrorOr<BAN::String> Ext2Inode::link_target_impl()
|
BAN::ErrorOr<BAN::String> Ext2Inode::link_target_impl()
|
||||||
{
|
{
|
||||||
ASSERT(mode().iflnk());
|
ASSERT(mode().iflnk());
|
||||||
|
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
if (m_inode.size < sizeof(m_inode.block))
|
if (m_inode.size < sizeof(m_inode.block))
|
||||||
{
|
{
|
||||||
BAN::String result;
|
BAN::String result;
|
||||||
@@ -168,6 +175,9 @@ namespace Kernel
|
|||||||
BAN::ErrorOr<void> Ext2Inode::set_link_target_impl(BAN::StringView target)
|
BAN::ErrorOr<void> Ext2Inode::set_link_target_impl(BAN::StringView target)
|
||||||
{
|
{
|
||||||
ASSERT(mode().iflnk());
|
ASSERT(mode().iflnk());
|
||||||
|
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
if (target.size() < sizeof(m_inode.block))
|
if (target.size() < sizeof(m_inode.block))
|
||||||
{
|
{
|
||||||
if (m_inode.size >= sizeof(m_inode.block))
|
if (m_inode.size >= sizeof(m_inode.block))
|
||||||
@@ -194,10 +204,12 @@ namespace Kernel
|
|||||||
if (static_cast<BAN::make_unsigned_t<decltype(offset)>>(offset) >= UINT32_MAX || buffer.size() >= UINT32_MAX || buffer.size() >= (size_t)(UINT32_MAX - offset))
|
if (static_cast<BAN::make_unsigned_t<decltype(offset)>>(offset) >= UINT32_MAX || buffer.size() >= UINT32_MAX || buffer.size() >= (size_t)(UINT32_MAX - offset))
|
||||||
return BAN::Error::from_errno(EOVERFLOW);
|
return BAN::Error::from_errno(EOVERFLOW);
|
||||||
|
|
||||||
|
LockGuard _0(m_lock);
|
||||||
|
|
||||||
if (static_cast<BAN::make_unsigned_t<decltype(offset)>>(offset) >= m_inode.size)
|
if (static_cast<BAN::make_unsigned_t<decltype(offset)>>(offset) >= m_inode.size)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ScopedSync _(*this);
|
ScopedSync _1(*this);
|
||||||
|
|
||||||
uint32_t count = buffer.size();
|
uint32_t count = buffer.size();
|
||||||
if (offset + buffer.size() > m_inode.size)
|
if (offset + buffer.size() > m_inode.size)
|
||||||
@@ -240,6 +252,8 @@ namespace Kernel
|
|||||||
if (static_cast<BAN::make_unsigned_t<decltype(offset)>>(offset) >= UINT32_MAX || buffer.size() >= UINT32_MAX || buffer.size() >= (size_t)(UINT32_MAX - offset))
|
if (static_cast<BAN::make_unsigned_t<decltype(offset)>>(offset) >= UINT32_MAX || buffer.size() >= UINT32_MAX || buffer.size() >= (size_t)(UINT32_MAX - offset))
|
||||||
return BAN::Error::from_errno(EOVERFLOW);
|
return BAN::Error::from_errno(EOVERFLOW);
|
||||||
|
|
||||||
|
LockGuard _0(m_lock);
|
||||||
|
|
||||||
if (m_inode.size < offset + buffer.size())
|
if (m_inode.size < offset + buffer.size())
|
||||||
TRY(truncate_impl(offset + buffer.size()));
|
TRY(truncate_impl(offset + buffer.size()));
|
||||||
|
|
||||||
@@ -300,6 +314,8 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> Ext2Inode::truncate_impl(size_t new_size)
|
BAN::ErrorOr<void> Ext2Inode::truncate_impl(size_t new_size)
|
||||||
{
|
{
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
if (m_inode.size == new_size)
|
if (m_inode.size == new_size)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
@@ -320,6 +336,10 @@ namespace Kernel
|
|||||||
BAN::ErrorOr<void> Ext2Inode::chmod_impl(mode_t mode)
|
BAN::ErrorOr<void> Ext2Inode::chmod_impl(mode_t mode)
|
||||||
{
|
{
|
||||||
ASSERT((mode & Inode::Mode::TYPE_MASK) == 0);
|
ASSERT((mode & Inode::Mode::TYPE_MASK) == 0);
|
||||||
|
|
||||||
|
// TODO: this could be atomic
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
if (m_inode.mode == mode)
|
if (m_inode.mode == mode)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
@@ -337,6 +357,9 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> Ext2Inode::chown_impl(uid_t uid, gid_t gid)
|
BAN::ErrorOr<void> Ext2Inode::chown_impl(uid_t uid, gid_t gid)
|
||||||
{
|
{
|
||||||
|
// TODO: this could be atomic
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
if (m_inode.uid == uid && m_inode.gid == gid)
|
if (m_inode.uid == uid && m_inode.gid == gid)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
@@ -357,6 +380,9 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> Ext2Inode::utimens_impl(const timespec times[2])
|
BAN::ErrorOr<void> Ext2Inode::utimens_impl(const timespec times[2])
|
||||||
{
|
{
|
||||||
|
// TODO: this could be atomic
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
const uint32_t old_times[2] {
|
const uint32_t old_times[2] {
|
||||||
m_inode.atime,
|
m_inode.atime,
|
||||||
m_inode.mtime,
|
m_inode.mtime,
|
||||||
@@ -379,6 +405,7 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> Ext2Inode::fsync_impl()
|
BAN::ErrorOr<void> Ext2Inode::fsync_impl()
|
||||||
{
|
{
|
||||||
|
LockGuard _(m_lock);
|
||||||
for (size_t i = 0; i < max_used_data_block_count(); i++)
|
for (size_t i = 0; i < max_used_data_block_count(); i++)
|
||||||
if (const auto fs_block = TRY(fs_block_of_data_block_index(i, false)); fs_block.has_value())
|
if (const auto fs_block = TRY(fs_block_of_data_block_index(i, false)); fs_block.has_value())
|
||||||
TRY(m_fs.sync_block(fs_block.value()));
|
TRY(m_fs.sync_block(fs_block.value()));
|
||||||
@@ -389,6 +416,8 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
ASSERT(block);
|
ASSERT(block);
|
||||||
|
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
if (depth == 0)
|
if (depth == 0)
|
||||||
{
|
{
|
||||||
TRY(m_fs.release_block(block));
|
TRY(m_fs.release_block(block));
|
||||||
@@ -413,6 +442,8 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> Ext2Inode::cleanup_data_blocks()
|
BAN::ErrorOr<void> Ext2Inode::cleanup_data_blocks()
|
||||||
{
|
{
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
if (mode().iflnk() && (size_t)size() < sizeof(m_inode.block))
|
if (mode().iflnk() && (size_t)size() < sizeof(m_inode.block))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
@@ -451,6 +482,8 @@ done:
|
|||||||
ASSERT(mode().ifdir());
|
ASSERT(mode().ifdir());
|
||||||
ASSERT(offset >= 0);
|
ASSERT(offset >= 0);
|
||||||
|
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
if (static_cast<BAN::make_unsigned_t<decltype(offset)>>(offset) >= max_used_data_block_count())
|
if (static_cast<BAN::make_unsigned_t<decltype(offset)>>(offset) >= max_used_data_block_count())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -552,6 +585,8 @@ done:
|
|||||||
{
|
{
|
||||||
ASSERT(this->mode().ifdir());
|
ASSERT(this->mode().ifdir());
|
||||||
|
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
if (!find_inode_impl(name).is_error())
|
if (!find_inode_impl(name).is_error())
|
||||||
return BAN::Error::from_errno(EEXIST);
|
return BAN::Error::from_errno(EEXIST);
|
||||||
|
|
||||||
@@ -586,6 +621,8 @@ done:
|
|||||||
ASSERT(this->mode().ifdir());
|
ASSERT(this->mode().ifdir());
|
||||||
ASSERT(Mode(mode).ifdir());
|
ASSERT(Mode(mode).ifdir());
|
||||||
|
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
if (!find_inode_impl(name).is_error())
|
if (!find_inode_impl(name).is_error())
|
||||||
return BAN::Error::from_errno(EEXIST);
|
return BAN::Error::from_errno(EEXIST);
|
||||||
|
|
||||||
@@ -619,6 +656,8 @@ done:
|
|||||||
ASSERT(!inode->mode().ifdir());
|
ASSERT(!inode->mode().ifdir());
|
||||||
ASSERT(&m_fs == inode->filesystem());
|
ASSERT(&m_fs == inode->filesystem());
|
||||||
|
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
if (!find_inode_impl(name).is_error())
|
if (!find_inode_impl(name).is_error())
|
||||||
return BAN::Error::from_errno(EEXIST);
|
return BAN::Error::from_errno(EEXIST);
|
||||||
|
|
||||||
@@ -636,16 +675,17 @@ done:
|
|||||||
|
|
||||||
auto* ext2_parent = static_cast<Ext2Inode*>(old_parent.ptr());
|
auto* ext2_parent = static_cast<Ext2Inode*>(old_parent.ptr());
|
||||||
|
|
||||||
// FIXME: possible deadlock :)
|
// FIXME: is this a possible deadlock?
|
||||||
LockGuard _(ext2_parent->m_mutex);
|
LockGuard _0(ext2_parent->m_lock);
|
||||||
|
LockGuard _1(m_lock);
|
||||||
|
|
||||||
auto old_inode = TRY(ext2_parent->find_inode_impl(old_name));
|
auto old_inode = TRY(ext2_parent->find_inode_impl(old_name));
|
||||||
auto* ext2_inode = static_cast<Ext2Inode*>(old_inode.ptr());
|
auto* ext2_inode = static_cast<Ext2Inode*>(old_inode.ptr());
|
||||||
|
|
||||||
if (auto replace_or_error = find_inode_impl(new_name); replace_or_error.is_error())
|
if (auto find_result = find_inode_impl(new_name); find_result.is_error())
|
||||||
{
|
{
|
||||||
if (replace_or_error.error().get_error_code() != ENOENT)
|
if (find_result.error().get_error_code() != ENOENT)
|
||||||
return replace_or_error.release_error();
|
return find_result.release_error();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -667,6 +707,8 @@ done:
|
|||||||
if (name.size() > 255)
|
if (name.size() > 255)
|
||||||
return BAN::Error::from_errno(ENAMETOOLONG);
|
return BAN::Error::from_errno(ENAMETOOLONG);
|
||||||
|
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
if (m_inode.flags & Ext2::Enum::INDEX_FL)
|
if (m_inode.flags & Ext2::Enum::INDEX_FL)
|
||||||
{
|
{
|
||||||
dwarnln("file creation to indexed directory not supported");
|
dwarnln("file creation to indexed directory not supported");
|
||||||
@@ -770,6 +812,8 @@ needs_new_block:
|
|||||||
|
|
||||||
auto block_buffer = TRY(m_fs.get_block_buffer());
|
auto block_buffer = TRY(m_fs.get_block_buffer());
|
||||||
|
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
// Confirm that this doesn't contain anything else than '.' or '..'
|
// Confirm that this doesn't contain anything else than '.' or '..'
|
||||||
for (uint32_t i = 0; i < max_used_data_block_count(); i++)
|
for (uint32_t i = 0; i < max_used_data_block_count(); i++)
|
||||||
{
|
{
|
||||||
@@ -800,14 +844,17 @@ needs_new_block:
|
|||||||
BAN::ErrorOr<void> Ext2Inode::cleanup_default_links()
|
BAN::ErrorOr<void> Ext2Inode::cleanup_default_links()
|
||||||
{
|
{
|
||||||
ASSERT(mode().ifdir());
|
ASSERT(mode().ifdir());
|
||||||
|
|
||||||
|
auto block_buffer = TRY(m_fs.get_block_buffer());
|
||||||
|
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
if (m_inode.flags & Ext2::Enum::INDEX_FL)
|
if (m_inode.flags & Ext2::Enum::INDEX_FL)
|
||||||
{
|
{
|
||||||
dwarnln("deletion of indexed directory is not supported");
|
dwarnln("deletion of indexed directory is not supported");
|
||||||
return BAN::Error::from_errno(ENOTSUP);
|
return BAN::Error::from_errno(ENOTSUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto block_buffer = TRY(m_fs.get_block_buffer());
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < max_used_data_block_count(); i++)
|
for (uint32_t i = 0; i < max_used_data_block_count(); i++)
|
||||||
{
|
{
|
||||||
const auto block_index = TRY(fs_block_of_data_block_index(i, false));
|
const auto block_index = TRY(fs_block_of_data_block_index(i, false));
|
||||||
@@ -857,14 +904,17 @@ needs_new_block:
|
|||||||
BAN::ErrorOr<void> Ext2Inode::remove_inode_from_directory(BAN::StringView name, bool cleanup_directory)
|
BAN::ErrorOr<void> Ext2Inode::remove_inode_from_directory(BAN::StringView name, bool cleanup_directory)
|
||||||
{
|
{
|
||||||
ASSERT(mode().ifdir());
|
ASSERT(mode().ifdir());
|
||||||
|
|
||||||
|
auto block_buffer = TRY(m_fs.get_block_buffer());
|
||||||
|
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
if (m_inode.flags & Ext2::Enum::INDEX_FL)
|
if (m_inode.flags & Ext2::Enum::INDEX_FL)
|
||||||
{
|
{
|
||||||
dwarnln("deletion from indexed directory is not supported");
|
dwarnln("deletion from indexed directory is not supported");
|
||||||
return BAN::Error::from_errno(ENOTSUP);
|
return BAN::Error::from_errno(ENOTSUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto block_buffer = TRY(m_fs.get_block_buffer());
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < max_used_data_block_count(); i++)
|
for (uint32_t i = 0; i < max_used_data_block_count(); i++)
|
||||||
{
|
{
|
||||||
const auto block_index = TRY(fs_block_of_data_block_index(i, false));
|
const auto block_index = TRY(fs_block_of_data_block_index(i, false));
|
||||||
@@ -925,6 +975,8 @@ needs_new_block:
|
|||||||
auto block_buffer = TRY(m_fs.get_block_buffer());
|
auto block_buffer = TRY(m_fs.get_block_buffer());
|
||||||
|
|
||||||
TRY(m_fs.read_block(inode_location.block, block_buffer));
|
TRY(m_fs.read_block(inode_location.block, block_buffer));
|
||||||
|
|
||||||
|
LockGuard _(m_lock);
|
||||||
if (memcmp(block_buffer.data() + inode_location.offset, &m_inode, sizeof(Ext2::Inode)))
|
if (memcmp(block_buffer.data() + inode_location.offset, &m_inode, sizeof(Ext2::Inode)))
|
||||||
{
|
{
|
||||||
memcpy(block_buffer.data() + inode_location.offset, &m_inode, sizeof(Ext2::Inode));
|
memcpy(block_buffer.data() + inode_location.offset, &m_inode, sizeof(Ext2::Inode));
|
||||||
@@ -940,6 +992,7 @@ needs_new_block:
|
|||||||
|
|
||||||
auto block_buffer = TRY(m_fs.get_block_buffer());
|
auto block_buffer = TRY(m_fs.get_block_buffer());
|
||||||
|
|
||||||
|
LockGuard _(m_lock);
|
||||||
for (uint32_t i = 0; i < max_used_data_block_count(); i++)
|
for (uint32_t i = 0; i < max_used_data_block_count(); i++)
|
||||||
{
|
{
|
||||||
const auto block_index = TRY(fs_block_of_data_block_index(i, false));
|
const auto block_index = TRY(fs_block_of_data_block_index(i, false));
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<BAN::RefPtr<Inode>> Inode::find_inode(BAN::StringView name)
|
BAN::ErrorOr<BAN::RefPtr<Inode>> Inode::find_inode(BAN::StringView name)
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
if (!mode().ifdir())
|
if (!mode().ifdir())
|
||||||
return BAN::Error::from_errno(ENOTDIR);
|
return BAN::Error::from_errno(ENOTDIR);
|
||||||
return find_inode_impl(name);
|
return find_inode_impl(name);
|
||||||
@@ -70,7 +69,6 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<size_t> Inode::list_next_inodes(off_t offset, struct dirent* list, size_t list_len)
|
BAN::ErrorOr<size_t> Inode::list_next_inodes(off_t offset, struct dirent* list, size_t list_len)
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
if (!mode().ifdir())
|
if (!mode().ifdir())
|
||||||
return BAN::Error::from_errno(ENOTDIR);
|
return BAN::Error::from_errno(ENOTDIR);
|
||||||
return list_next_inodes_impl(offset, list, list_len);
|
return list_next_inodes_impl(offset, list, list_len);
|
||||||
@@ -78,7 +76,6 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> Inode::create_file(BAN::StringView name, mode_t mode, uid_t uid, gid_t gid)
|
BAN::ErrorOr<void> Inode::create_file(BAN::StringView name, mode_t mode, uid_t uid, gid_t gid)
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
if (!this->mode().ifdir())
|
if (!this->mode().ifdir())
|
||||||
return BAN::Error::from_errno(ENOTDIR);
|
return BAN::Error::from_errno(ENOTDIR);
|
||||||
if (Mode(mode).ifdir())
|
if (Mode(mode).ifdir())
|
||||||
@@ -90,7 +87,6 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> Inode::create_directory(BAN::StringView name, mode_t mode, uid_t uid, gid_t gid)
|
BAN::ErrorOr<void> Inode::create_directory(BAN::StringView name, mode_t mode, uid_t uid, gid_t gid)
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
if (!this->mode().ifdir())
|
if (!this->mode().ifdir())
|
||||||
return BAN::Error::from_errno(ENOTDIR);
|
return BAN::Error::from_errno(ENOTDIR);
|
||||||
if (!Mode(mode).ifdir())
|
if (!Mode(mode).ifdir())
|
||||||
@@ -102,7 +98,6 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> Inode::link_inode(BAN::StringView name, BAN::RefPtr<Inode> inode)
|
BAN::ErrorOr<void> Inode::link_inode(BAN::StringView name, BAN::RefPtr<Inode> inode)
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
if (!this->mode().ifdir())
|
if (!this->mode().ifdir())
|
||||||
return BAN::Error::from_errno(ENOTDIR);
|
return BAN::Error::from_errno(ENOTDIR);
|
||||||
if (inode->mode().ifdir())
|
if (inode->mode().ifdir())
|
||||||
@@ -116,7 +111,6 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> Inode::rename_inode(BAN::RefPtr<Inode> old_parent, BAN::StringView old_name, BAN::StringView new_name)
|
BAN::ErrorOr<void> Inode::rename_inode(BAN::RefPtr<Inode> old_parent, BAN::StringView old_name, BAN::StringView new_name)
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
if (!this->mode().ifdir())
|
if (!this->mode().ifdir())
|
||||||
return BAN::Error::from_errno(ENOTDIR);
|
return BAN::Error::from_errno(ENOTDIR);
|
||||||
if (!old_parent->mode().ifdir())
|
if (!old_parent->mode().ifdir())
|
||||||
@@ -130,7 +124,6 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> Inode::unlink(BAN::StringView name)
|
BAN::ErrorOr<void> Inode::unlink(BAN::StringView name)
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
if (!mode().ifdir())
|
if (!mode().ifdir())
|
||||||
return BAN::Error::from_errno(ENOTDIR);
|
return BAN::Error::from_errno(ENOTDIR);
|
||||||
if (name == "."_sv || name == ".."_sv)
|
if (name == "."_sv || name == ".."_sv)
|
||||||
@@ -142,7 +135,6 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<BAN::String> Inode::link_target()
|
BAN::ErrorOr<BAN::String> Inode::link_target()
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
if (!mode().iflnk())
|
if (!mode().iflnk())
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
return link_target_impl();
|
return link_target_impl();
|
||||||
@@ -150,7 +142,6 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> Inode::set_link_target(BAN::StringView target)
|
BAN::ErrorOr<void> Inode::set_link_target(BAN::StringView target)
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
if (!mode().iflnk())
|
if (!mode().iflnk())
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
if (auto* fs = filesystem(); fs && (fs->flag() & ST_RDONLY))
|
if (auto* fs = filesystem(); fs && (fs->flag() & ST_RDONLY))
|
||||||
@@ -160,7 +151,6 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<long> Inode::accept(sockaddr* address, socklen_t* address_len, int flags)
|
BAN::ErrorOr<long> Inode::accept(sockaddr* address, socklen_t* address_len, int flags)
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
if (!mode().ifsock())
|
if (!mode().ifsock())
|
||||||
return BAN::Error::from_errno(ENOTSOCK);
|
return BAN::Error::from_errno(ENOTSOCK);
|
||||||
return accept_impl(address, address_len, flags);
|
return accept_impl(address, address_len, flags);
|
||||||
@@ -168,7 +158,6 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> Inode::bind(const sockaddr* address, socklen_t address_len)
|
BAN::ErrorOr<void> Inode::bind(const sockaddr* address, socklen_t address_len)
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
if (!mode().ifsock())
|
if (!mode().ifsock())
|
||||||
return BAN::Error::from_errno(ENOTSOCK);
|
return BAN::Error::from_errno(ENOTSOCK);
|
||||||
return bind_impl(address, address_len);
|
return bind_impl(address, address_len);
|
||||||
@@ -176,7 +165,6 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> Inode::connect(const sockaddr* address, socklen_t address_len)
|
BAN::ErrorOr<void> Inode::connect(const sockaddr* address, socklen_t address_len)
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
if (!mode().ifsock())
|
if (!mode().ifsock())
|
||||||
return BAN::Error::from_errno(ENOTSOCK);
|
return BAN::Error::from_errno(ENOTSOCK);
|
||||||
return connect_impl(address, address_len);
|
return connect_impl(address, address_len);
|
||||||
@@ -184,7 +172,6 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> Inode::listen(int backlog)
|
BAN::ErrorOr<void> Inode::listen(int backlog)
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
if (!mode().ifsock())
|
if (!mode().ifsock())
|
||||||
return BAN::Error::from_errno(ENOTSOCK);
|
return BAN::Error::from_errno(ENOTSOCK);
|
||||||
return listen_impl(backlog);
|
return listen_impl(backlog);
|
||||||
@@ -192,7 +179,6 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<size_t> Inode::recvmsg(msghdr& message, int flags)
|
BAN::ErrorOr<size_t> Inode::recvmsg(msghdr& message, int flags)
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
if (!mode().ifsock())
|
if (!mode().ifsock())
|
||||||
return BAN::Error::from_errno(ENOTSOCK);
|
return BAN::Error::from_errno(ENOTSOCK);
|
||||||
return recvmsg_impl(message, flags);
|
return recvmsg_impl(message, flags);
|
||||||
@@ -200,7 +186,6 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<size_t> Inode::sendmsg(const msghdr& message, int flags)
|
BAN::ErrorOr<size_t> Inode::sendmsg(const msghdr& message, int flags)
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
if (!mode().ifsock())
|
if (!mode().ifsock())
|
||||||
return BAN::Error::from_errno(ENOTSOCK);
|
return BAN::Error::from_errno(ENOTSOCK);
|
||||||
return sendmsg_impl(message, flags);
|
return sendmsg_impl(message, flags);
|
||||||
@@ -208,7 +193,6 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> Inode::getsockname(sockaddr* address, socklen_t* address_len)
|
BAN::ErrorOr<void> Inode::getsockname(sockaddr* address, socklen_t* address_len)
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
if (!mode().ifsock())
|
if (!mode().ifsock())
|
||||||
return BAN::Error::from_errno(ENOTSOCK);
|
return BAN::Error::from_errno(ENOTSOCK);
|
||||||
return getsockname_impl(address, address_len);
|
return getsockname_impl(address, address_len);
|
||||||
@@ -216,7 +200,6 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> Inode::getpeername(sockaddr* address, socklen_t* address_len)
|
BAN::ErrorOr<void> Inode::getpeername(sockaddr* address, socklen_t* address_len)
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
if (!mode().ifsock())
|
if (!mode().ifsock())
|
||||||
return BAN::Error::from_errno(ENOTSOCK);
|
return BAN::Error::from_errno(ENOTSOCK);
|
||||||
return getpeername_impl(address, address_len);
|
return getpeername_impl(address, address_len);
|
||||||
@@ -224,7 +207,6 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> Inode::getsockopt(int level, int option, void* value, socklen_t* value_len)
|
BAN::ErrorOr<void> Inode::getsockopt(int level, int option, void* value, socklen_t* value_len)
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
if (!mode().ifsock())
|
if (!mode().ifsock())
|
||||||
return BAN::Error::from_errno(ENOTSOCK);
|
return BAN::Error::from_errno(ENOTSOCK);
|
||||||
return getsockopt_impl(level, option, value, value_len);
|
return getsockopt_impl(level, option, value, value_len);
|
||||||
@@ -232,7 +214,6 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> Inode::setsockopt(int level, int option, const void* value, socklen_t value_len)
|
BAN::ErrorOr<void> Inode::setsockopt(int level, int option, const void* value, socklen_t value_len)
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
if (!mode().ifsock())
|
if (!mode().ifsock())
|
||||||
return BAN::Error::from_errno(ENOTSOCK);
|
return BAN::Error::from_errno(ENOTSOCK);
|
||||||
return setsockopt_impl(level, option, value, value_len);
|
return setsockopt_impl(level, option, value, value_len);
|
||||||
@@ -240,7 +221,6 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<size_t> Inode::read(off_t offset, BAN::ByteSpan buffer)
|
BAN::ErrorOr<size_t> Inode::read(off_t offset, BAN::ByteSpan buffer)
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
if (mode().ifdir())
|
if (mode().ifdir())
|
||||||
return BAN::Error::from_errno(EISDIR);
|
return BAN::Error::from_errno(EISDIR);
|
||||||
return read_impl(offset, buffer);
|
return read_impl(offset, buffer);
|
||||||
@@ -248,7 +228,6 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<size_t> Inode::write(off_t offset, BAN::ConstByteSpan buffer)
|
BAN::ErrorOr<size_t> Inode::write(off_t offset, BAN::ConstByteSpan buffer)
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
if (mode().ifdir())
|
if (mode().ifdir())
|
||||||
return BAN::Error::from_errno(EISDIR);
|
return BAN::Error::from_errno(EISDIR);
|
||||||
if (auto* fs = filesystem(); fs && (fs->flag() & ST_RDONLY))
|
if (auto* fs = filesystem(); fs && (fs->flag() & ST_RDONLY))
|
||||||
@@ -258,7 +237,6 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> Inode::truncate(size_t size)
|
BAN::ErrorOr<void> Inode::truncate(size_t size)
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
if (mode().ifdir())
|
if (mode().ifdir())
|
||||||
return BAN::Error::from_errno(EISDIR);
|
return BAN::Error::from_errno(EISDIR);
|
||||||
if (auto* fs = filesystem(); fs && (fs->flag() & ST_RDONLY))
|
if (auto* fs = filesystem(); fs && (fs->flag() & ST_RDONLY))
|
||||||
@@ -269,7 +247,6 @@ namespace Kernel
|
|||||||
BAN::ErrorOr<void> Inode::chmod(mode_t mode)
|
BAN::ErrorOr<void> Inode::chmod(mode_t mode)
|
||||||
{
|
{
|
||||||
ASSERT((mode & Inode::Mode::TYPE_MASK) == 0);
|
ASSERT((mode & Inode::Mode::TYPE_MASK) == 0);
|
||||||
LockGuard _(m_mutex);
|
|
||||||
if (auto* fs = filesystem(); fs && (fs->flag() & ST_RDONLY))
|
if (auto* fs = filesystem(); fs && (fs->flag() & ST_RDONLY))
|
||||||
return BAN::Error::from_errno(EROFS);
|
return BAN::Error::from_errno(EROFS);
|
||||||
return chmod_impl(mode);
|
return chmod_impl(mode);
|
||||||
@@ -277,7 +254,6 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> Inode::chown(uid_t uid, gid_t gid)
|
BAN::ErrorOr<void> Inode::chown(uid_t uid, gid_t gid)
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
if (auto* fs = filesystem(); fs && (fs->flag() & ST_RDONLY))
|
if (auto* fs = filesystem(); fs && (fs->flag() & ST_RDONLY))
|
||||||
return BAN::Error::from_errno(EROFS);
|
return BAN::Error::from_errno(EROFS);
|
||||||
return chown_impl(uid, gid);
|
return chown_impl(uid, gid);
|
||||||
@@ -285,7 +261,6 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> Inode::utimens(const timespec times[2])
|
BAN::ErrorOr<void> Inode::utimens(const timespec times[2])
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
if (auto* fs = filesystem(); fs && (fs->flag() & ST_RDONLY))
|
if (auto* fs = filesystem(); fs && (fs->flag() & ST_RDONLY))
|
||||||
return BAN::Error::from_errno(EROFS);
|
return BAN::Error::from_errno(EROFS);
|
||||||
return utimens_impl(times);
|
return utimens_impl(times);
|
||||||
@@ -293,40 +268,32 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> Inode::fsync()
|
BAN::ErrorOr<void> Inode::fsync()
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
// TODO: should we sync shared data?
|
||||||
if (auto shared = m_shared_region.lock())
|
|
||||||
for (size_t i = 0; i < shared->pages.size(); i++)
|
|
||||||
shared->sync(i);
|
|
||||||
return fsync_impl();
|
return fsync_impl();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Inode::can_read() const
|
bool Inode::can_read() const
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
return can_read_impl();
|
return can_read_impl();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Inode::can_write() const
|
bool Inode::can_write() const
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
return can_write_impl();
|
return can_write_impl();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Inode::has_error() const
|
bool Inode::has_error() const
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
return has_error_impl();
|
return has_error_impl();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Inode::has_hungup() const
|
bool Inode::has_hungup() const
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
return has_hungup_impl();
|
return has_hungup_impl();
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Inode::ioctl(int request, void* arg)
|
BAN::ErrorOr<long> Inode::ioctl(int request, void* arg)
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
return ioctl_impl(request, arg);
|
return ioctl_impl(request, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -73,6 +73,8 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<size_t> Pipe::read_impl(off_t, BAN::ByteSpan buffer)
|
BAN::ErrorOr<size_t> Pipe::read_impl(off_t, BAN::ByteSpan buffer)
|
||||||
{
|
{
|
||||||
|
LockGuard _(m_mutex);
|
||||||
|
|
||||||
while (m_buffer->empty())
|
while (m_buffer->empty())
|
||||||
{
|
{
|
||||||
if (m_writing_count == 0)
|
if (m_writing_count == 0)
|
||||||
@@ -95,6 +97,8 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<size_t> Pipe::write_impl(off_t, BAN::ConstByteSpan buffer)
|
BAN::ErrorOr<size_t> Pipe::write_impl(off_t, BAN::ConstByteSpan buffer)
|
||||||
{
|
{
|
||||||
|
LockGuard _(m_mutex);
|
||||||
|
|
||||||
while (m_buffer->full())
|
while (m_buffer->full())
|
||||||
{
|
{
|
||||||
if (m_reading_count == 0)
|
if (m_reading_count == 0)
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> TmpInode::chmod_impl(mode_t new_mode)
|
BAN::ErrorOr<void> TmpInode::chmod_impl(mode_t new_mode)
|
||||||
{
|
{
|
||||||
|
// FIXME: make this atomic
|
||||||
ASSERT(!(new_mode & Inode::Mode::TYPE_MASK));
|
ASSERT(!(new_mode & Inode::Mode::TYPE_MASK));
|
||||||
m_inode_info.mode &= Inode::Mode::TYPE_MASK;
|
m_inode_info.mode &= Inode::Mode::TYPE_MASK;
|
||||||
m_inode_info.mode |= new_mode;
|
m_inode_info.mode |= new_mode;
|
||||||
@@ -102,6 +103,7 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> TmpInode::chown_impl(uid_t new_uid, gid_t new_gid)
|
BAN::ErrorOr<void> TmpInode::chown_impl(uid_t new_uid, gid_t new_gid)
|
||||||
{
|
{
|
||||||
|
// FIXME: make this atomic
|
||||||
m_inode_info.uid = new_uid;
|
m_inode_info.uid = new_uid;
|
||||||
m_inode_info.gid = new_gid;
|
m_inode_info.gid = new_gid;
|
||||||
return {};
|
return {};
|
||||||
@@ -109,6 +111,7 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> TmpInode::utimens_impl(const timespec times[2])
|
BAN::ErrorOr<void> TmpInode::utimens_impl(const timespec times[2])
|
||||||
{
|
{
|
||||||
|
// FIXME: make this atomic
|
||||||
if (times[0].tv_nsec != UTIME_OMIT)
|
if (times[0].tv_nsec != UTIME_OMIT)
|
||||||
m_inode_info.atime = times[0];
|
m_inode_info.atime = times[0];
|
||||||
if (times[1].tv_nsec != UTIME_OMIT)
|
if (times[1].tv_nsec != UTIME_OMIT)
|
||||||
@@ -123,23 +126,24 @@ namespace Kernel
|
|||||||
|
|
||||||
void TmpInode::free_all_blocks()
|
void TmpInode::free_all_blocks()
|
||||||
{
|
{
|
||||||
|
LockGuard _(m_lock);
|
||||||
if (mode().iflnk() && m_inode_info.size <= sizeof(TmpInodeInfo::block))
|
if (mode().iflnk() && m_inode_info.size <= sizeof(TmpInodeInfo::block))
|
||||||
goto free_all_blocks_done;
|
goto free_all_blocks_done;
|
||||||
for (size_t i = 0; i < TmpInodeInfo::direct_block_count; i++)
|
for (size_t i = 0; i < TmpInodeInfo::direct_block_count; i++)
|
||||||
if (m_inode_info.block[i])
|
if (m_inode_info.block[i])
|
||||||
m_fs.free_block(m_inode_info.block[i]);
|
m_fs.free_block(m_inode_info.block[i]);
|
||||||
if (size_t block = m_inode_info.block[TmpInodeInfo::direct_block_count + 0])
|
if (size_t block = m_inode_info.block[TmpInodeInfo::direct_block_count + 0])
|
||||||
free_indirect_blocks(block, 1);
|
free_indirect_blocks_no_lock(block, 1);
|
||||||
if (size_t block = m_inode_info.block[TmpInodeInfo::direct_block_count + 1])
|
if (size_t block = m_inode_info.block[TmpInodeInfo::direct_block_count + 1])
|
||||||
free_indirect_blocks(block, 2);
|
free_indirect_blocks_no_lock(block, 2);
|
||||||
if (size_t block = m_inode_info.block[TmpInodeInfo::direct_block_count + 2])
|
if (size_t block = m_inode_info.block[TmpInodeInfo::direct_block_count + 2])
|
||||||
free_indirect_blocks(block, 3);
|
free_indirect_blocks_no_lock(block, 3);
|
||||||
free_all_blocks_done:
|
free_all_blocks_done:
|
||||||
for (auto& block : m_inode_info.block)
|
for (auto& block : m_inode_info.block)
|
||||||
block = 0;
|
block = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TmpInode::free_indirect_blocks(size_t block, uint32_t depth)
|
void TmpInode::free_indirect_blocks_no_lock(size_t block, uint32_t depth)
|
||||||
{
|
{
|
||||||
ASSERT(block != 0);
|
ASSERT(block != 0);
|
||||||
|
|
||||||
@@ -160,7 +164,7 @@ namespace Kernel
|
|||||||
if (next_block == 0)
|
if (next_block == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
free_indirect_blocks(next_block, depth - 1);
|
free_indirect_blocks_no_lock(next_block, depth - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_fs.free_block(block);
|
m_fs.free_block(block);
|
||||||
@@ -168,6 +172,8 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::Optional<size_t> TmpInode::block_index(size_t data_block_index)
|
BAN::Optional<size_t> TmpInode::block_index(size_t data_block_index)
|
||||||
{
|
{
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
if (data_block_index < TmpInodeInfo::direct_block_count)
|
if (data_block_index < TmpInodeInfo::direct_block_count)
|
||||||
{
|
{
|
||||||
if (m_inode_info.block[data_block_index] == 0)
|
if (m_inode_info.block[data_block_index] == 0)
|
||||||
@@ -179,20 +185,20 @@ namespace Kernel
|
|||||||
const size_t indices_per_block = blksize() / sizeof(size_t);
|
const size_t indices_per_block = blksize() / sizeof(size_t);
|
||||||
|
|
||||||
if (data_block_index < indices_per_block)
|
if (data_block_index < indices_per_block)
|
||||||
return block_index_from_indirect(m_inode_info.block[TmpInodeInfo::direct_block_count + 0], data_block_index, 1);
|
return block_index_from_indirect_no_lock(m_inode_info.block[TmpInodeInfo::direct_block_count + 0], data_block_index, 1);
|
||||||
data_block_index -= indices_per_block;
|
data_block_index -= indices_per_block;
|
||||||
|
|
||||||
if (data_block_index < indices_per_block * indices_per_block)
|
if (data_block_index < indices_per_block * indices_per_block)
|
||||||
return block_index_from_indirect(m_inode_info.block[TmpInodeInfo::direct_block_count + 1], data_block_index, 2);
|
return block_index_from_indirect_no_lock(m_inode_info.block[TmpInodeInfo::direct_block_count + 1], data_block_index, 2);
|
||||||
data_block_index -= indices_per_block * indices_per_block;
|
data_block_index -= indices_per_block * indices_per_block;
|
||||||
|
|
||||||
if (data_block_index < indices_per_block * indices_per_block * indices_per_block)
|
if (data_block_index < indices_per_block * indices_per_block * indices_per_block)
|
||||||
return block_index_from_indirect(m_inode_info.block[TmpInodeInfo::direct_block_count + 2], data_block_index, 3);
|
return block_index_from_indirect_no_lock(m_inode_info.block[TmpInodeInfo::direct_block_count + 2], data_block_index, 3);
|
||||||
|
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::Optional<size_t> TmpInode::block_index_from_indirect(size_t block, size_t index, uint32_t depth)
|
BAN::Optional<size_t> TmpInode::block_index_from_indirect_no_lock(size_t block, size_t index, uint32_t depth)
|
||||||
{
|
{
|
||||||
if (block == 0)
|
if (block == 0)
|
||||||
return {};
|
return {};
|
||||||
@@ -215,11 +221,13 @@ namespace Kernel
|
|||||||
if (depth == 1)
|
if (depth == 1)
|
||||||
return next_block;
|
return next_block;
|
||||||
|
|
||||||
return block_index_from_indirect(next_block, index, depth - 1);
|
return block_index_from_indirect_no_lock(next_block, index, depth - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<size_t> TmpInode::block_index_with_allocation(size_t data_block_index)
|
BAN::ErrorOr<size_t> TmpInode::block_index_with_allocation(size_t data_block_index)
|
||||||
{
|
{
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
if (data_block_index < TmpInodeInfo::direct_block_count)
|
if (data_block_index < TmpInodeInfo::direct_block_count)
|
||||||
{
|
{
|
||||||
if (m_inode_info.block[data_block_index] == 0)
|
if (m_inode_info.block[data_block_index] == 0)
|
||||||
@@ -234,20 +242,20 @@ namespace Kernel
|
|||||||
const size_t indices_per_block = blksize() / sizeof(size_t);
|
const size_t indices_per_block = blksize() / sizeof(size_t);
|
||||||
|
|
||||||
if (data_block_index < indices_per_block)
|
if (data_block_index < indices_per_block)
|
||||||
return block_index_from_indirect_with_allocation(m_inode_info.block[TmpInodeInfo::direct_block_count + 0], data_block_index, 1);
|
return block_index_from_indirect_with_allocation_no_lock(m_inode_info.block[TmpInodeInfo::direct_block_count + 0], data_block_index, 1);
|
||||||
data_block_index -= indices_per_block;
|
data_block_index -= indices_per_block;
|
||||||
|
|
||||||
if (data_block_index < indices_per_block * indices_per_block)
|
if (data_block_index < indices_per_block * indices_per_block)
|
||||||
return block_index_from_indirect_with_allocation(m_inode_info.block[TmpInodeInfo::direct_block_count + 1], data_block_index, 2);
|
return block_index_from_indirect_with_allocation_no_lock(m_inode_info.block[TmpInodeInfo::direct_block_count + 1], data_block_index, 2);
|
||||||
data_block_index -= indices_per_block * indices_per_block;
|
data_block_index -= indices_per_block * indices_per_block;
|
||||||
|
|
||||||
if (data_block_index < indices_per_block * indices_per_block * indices_per_block)
|
if (data_block_index < indices_per_block * indices_per_block * indices_per_block)
|
||||||
return block_index_from_indirect_with_allocation(m_inode_info.block[TmpInodeInfo::direct_block_count + 2], data_block_index, 3);
|
return block_index_from_indirect_with_allocation_no_lock(m_inode_info.block[TmpInodeInfo::direct_block_count + 2], data_block_index, 3);
|
||||||
|
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<size_t> TmpInode::block_index_from_indirect_with_allocation(size_t& block, size_t index, uint32_t depth)
|
BAN::ErrorOr<size_t> TmpInode::block_index_from_indirect_with_allocation_no_lock(size_t& block, size_t index, uint32_t depth)
|
||||||
{
|
{
|
||||||
if (block == 0)
|
if (block == 0)
|
||||||
{
|
{
|
||||||
@@ -280,7 +288,7 @@ namespace Kernel
|
|||||||
if (depth == 1)
|
if (depth == 1)
|
||||||
return next_block;
|
return next_block;
|
||||||
|
|
||||||
return block_index_from_indirect_with_allocation(next_block, index, depth - 1);
|
return block_index_from_indirect_with_allocation_no_lock(next_block, index, depth - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FILE INODE */
|
/* FILE INODE */
|
||||||
@@ -309,6 +317,8 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<size_t> TmpFileInode::read_impl(off_t offset, BAN::ByteSpan out_buffer)
|
BAN::ErrorOr<size_t> TmpFileInode::read_impl(off_t offset, BAN::ByteSpan out_buffer)
|
||||||
{
|
{
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
if (offset >= size() || out_buffer.size() == 0)
|
if (offset >= size() || out_buffer.size() == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -339,7 +349,12 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<size_t> TmpFileInode::write_impl(off_t offset, BAN::ConstByteSpan in_buffer)
|
BAN::ErrorOr<size_t> TmpFileInode::write_impl(off_t offset, BAN::ConstByteSpan in_buffer)
|
||||||
{
|
{
|
||||||
// FIXME: handle overflow
|
if (offset < 0)
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
if (BAN::Math::will_addition_overflow<size_t>(offset, in_buffer.size()))
|
||||||
|
return BAN::Error::from_errno(EOVERFLOW);
|
||||||
|
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
if (offset + in_buffer.size() > (size_t)size())
|
if (offset + in_buffer.size() > (size_t)size())
|
||||||
TRY(truncate_impl(offset + in_buffer.size()));
|
TRY(truncate_impl(offset + in_buffer.size()));
|
||||||
@@ -370,6 +385,7 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
// FIXME: if size is decreased, we should probably free
|
// FIXME: if size is decreased, we should probably free
|
||||||
// unused blocks
|
// unused blocks
|
||||||
|
// FIXME: make this atomic
|
||||||
|
|
||||||
m_inode_info.size = new_size;
|
m_inode_info.size = new_size;
|
||||||
return {};
|
return {};
|
||||||
@@ -427,6 +443,8 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> TmpSymlinkInode::set_link_target_impl(BAN::StringView new_target)
|
BAN::ErrorOr<void> TmpSymlinkInode::set_link_target_impl(BAN::StringView new_target)
|
||||||
{
|
{
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
free_all_blocks();
|
free_all_blocks();
|
||||||
m_inode_info.size = 0;
|
m_inode_info.size = 0;
|
||||||
|
|
||||||
@@ -455,6 +473,8 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<BAN::String> TmpSymlinkInode::link_target_impl()
|
BAN::ErrorOr<BAN::String> TmpSymlinkInode::link_target_impl()
|
||||||
{
|
{
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
BAN::String result;
|
BAN::String result;
|
||||||
TRY(result.resize(size()));
|
TRY(result.resize(size()));
|
||||||
|
|
||||||
@@ -522,7 +542,7 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> TmpDirectoryInode::prepare_unlink()
|
BAN::ErrorOr<void> TmpDirectoryInode::prepare_unlink_no_lock()
|
||||||
{
|
{
|
||||||
ino_t dot_ino = 0;
|
ino_t dot_ino = 0;
|
||||||
ino_t dotdot_ino = 0;
|
ino_t dotdot_ino = 0;
|
||||||
@@ -564,15 +584,15 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<BAN::RefPtr<Inode>> TmpDirectoryInode::find_inode_impl(BAN::StringView name)
|
BAN::ErrorOr<BAN::RefPtr<Inode>> TmpDirectoryInode::find_inode_impl(BAN::StringView name)
|
||||||
{
|
{
|
||||||
ino_t result = 0;
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
|
ino_t result = 0;
|
||||||
for_each_valid_entry([&](TmpDirectoryEntry& entry) {
|
for_each_valid_entry([&](TmpDirectoryEntry& entry) {
|
||||||
if (entry.name_sv() != name)
|
if (entry.name_sv() != name)
|
||||||
return BAN::Iteration::Continue;
|
return BAN::Iteration::Continue;
|
||||||
result = entry.ino;
|
result = entry.ino;
|
||||||
return BAN::Iteration::Break;
|
return BAN::Iteration::Break;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
return BAN::Error::from_errno(ENOENT);
|
return BAN::Error::from_errno(ENOENT);
|
||||||
|
|
||||||
@@ -588,6 +608,8 @@ namespace Kernel
|
|||||||
return BAN::Error::from_errno(ENOBUFS);
|
return BAN::Error::from_errno(ENOBUFS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
auto block_index = this->block_index(data_block_index);
|
auto block_index = this->block_index(data_block_index);
|
||||||
|
|
||||||
// if we reach a non-allocated block, it marks the end
|
// if we reach a non-allocated block, it marks the end
|
||||||
@@ -664,6 +686,8 @@ namespace Kernel
|
|||||||
ASSERT(!inode->mode().ifdir());
|
ASSERT(!inode->mode().ifdir());
|
||||||
ASSERT(&m_fs == inode->filesystem());
|
ASSERT(&m_fs == inode->filesystem());
|
||||||
|
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
if (!find_inode_impl(name).is_error())
|
if (!find_inode_impl(name).is_error())
|
||||||
return BAN::Error::from_errno(EEXIST);
|
return BAN::Error::from_errno(EEXIST);
|
||||||
|
|
||||||
@@ -680,16 +704,17 @@ namespace Kernel
|
|||||||
|
|
||||||
auto* tmp_parent = static_cast<TmpDirectoryInode*>(old_parent.ptr());
|
auto* tmp_parent = static_cast<TmpDirectoryInode*>(old_parent.ptr());
|
||||||
|
|
||||||
// FIXME: possible deadlock :)
|
// FIXME: is this a possible deadlock?
|
||||||
LockGuard _(tmp_parent->m_mutex);
|
LockGuard _0(tmp_parent->m_lock);
|
||||||
|
LockGuard _1(m_lock);
|
||||||
|
|
||||||
auto old_inode = TRY(tmp_parent->find_inode_impl(old_name));
|
auto old_inode = TRY(tmp_parent->find_inode_impl(old_name));
|
||||||
auto* tmp_inode = static_cast<TmpInode*>(old_inode.ptr());
|
auto* tmp_inode = static_cast<TmpInode*>(old_inode.ptr());
|
||||||
|
|
||||||
if (auto replace_or_error = find_inode_impl(new_name); replace_or_error.is_error())
|
if (auto find_result = find_inode_impl(new_name); find_result.is_error())
|
||||||
{
|
{
|
||||||
if (replace_or_error.error().get_error_code() != ENOENT)
|
if (find_result.error().get_error_code() != ENOENT)
|
||||||
return replace_or_error.release_error();
|
return find_result.release_error();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -711,15 +736,15 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> TmpDirectoryInode::unlink_inode(BAN::StringView name, bool cleanup)
|
BAN::ErrorOr<void> TmpDirectoryInode::unlink_inode(BAN::StringView name, bool cleanup)
|
||||||
{
|
{
|
||||||
ino_t entry_ino = 0;
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
|
ino_t entry_ino = 0;
|
||||||
for_each_valid_entry([&](TmpDirectoryEntry& entry) {
|
for_each_valid_entry([&](TmpDirectoryEntry& entry) {
|
||||||
if (entry.name_sv() != name)
|
if (entry.name_sv() != name)
|
||||||
return BAN::Iteration::Continue;
|
return BAN::Iteration::Continue;
|
||||||
entry_ino = entry.ino;
|
entry_ino = entry.ino;
|
||||||
return BAN::Iteration::Break;
|
return BAN::Iteration::Break;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (entry_ino == 0)
|
if (entry_ino == 0)
|
||||||
return BAN::Error::from_errno(ENOENT);
|
return BAN::Error::from_errno(ENOENT);
|
||||||
|
|
||||||
@@ -728,7 +753,7 @@ namespace Kernel
|
|||||||
ASSERT(inode->nlink() > 0);
|
ASSERT(inode->nlink() > 0);
|
||||||
|
|
||||||
if (cleanup)
|
if (cleanup)
|
||||||
TRY(inode->prepare_unlink());
|
TRY(inode->prepare_unlink_no_lock());
|
||||||
inode->m_inode_info.nlink--;
|
inode->m_inode_info.nlink--;
|
||||||
|
|
||||||
if (inode->nlink() == 0)
|
if (inode->nlink() == 0)
|
||||||
@@ -749,6 +774,8 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
static constexpr size_t directory_entry_alignment = sizeof(TmpDirectoryEntry);
|
static constexpr size_t directory_entry_alignment = sizeof(TmpDirectoryEntry);
|
||||||
|
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
auto find_result = find_inode_impl(name);
|
auto find_result = find_inode_impl(name);
|
||||||
if (!find_result.is_error())
|
if (!find_result.is_error())
|
||||||
return BAN::Error::from_errno(EEXIST);
|
return BAN::Error::from_errno(EEXIST);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include <BAN/ScopeGuard.h>
|
#include <BAN/ScopeGuard.h>
|
||||||
#include <kernel/FS/USTARModule.h>
|
#include <kernel/FS/USTARModule.h>
|
||||||
|
#include <kernel/Memory/PageTable.h>
|
||||||
#include <kernel/Timer/Timer.h>
|
#include <kernel/Timer/Timer.h>
|
||||||
#include <LibDEFLATE/Decompressor.h>
|
#include <LibDEFLATE/Decompressor.h>
|
||||||
|
|
||||||
|
|||||||
@@ -13,12 +13,15 @@
|
|||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
|
static SpinLock s_keyboard_lock;
|
||||||
static BAN::Vector<BAN::WeakPtr<InputDevice>> s_keyboards;
|
static BAN::Vector<BAN::WeakPtr<InputDevice>> s_keyboards;
|
||||||
static BAN::RefPtr<KeyboardDevice> s_keyboard_device;
|
static BAN::RefPtr<KeyboardDevice> s_keyboard_device;
|
||||||
|
|
||||||
|
static SpinLock s_mouse_lock;
|
||||||
static BAN::Vector<BAN::WeakPtr<InputDevice>> s_mice;
|
static BAN::Vector<BAN::WeakPtr<InputDevice>> s_mice;
|
||||||
static BAN::RefPtr<MouseDevice> s_mouse_device;
|
static BAN::RefPtr<MouseDevice> s_mouse_device;
|
||||||
|
|
||||||
|
static SpinLock s_joystick_lock;
|
||||||
static BAN::Vector<BAN::WeakPtr<InputDevice>> s_joysticks;
|
static BAN::Vector<BAN::WeakPtr<InputDevice>> s_joysticks;
|
||||||
|
|
||||||
static const char* get_name_format(InputDevice::Type type)
|
static const char* get_name_format(InputDevice::Type type)
|
||||||
@@ -40,20 +43,29 @@ namespace Kernel
|
|||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case InputDevice::Type::Keyboard:
|
case InputDevice::Type::Keyboard:
|
||||||
|
{
|
||||||
|
SpinLockGuard _(s_keyboard_lock);
|
||||||
for (size_t i = 0; i < s_keyboards.size(); i++)
|
for (size_t i = 0; i < s_keyboards.size(); i++)
|
||||||
if (!s_keyboards[i].valid())
|
if (!s_keyboards[i].valid())
|
||||||
return makedev(DeviceNumber::Keyboard, i + 1);
|
return makedev(DeviceNumber::Keyboard, i + 1);
|
||||||
return makedev(DeviceNumber::Keyboard, s_keyboards.size() + 1);
|
return makedev(DeviceNumber::Keyboard, s_keyboards.size() + 1);
|
||||||
|
}
|
||||||
case InputDevice::Type::Mouse:
|
case InputDevice::Type::Mouse:
|
||||||
|
{
|
||||||
|
SpinLockGuard _(s_mouse_lock);
|
||||||
for (size_t i = 0; i < s_mice.size(); i++)
|
for (size_t i = 0; i < s_mice.size(); i++)
|
||||||
if (!s_mice[i].valid())
|
if (!s_mice[i].valid())
|
||||||
return makedev(DeviceNumber::Mouse, i + 1);
|
return makedev(DeviceNumber::Mouse, i + 1);
|
||||||
return makedev(DeviceNumber::Mouse, s_mice.size() + 1);
|
return makedev(DeviceNumber::Mouse, s_mice.size() + 1);
|
||||||
|
}
|
||||||
case InputDevice::Type::Joystick:
|
case InputDevice::Type::Joystick:
|
||||||
|
{
|
||||||
|
SpinLockGuard _(s_joystick_lock);
|
||||||
for (size_t i = 0; i < s_joysticks.size(); i++)
|
for (size_t i = 0; i < s_joysticks.size(); i++)
|
||||||
if (!s_joysticks[i].valid())
|
if (!s_joysticks[i].valid())
|
||||||
return makedev(DeviceNumber::Joystick, i + 1);
|
return makedev(DeviceNumber::Joystick, i + 1);
|
||||||
return makedev(DeviceNumber::Joystick, s_joysticks.size() + 1);
|
return makedev(DeviceNumber::Joystick, s_joysticks.size() + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
@@ -84,20 +96,29 @@ namespace Kernel
|
|||||||
switch (m_type)
|
switch (m_type)
|
||||||
{
|
{
|
||||||
case Type::Keyboard:
|
case Type::Keyboard:
|
||||||
|
{
|
||||||
|
SpinLockGuard _(s_keyboard_lock);
|
||||||
if (s_keyboards.size() < minor(m_rdev))
|
if (s_keyboards.size() < minor(m_rdev))
|
||||||
MUST(s_keyboards.resize(minor(m_rdev)));
|
MUST(s_keyboards.resize(minor(m_rdev)));
|
||||||
s_keyboards[minor(m_rdev) - 1] = MUST(get_weak_ptr());
|
s_keyboards[minor(m_rdev) - 1] = MUST(get_weak_ptr());
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case Type::Mouse:
|
case Type::Mouse:
|
||||||
|
{
|
||||||
|
SpinLockGuard _(s_mouse_lock);
|
||||||
if (s_mice.size() < minor(m_rdev))
|
if (s_mice.size() < minor(m_rdev))
|
||||||
MUST(s_mice.resize(minor(m_rdev)));
|
MUST(s_mice.resize(minor(m_rdev)));
|
||||||
s_mice[minor(m_rdev) - 1] = MUST(get_weak_ptr());
|
s_mice[minor(m_rdev) - 1] = MUST(get_weak_ptr());
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case Type::Joystick:
|
case Type::Joystick:
|
||||||
|
{
|
||||||
|
SpinLockGuard _(s_joystick_lock);
|
||||||
if (s_joysticks.size() < minor(m_rdev))
|
if (s_joysticks.size() < minor(m_rdev))
|
||||||
MUST(s_joysticks.resize(minor(m_rdev)));
|
MUST(s_joysticks.resize(minor(m_rdev)));
|
||||||
s_joysticks[minor(m_rdev) - 1] = MUST(get_weak_ptr());
|
s_joysticks[minor(m_rdev) - 1] = MUST(get_weak_ptr());
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,6 +277,8 @@ namespace Kernel
|
|||||||
void KeyboardDevice::notify()
|
void KeyboardDevice::notify()
|
||||||
{
|
{
|
||||||
epoll_notify(EPOLLIN);
|
epoll_notify(EPOLLIN);
|
||||||
|
|
||||||
|
SpinLockGuard _(s_keyboard_lock);
|
||||||
m_thread_blocker.unblock();
|
m_thread_blocker.unblock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,6 +287,7 @@ namespace Kernel
|
|||||||
if (buffer.size() < sizeof(LibInput::RawKeyEvent))
|
if (buffer.size() < sizeof(LibInput::RawKeyEvent))
|
||||||
return BAN::Error::from_errno(ENOBUFS);
|
return BAN::Error::from_errno(ENOBUFS);
|
||||||
|
|
||||||
|
SpinLockGuard keyboard_guard(s_keyboard_lock);
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
for (auto& weak_keyboard : s_keyboards)
|
for (auto& weak_keyboard : s_keyboards)
|
||||||
@@ -277,13 +301,14 @@ namespace Kernel
|
|||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: race condition as notify doesn't lock mutex
|
SpinLockGuardAsMutex smutex(keyboard_guard);
|
||||||
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex));
|
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &smutex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KeyboardDevice::can_read_impl() const
|
bool KeyboardDevice::can_read_impl() const
|
||||||
{
|
{
|
||||||
|
SpinLockGuard _(s_keyboard_lock);
|
||||||
for (auto& weak_keyboard : s_keyboards)
|
for (auto& weak_keyboard : s_keyboards)
|
||||||
if (auto keyboard = weak_keyboard.lock())
|
if (auto keyboard = weak_keyboard.lock())
|
||||||
if (keyboard->can_read())
|
if (keyboard->can_read())
|
||||||
@@ -308,6 +333,8 @@ namespace Kernel
|
|||||||
void MouseDevice::notify()
|
void MouseDevice::notify()
|
||||||
{
|
{
|
||||||
epoll_notify(EPOLLIN);
|
epoll_notify(EPOLLIN);
|
||||||
|
|
||||||
|
SpinLockGuard _(s_mouse_lock);
|
||||||
m_thread_blocker.unblock();
|
m_thread_blocker.unblock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,6 +343,7 @@ namespace Kernel
|
|||||||
if (buffer.size() < sizeof(LibInput::MouseEvent))
|
if (buffer.size() < sizeof(LibInput::MouseEvent))
|
||||||
return BAN::Error::from_errno(ENOBUFS);
|
return BAN::Error::from_errno(ENOBUFS);
|
||||||
|
|
||||||
|
SpinLockGuard mouse_guard(s_mouse_lock);
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
for (auto& weak_mouse : s_mice)
|
for (auto& weak_mouse : s_mice)
|
||||||
@@ -329,13 +357,14 @@ namespace Kernel
|
|||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: race condition as notify doesn't lock mutex
|
SpinLockGuardAsMutex smutex(mouse_guard);
|
||||||
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex));
|
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &smutex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MouseDevice::can_read_impl() const
|
bool MouseDevice::can_read_impl() const
|
||||||
{
|
{
|
||||||
|
SpinLockGuard _(s_mouse_lock);
|
||||||
for (auto& weak_mouse : s_mice)
|
for (auto& weak_mouse : s_mice)
|
||||||
if (auto mouse = weak_mouse.lock())
|
if (auto mouse = weak_mouse.lock())
|
||||||
if (mouse->can_read())
|
if (mouse->can_read())
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ namespace Kernel
|
|||||||
if (type == Type::PRIVATE)
|
if (type == Type::PRIVATE)
|
||||||
TRY(region->m_dirty_pages.resize(BAN::Math::div_round_up<size_t>(size, PAGE_SIZE)));
|
TRY(region->m_dirty_pages.resize(BAN::Math::div_round_up<size_t>(size, PAGE_SIZE)));
|
||||||
|
|
||||||
LockGuard _(inode->m_mutex);
|
SpinLockGuard _(inode->m_shared_region_lock);
|
||||||
if (!(region->m_shared_data = inode->m_shared_region.lock()))
|
if (!(region->m_shared_data = inode->m_shared_region.lock()))
|
||||||
{
|
{
|
||||||
auto shared_data = TRY(BAN::RefPtr<SharedFileData>::create());
|
auto shared_data = TRY(BAN::RefPtr<SharedFileData>::create());
|
||||||
|
|||||||
@@ -66,6 +66,8 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<long> TCPSocket::accept_impl(sockaddr* address, socklen_t* address_len, int flags)
|
BAN::ErrorOr<long> TCPSocket::accept_impl(sockaddr* address, socklen_t* address_len, int flags)
|
||||||
{
|
{
|
||||||
|
LockGuard _(m_mutex);
|
||||||
|
|
||||||
if (m_state != State::Listen)
|
if (m_state != State::Listen)
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
@@ -171,6 +173,8 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> TCPSocket::listen_impl(int backlog)
|
BAN::ErrorOr<void> TCPSocket::listen_impl(int backlog)
|
||||||
{
|
{
|
||||||
|
LockGuard _(m_mutex);
|
||||||
|
|
||||||
if (!is_bound())
|
if (!is_bound())
|
||||||
return BAN::Error::from_errno(EDESTADDRREQ);
|
return BAN::Error::from_errno(EDESTADDRREQ);
|
||||||
if (m_connection_info.has_value())
|
if (m_connection_info.has_value())
|
||||||
@@ -185,6 +189,8 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> TCPSocket::bind_impl(const sockaddr* address, socklen_t address_len)
|
BAN::ErrorOr<void> TCPSocket::bind_impl(const sockaddr* address, socklen_t address_len)
|
||||||
{
|
{
|
||||||
|
LockGuard _(m_mutex);
|
||||||
|
|
||||||
if (is_bound())
|
if (is_bound())
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
return m_network_layer.bind_socket_to_address(this, address, address_len);
|
return m_network_layer.bind_socket_to_address(this, address, address_len);
|
||||||
@@ -204,6 +210,8 @@ namespace Kernel
|
|||||||
message.msg_controllen = 0;
|
message.msg_controllen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LockGuard _(m_mutex);
|
||||||
|
|
||||||
if (!m_has_connected)
|
if (!m_has_connected)
|
||||||
return BAN::Error::from_errno(ENOTCONN);
|
return BAN::Error::from_errno(ENOTCONN);
|
||||||
|
|
||||||
@@ -261,6 +269,8 @@ namespace Kernel
|
|||||||
if (CMSG_FIRSTHDR(&message))
|
if (CMSG_FIRSTHDR(&message))
|
||||||
dwarnln("ignoring sendmsg control message");
|
dwarnln("ignoring sendmsg control message");
|
||||||
|
|
||||||
|
LockGuard _(m_mutex);
|
||||||
|
|
||||||
if (!m_has_connected)
|
if (!m_has_connected)
|
||||||
return BAN::Error::from_errno(ENOTCONN);
|
return BAN::Error::from_errno(ENOTCONN);
|
||||||
|
|
||||||
@@ -291,6 +301,7 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> TCPSocket::getpeername_impl(sockaddr* address, socklen_t* address_len)
|
BAN::ErrorOr<void> TCPSocket::getpeername_impl(sockaddr* address, socklen_t* address_len)
|
||||||
{
|
{
|
||||||
|
LockGuard _(m_mutex);
|
||||||
if (!m_has_connected && m_state != State::Established)
|
if (!m_has_connected && m_state != State::Established)
|
||||||
return BAN::Error::from_errno(ENOTCONN);
|
return BAN::Error::from_errno(ENOTCONN);
|
||||||
ASSERT(m_connection_info.has_value());
|
ASSERT(m_connection_info.has_value());
|
||||||
@@ -302,6 +313,8 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> TCPSocket::getsockopt_impl(int level, int option, void* value, socklen_t* value_len)
|
BAN::ErrorOr<void> TCPSocket::getsockopt_impl(int level, int option, void* value, socklen_t* value_len)
|
||||||
{
|
{
|
||||||
|
LockGuard _(m_mutex);
|
||||||
|
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
switch (level)
|
switch (level)
|
||||||
@@ -351,6 +364,8 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> TCPSocket::setsockopt_impl(int level, int option, const void* value, socklen_t value_len)
|
BAN::ErrorOr<void> TCPSocket::setsockopt_impl(int level, int option, const void* value, socklen_t value_len)
|
||||||
{
|
{
|
||||||
|
LockGuard _(m_mutex);
|
||||||
|
|
||||||
switch (level)
|
switch (level)
|
||||||
{
|
{
|
||||||
case SOL_SOCKET:
|
case SOL_SOCKET:
|
||||||
@@ -401,6 +416,7 @@ namespace Kernel
|
|||||||
|
|
||||||
bool TCPSocket::can_read_impl() const
|
bool TCPSocket::can_read_impl() const
|
||||||
{
|
{
|
||||||
|
LockGuard _(m_mutex);
|
||||||
if (m_has_connected && !m_has_sent_zero && m_state != State::Established && m_state != State::Listen)
|
if (m_has_connected && !m_has_sent_zero && m_state != State::Established && m_state != State::Listen)
|
||||||
return true;
|
return true;
|
||||||
if (m_state == State::Listen)
|
if (m_state == State::Listen)
|
||||||
@@ -410,6 +426,7 @@ namespace Kernel
|
|||||||
|
|
||||||
bool TCPSocket::can_write_impl() const
|
bool TCPSocket::can_write_impl() const
|
||||||
{
|
{
|
||||||
|
LockGuard _(m_mutex);
|
||||||
if (m_state != State::Established)
|
if (m_state != State::Established)
|
||||||
return false;
|
return false;
|
||||||
return !m_send_window.buffer->full();
|
return !m_send_window.buffer->full();
|
||||||
@@ -417,6 +434,7 @@ namespace Kernel
|
|||||||
|
|
||||||
bool TCPSocket::has_hungup_impl() const
|
bool TCPSocket::has_hungup_impl() const
|
||||||
{
|
{
|
||||||
|
LockGuard _(m_mutex);
|
||||||
return m_has_connected && m_state != State::Established;
|
return m_has_connected && m_state != State::Established;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include <kernel/Lock/LockGuard.h>
|
||||||
#include <kernel/Lock/SpinLockAsMutex.h>
|
#include <kernel/Lock/SpinLockAsMutex.h>
|
||||||
#include <kernel/Memory/Heap.h>
|
#include <kernel/Memory/Heap.h>
|
||||||
#include <kernel/Networking/UDPSocket.h>
|
#include <kernel/Networking/UDPSocket.h>
|
||||||
@@ -58,9 +59,6 @@ namespace Kernel
|
|||||||
|
|
||||||
void UDPSocket::receive_packet(BAN::ConstByteSpan packet, const sockaddr* sender, socklen_t sender_len)
|
void UDPSocket::receive_packet(BAN::ConstByteSpan packet, const sockaddr* sender, socklen_t sender_len)
|
||||||
{
|
{
|
||||||
(void)sender_len;
|
|
||||||
|
|
||||||
//auto& header = packet.as<const UDPHeader>();
|
|
||||||
auto payload = packet.slice(sizeof(UDPHeader));
|
auto payload = packet.slice(sizeof(UDPHeader));
|
||||||
|
|
||||||
SpinLockGuard _(m_packet_lock);
|
SpinLockGuard _(m_packet_lock);
|
||||||
@@ -95,6 +93,8 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
if (address_len > static_cast<socklen_t>(sizeof(m_peer_address)))
|
if (address_len > static_cast<socklen_t>(sizeof(m_peer_address)))
|
||||||
address_len = sizeof(m_peer_address);
|
address_len = sizeof(m_peer_address);
|
||||||
|
|
||||||
|
SpinLockGuard _(m_peer_address_lock);
|
||||||
memcpy(&m_peer_address, address, address_len);
|
memcpy(&m_peer_address, address, address_len);
|
||||||
m_peer_address_len = address_len;
|
m_peer_address_len = address_len;
|
||||||
return {};
|
return {};
|
||||||
@@ -102,6 +102,7 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> UDPSocket::bind_impl(const sockaddr* address, socklen_t address_len)
|
BAN::ErrorOr<void> UDPSocket::bind_impl(const sockaddr* address, socklen_t address_len)
|
||||||
{
|
{
|
||||||
|
LockGuard _(m_bind_lock);
|
||||||
if (is_bound())
|
if (is_bound())
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
return m_network_layer.bind_socket_to_address(this, address, address_len);
|
return m_network_layer.bind_socket_to_address(this, address, address_len);
|
||||||
@@ -183,8 +184,11 @@ namespace Kernel
|
|||||||
if (CMSG_FIRSTHDR(&message))
|
if (CMSG_FIRSTHDR(&message))
|
||||||
dwarnln("ignoring sendmsg control message");
|
dwarnln("ignoring sendmsg control message");
|
||||||
|
|
||||||
if (!is_bound())
|
{
|
||||||
TRY(m_network_layer.bind_socket_with_target(this, static_cast<sockaddr*>(message.msg_name), message.msg_namelen));
|
LockGuard _(m_bind_lock);
|
||||||
|
if (!is_bound())
|
||||||
|
TRY(m_network_layer.bind_socket_with_target(this, static_cast<sockaddr*>(message.msg_name), message.msg_namelen));
|
||||||
|
}
|
||||||
|
|
||||||
const size_t total_send_size =
|
const size_t total_send_size =
|
||||||
[&message]() -> size_t {
|
[&message]() -> size_t {
|
||||||
@@ -208,6 +212,7 @@ namespace Kernel
|
|||||||
socklen_t address_len;
|
socklen_t address_len;
|
||||||
if (!message.msg_name || message.msg_namelen == 0)
|
if (!message.msg_name || message.msg_namelen == 0)
|
||||||
{
|
{
|
||||||
|
SpinLockGuard _(m_peer_address_lock);
|
||||||
if (m_peer_address_len == 0)
|
if (m_peer_address_len == 0)
|
||||||
return BAN::Error::from_errno(EDESTADDRREQ);
|
return BAN::Error::from_errno(EDESTADDRREQ);
|
||||||
address = reinterpret_cast<sockaddr*>(&m_peer_address);
|
address = reinterpret_cast<sockaddr*>(&m_peer_address);
|
||||||
|
|||||||
@@ -88,6 +88,26 @@ namespace Kernel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool UnixDomainSocket::is_bound() const
|
||||||
|
{
|
||||||
|
LockGuard _(m_bind_mutex);
|
||||||
|
return !m_bound_file.canonical_path.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UnixDomainSocket::is_bound_to_unused() const
|
||||||
|
{
|
||||||
|
LockGuard _(m_bind_mutex);
|
||||||
|
return !m_bound_file.inode;
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> UnixDomainSocket::bind_to_unused_if_not_bound()
|
||||||
|
{
|
||||||
|
LockGuard _(m_bind_mutex);
|
||||||
|
if (!is_bound())
|
||||||
|
TRY(m_bound_file.canonical_path.push_back('X'));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> UnixDomainSocket::make_socket_pair(UnixDomainSocket& other)
|
BAN::ErrorOr<void> UnixDomainSocket::make_socket_pair(UnixDomainSocket& other)
|
||||||
{
|
{
|
||||||
if (!m_info.has<ConnectionInfo>() || !other.m_info.has<ConnectionInfo>())
|
if (!m_info.has<ConnectionInfo>() || !other.m_info.has<ConnectionInfo>())
|
||||||
@@ -106,15 +126,15 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
if (!m_info.has<ConnectionInfo>())
|
if (!m_info.has<ConnectionInfo>())
|
||||||
return BAN::Error::from_errno(EOPNOTSUPP);
|
return BAN::Error::from_errno(EOPNOTSUPP);
|
||||||
auto& connection_info = m_info.get<ConnectionInfo>();
|
|
||||||
if (!connection_info.listening)
|
|
||||||
return BAN::Error::from_errno(EINVAL);
|
|
||||||
|
|
||||||
|
|
||||||
BAN::RefPtr<UnixDomainSocket> pending;
|
BAN::RefPtr<UnixDomainSocket> pending;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
auto& connection_info = m_info.get<ConnectionInfo>();
|
||||||
|
|
||||||
LockGuard _(connection_info.pending_lock);
|
LockGuard _(connection_info.pending_lock);
|
||||||
|
if (!connection_info.listening)
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
while (connection_info.pending_connections.empty())
|
while (connection_info.pending_connections.empty())
|
||||||
TRY(Thread::current().block_or_eintr_indefinite(connection_info.pending_thread_blocker, &connection_info.pending_lock));
|
TRY(Thread::current().block_or_eintr_indefinite(connection_info.pending_thread_blocker, &connection_info.pending_lock));
|
||||||
|
|
||||||
@@ -154,8 +174,6 @@ namespace Kernel
|
|||||||
BAN::ErrorOr<void> UnixDomainSocket::connect_impl(const sockaddr* address, socklen_t address_len)
|
BAN::ErrorOr<void> UnixDomainSocket::connect_impl(const sockaddr* address, socklen_t address_len)
|
||||||
{
|
{
|
||||||
const auto sun_path = TRY(validate_sockaddr_un(address, address_len));
|
const auto sun_path = TRY(validate_sockaddr_un(address, address_len));
|
||||||
if (!is_bound())
|
|
||||||
TRY(m_bound_file.canonical_path.push_back('X'));
|
|
||||||
|
|
||||||
auto absolute_path = TRY(Process::current().absolute_path_of(sun_path));
|
auto absolute_path = TRY(Process::current().absolute_path_of(sun_path));
|
||||||
auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(
|
auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(
|
||||||
@@ -180,9 +198,12 @@ namespace Kernel
|
|||||||
if (m_socket_type != target->m_socket_type)
|
if (m_socket_type != target->m_socket_type)
|
||||||
return BAN::Error::from_errno(EPROTOTYPE);
|
return BAN::Error::from_errno(EPROTOTYPE);
|
||||||
|
|
||||||
|
TRY(bind_to_unused_if_not_bound());
|
||||||
|
|
||||||
if (m_info.has<ConnectionlessInfo>())
|
if (m_info.has<ConnectionlessInfo>())
|
||||||
{
|
{
|
||||||
auto& connectionless_info = m_info.get<ConnectionlessInfo>();
|
auto& connectionless_info = m_info.get<ConnectionlessInfo>();
|
||||||
|
SpinLockGuard _(connectionless_info.lock);
|
||||||
connectionless_info.peer_address = BAN::move(file.canonical_path);
|
connectionless_info.peer_address = BAN::move(file.canonical_path);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -192,7 +213,6 @@ namespace Kernel
|
|||||||
return BAN::Error::from_errno(ECONNREFUSED);
|
return BAN::Error::from_errno(ECONNREFUSED);
|
||||||
if (connection_info.listening)
|
if (connection_info.listening)
|
||||||
return BAN::Error::from_errno(EOPNOTSUPP);
|
return BAN::Error::from_errno(EOPNOTSUPP);
|
||||||
|
|
||||||
connection_info.connection_done = false;
|
connection_info.connection_done = false;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
@@ -222,23 +242,25 @@ namespace Kernel
|
|||||||
BAN::ErrorOr<void> UnixDomainSocket::listen_impl(int backlog)
|
BAN::ErrorOr<void> UnixDomainSocket::listen_impl(int backlog)
|
||||||
{
|
{
|
||||||
backlog = BAN::Math::clamp(backlog, 1, SOMAXCONN);
|
backlog = BAN::Math::clamp(backlog, 1, SOMAXCONN);
|
||||||
|
|
||||||
if (!is_bound())
|
if (!is_bound())
|
||||||
return BAN::Error::from_errno(EDESTADDRREQ);
|
return BAN::Error::from_errno(EDESTADDRREQ);
|
||||||
if (!m_info.has<ConnectionInfo>())
|
if (!m_info.has<ConnectionInfo>())
|
||||||
return BAN::Error::from_errno(EOPNOTSUPP);
|
return BAN::Error::from_errno(EOPNOTSUPP);
|
||||||
|
|
||||||
auto& connection_info = m_info.get<ConnectionInfo>();
|
auto& connection_info = m_info.get<ConnectionInfo>();
|
||||||
|
|
||||||
|
LockGuard _(connection_info.pending_lock);
|
||||||
if (connection_info.connection)
|
if (connection_info.connection)
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
TRY(connection_info.pending_connections.reserve(backlog));
|
TRY(connection_info.pending_connections.reserve(backlog));
|
||||||
connection_info.listening = true;
|
connection_info.listening = true;
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> UnixDomainSocket::bind_impl(const sockaddr* address, socklen_t address_len)
|
BAN::ErrorOr<void> UnixDomainSocket::bind_impl(const sockaddr* address, socklen_t address_len)
|
||||||
{
|
{
|
||||||
if (is_bound())
|
|
||||||
return BAN::Error::from_errno(EINVAL);
|
|
||||||
|
|
||||||
const auto sun_path = TRY(validate_sockaddr_un(address, address_len));
|
const auto sun_path = TRY(validate_sockaddr_un(address, address_len));
|
||||||
if (sun_path.empty())
|
if (sun_path.empty())
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
@@ -261,10 +283,15 @@ namespace Kernel
|
|||||||
O_RDWR
|
O_RDWR
|
||||||
));
|
));
|
||||||
|
|
||||||
LockGuard _(s_bound_socket_lock);
|
LockGuard _0(m_bind_mutex);
|
||||||
|
if (is_bound())
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
|
LockGuard _1(s_bound_socket_lock);
|
||||||
if (s_bound_sockets.contains(file.inode))
|
if (s_bound_sockets.contains(file.inode))
|
||||||
return BAN::Error::from_errno(EADDRINUSE);
|
return BAN::Error::from_errno(EADDRINUSE);
|
||||||
TRY(s_bound_sockets.emplace(file.inode, TRY(get_weak_ptr())));
|
TRY(s_bound_sockets.emplace(file.inode, TRY(get_weak_ptr())));
|
||||||
|
|
||||||
m_bound_file = BAN::move(file);
|
m_bound_file = BAN::move(file);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
@@ -679,6 +706,7 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
if (!m_info.has<ConnectionInfo>())
|
if (!m_info.has<ConnectionInfo>())
|
||||||
return BAN::Error::from_errno(ENOTCONN);
|
return BAN::Error::from_errno(ENOTCONN);
|
||||||
|
|
||||||
auto connection = m_info.get<ConnectionInfo>().connection.lock();
|
auto connection = m_info.get<ConnectionInfo>().connection.lock();
|
||||||
if (!connection)
|
if (!connection)
|
||||||
return BAN::Error::from_errno(ENOTCONN);
|
return BAN::Error::from_errno(ENOTCONN);
|
||||||
@@ -687,7 +715,11 @@ namespace Kernel
|
|||||||
.sun_family = AF_UNIX,
|
.sun_family = AF_UNIX,
|
||||||
.sun_path = {},
|
.sun_path = {},
|
||||||
};
|
};
|
||||||
strcpy(sa_un.sun_path, connection->m_bound_file.canonical_path.data());
|
|
||||||
|
{
|
||||||
|
LockGuard _(m_bind_mutex);
|
||||||
|
strcpy(sa_un.sun_path, connection->m_bound_file.canonical_path.data());
|
||||||
|
}
|
||||||
|
|
||||||
const size_t to_copy = BAN::Math::min<socklen_t>(sizeof(sockaddr_un), *address_len);
|
const size_t to_copy = BAN::Math::min<socklen_t>(sizeof(sockaddr_un), *address_len);
|
||||||
memcpy(address, &sa_un, to_copy);
|
memcpy(address, &sa_un, to_copy);
|
||||||
|
|||||||
@@ -699,9 +699,9 @@ namespace Kernel
|
|||||||
|
|
||||||
size_t nread;
|
size_t nread;
|
||||||
{
|
{
|
||||||
LockGuard _(inode->m_mutex);
|
|
||||||
if (!inode->can_read() && inode->has_hungup())
|
if (!inode->can_read() && inode->has_hungup())
|
||||||
return 0;
|
return 0;
|
||||||
|
// FIXME: race condition, pass flags to read
|
||||||
if (is_nonblock && !inode->can_read())
|
if (is_nonblock && !inode->can_read())
|
||||||
return BAN::Error::from_errno(EAGAIN);
|
return BAN::Error::from_errno(EAGAIN);
|
||||||
nread = TRY(inode->read(offset, buffer));
|
nread = TRY(inode->read(offset, buffer));
|
||||||
@@ -753,7 +753,6 @@ namespace Kernel
|
|||||||
|
|
||||||
size_t nwrite;
|
size_t nwrite;
|
||||||
{
|
{
|
||||||
LockGuard _(inode->m_mutex);
|
|
||||||
if (inode->has_error())
|
if (inode->has_error())
|
||||||
{
|
{
|
||||||
Thread::current().add_signal(SIGPIPE, {});
|
Thread::current().add_signal(SIGPIPE, {});
|
||||||
@@ -761,6 +760,7 @@ namespace Kernel
|
|||||||
}
|
}
|
||||||
if (is_nonblock && !inode->can_write())
|
if (is_nonblock && !inode->can_write())
|
||||||
return BAN::Error::from_errno(EAGAIN);
|
return BAN::Error::from_errno(EAGAIN);
|
||||||
|
// FIXME: race condition, pass flags to write
|
||||||
nwrite = TRY(inode->write(offset, buffer));
|
nwrite = TRY(inode->write(offset, buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -818,7 +818,6 @@ namespace Kernel
|
|||||||
is_nonblock = !!(open_file->status_flags & O_NONBLOCK);
|
is_nonblock = !!(open_file->status_flags & O_NONBLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
LockGuard _(inode->m_mutex);
|
|
||||||
if (is_nonblock && !inode->can_read())
|
if (is_nonblock && !inode->can_read())
|
||||||
return BAN::Error::from_errno(EAGAIN);
|
return BAN::Error::from_errno(EAGAIN);
|
||||||
return inode->recvmsg(message, flags);
|
return inode->recvmsg(message, flags);
|
||||||
@@ -839,7 +838,6 @@ namespace Kernel
|
|||||||
is_nonblock = !!(open_file->status_flags & O_NONBLOCK);
|
is_nonblock = !!(open_file->status_flags & O_NONBLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
LockGuard _(inode->m_mutex);
|
|
||||||
if (inode->has_hungup())
|
if (inode->has_hungup())
|
||||||
{
|
{
|
||||||
if (!(flags & MSG_NOSIGNAL))
|
if (!(flags & MSG_NOSIGNAL))
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include <kernel/CPUID.h>
|
#include <kernel/CPUID.h>
|
||||||
#include <kernel/Debug.h>
|
#include <kernel/Debug.h>
|
||||||
|
#include <kernel/Lock/SpinLock.h>
|
||||||
#include <kernel/Random.h>
|
#include <kernel/Random.h>
|
||||||
#include <kernel/Timer/Timer.h>
|
#include <kernel/Timer/Timer.h>
|
||||||
|
|
||||||
@@ -9,6 +10,7 @@ namespace Kernel
|
|||||||
|
|
||||||
// Constants and algorithm from https://en.wikipedia.org/wiki/Permuted_congruential_generator
|
// Constants and algorithm from https://en.wikipedia.org/wiki/Permuted_congruential_generator
|
||||||
|
|
||||||
|
static SpinLock s_rand_lock;
|
||||||
static uint64_t s_rand_seed = 0x4d595df4d0f33173;
|
static uint64_t s_rand_seed = 0x4d595df4d0f33173;
|
||||||
static constexpr uint64_t s_rand_multiplier = 6364136223846793005;
|
static constexpr uint64_t s_rand_multiplier = 6364136223846793005;
|
||||||
static constexpr uint64_t s_rand_increment = 1442695040888963407;
|
static constexpr uint64_t s_rand_increment = 1442695040888963407;
|
||||||
@@ -46,7 +48,9 @@ namespace Kernel
|
|||||||
|
|
||||||
uint32_t Random::get_u32()
|
uint32_t Random::get_u32()
|
||||||
{
|
{
|
||||||
auto rotr32 = [](uint32_t x, unsigned r) { return x >> r | x << (-r & 31); };
|
constexpr auto rotr32 = [](uint32_t x, unsigned r) { return x >> r | x << (-r & 31); };
|
||||||
|
|
||||||
|
SpinLockGuard _(s_rand_lock);
|
||||||
|
|
||||||
uint64_t x = s_rand_seed;
|
uint64_t x = s_rand_seed;
|
||||||
unsigned count = (unsigned)(x >> 59);
|
unsigned count = (unsigned)(x >> 59);
|
||||||
|
|||||||
@@ -144,6 +144,7 @@ namespace Kernel
|
|||||||
auto slave = m_slave.lock();
|
auto slave = m_slave.lock();
|
||||||
if (!slave)
|
if (!slave)
|
||||||
return BAN::Error::from_errno(EIO);
|
return BAN::Error::from_errno(EIO);
|
||||||
|
LockGuard _(slave->m_mutex);
|
||||||
for (size_t i = 0; i < buffer.size(); i++)
|
for (size_t i = 0; i < buffer.size(); i++)
|
||||||
slave->handle_input_byte(buffer[i]);
|
slave->handle_input_byte(buffer[i]);
|
||||||
return buffer.size();
|
return buffer.size();
|
||||||
@@ -160,8 +161,11 @@ namespace Kernel
|
|||||||
switch (request)
|
switch (request)
|
||||||
{
|
{
|
||||||
case FIONREAD:
|
case FIONREAD:
|
||||||
|
{
|
||||||
|
SpinLockGuard _(m_buffer_lock);
|
||||||
*static_cast<int*>(argument) = m_buffer_size;
|
*static_cast<int*>(argument) = m_buffer_size;
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
case TIOCGWINSZ:
|
case TIOCGWINSZ:
|
||||||
case TIOCSWINSZ:
|
case TIOCSWINSZ:
|
||||||
if (auto slave = m_slave.lock())
|
if (auto slave = m_slave.lock())
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <kernel/FS/DevFS/FileSystem.h>
|
#include <kernel/FS/DevFS/FileSystem.h>
|
||||||
#include <kernel/FS/VirtualFileSystem.h>
|
#include <kernel/FS/VirtualFileSystem.h>
|
||||||
#include <kernel/Lock/LockGuard.h>
|
#include <kernel/Lock/LockGuard.h>
|
||||||
|
#include <kernel/Lock/SpinLockAsMutex.h>
|
||||||
#include <kernel/Process.h>
|
#include <kernel/Process.h>
|
||||||
#include <kernel/Terminal/TTY.h>
|
#include <kernel/Terminal/TTY.h>
|
||||||
#include <kernel/Timer/Timer.h>
|
#include <kernel/Timer/Timer.h>
|
||||||
@@ -71,8 +72,8 @@ namespace Kernel
|
|||||||
|
|
||||||
TTY::TTY(termios termios, mode_t mode, uid_t uid, gid_t gid)
|
TTY::TTY(termios termios, mode_t mode, uid_t uid, gid_t gid)
|
||||||
: CharacterDevice(mode, uid, gid)
|
: CharacterDevice(mode, uid, gid)
|
||||||
, m_termios(termios)
|
|
||||||
, m_rdev(next_tty_rdev())
|
, m_rdev(next_tty_rdev())
|
||||||
|
, m_termios(termios)
|
||||||
{
|
{
|
||||||
m_output.buffer = MUST(ByteRingBuffer::create(PAGE_SIZE));
|
m_output.buffer = MUST(ByteRingBuffer::create(PAGE_SIZE));
|
||||||
}
|
}
|
||||||
@@ -94,21 +95,16 @@ namespace Kernel
|
|||||||
if (flags & ~(TTY_FLAG_ENABLE_INPUT | TTY_FLAG_ENABLE_OUTPUT))
|
if (flags & ~(TTY_FLAG_ENABLE_INPUT | TTY_FLAG_ENABLE_OUTPUT))
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
LockGuard _(m_mutex);
|
|
||||||
|
|
||||||
switch (command)
|
switch (command)
|
||||||
{
|
{
|
||||||
case TTY_CMD_SET:
|
case TTY_CMD_SET:
|
||||||
if ((flags & TTY_FLAG_ENABLE_INPUT) && !m_tty_ctrl.receive_input)
|
if (flags & TTY_FLAG_ENABLE_INPUT)
|
||||||
{
|
|
||||||
m_tty_ctrl.receive_input = true;
|
m_tty_ctrl.receive_input = true;
|
||||||
m_tty_ctrl.thread_blocker.unblock();
|
|
||||||
}
|
|
||||||
if (flags & TTY_FLAG_ENABLE_OUTPUT)
|
if (flags & TTY_FLAG_ENABLE_OUTPUT)
|
||||||
m_tty_ctrl.draw_graphics = true;
|
m_tty_ctrl.draw_graphics = true;
|
||||||
break;
|
break;
|
||||||
case TTY_CMD_UNSET:
|
case TTY_CMD_UNSET:
|
||||||
if ((flags & TTY_FLAG_ENABLE_INPUT) && m_tty_ctrl.receive_input)
|
if (flags & TTY_FLAG_ENABLE_INPUT)
|
||||||
m_tty_ctrl.receive_input = false;
|
m_tty_ctrl.receive_input = false;
|
||||||
if (flags & TTY_FLAG_ENABLE_OUTPUT)
|
if (flags & TTY_FLAG_ENABLE_OUTPUT)
|
||||||
m_tty_ctrl.draw_graphics = false;
|
m_tty_ctrl.draw_graphics = false;
|
||||||
@@ -133,16 +129,8 @@ namespace Kernel
|
|||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
{
|
|
||||||
LockGuard _(TTY::current()->m_mutex);
|
|
||||||
while (!TTY::current()->m_tty_ctrl.receive_input)
|
|
||||||
TTY::current()->m_tty_ctrl.thread_blocker.block_indefinite(&TTY::current()->m_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (TTY::current()->m_tty_ctrl.receive_input)
|
while (TTY::current()->m_tty_ctrl.receive_input)
|
||||||
{
|
{
|
||||||
LockGuard _(keyboard_inode->m_mutex);
|
|
||||||
|
|
||||||
if (!keyboard_inode->can_read())
|
if (!keyboard_inode->can_read())
|
||||||
{
|
{
|
||||||
SystemTimer::get().sleep_ms(1);
|
SystemTimer::get().sleep_ms(1);
|
||||||
@@ -160,19 +148,15 @@ namespace Kernel
|
|||||||
|
|
||||||
void TTY::initialize_devices()
|
void TTY::initialize_devices()
|
||||||
{
|
{
|
||||||
static bool initialized = false;
|
|
||||||
ASSERT(!initialized);
|
|
||||||
|
|
||||||
auto* thread = MUST(Thread::create_kernel(&TTY::keyboard_task, nullptr));
|
auto* thread = MUST(Thread::create_kernel(&TTY::keyboard_task, nullptr));
|
||||||
MUST(Processor::scheduler().add_thread(thread));
|
MUST(Processor::scheduler().add_thread(thread));
|
||||||
|
|
||||||
DevFileSystem::get().add_inode("tty", MUST(DevTTY::create(0666, 0, 0)));
|
DevFileSystem::get().add_inode("tty", MUST(DevTTY::create(0666, 0, 0)));
|
||||||
|
|
||||||
initialized = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> TTY::chmod_impl(mode_t mode)
|
BAN::ErrorOr<void> TTY::chmod_impl(mode_t mode)
|
||||||
{
|
{
|
||||||
|
// FIXME: make this atomic
|
||||||
ASSERT((mode & Inode::Mode::TYPE_MASK) == 0);
|
ASSERT((mode & Inode::Mode::TYPE_MASK) == 0);
|
||||||
m_inode_info.mode &= Inode::Mode::TYPE_MASK;
|
m_inode_info.mode &= Inode::Mode::TYPE_MASK;
|
||||||
m_inode_info.mode |= mode;
|
m_inode_info.mode |= mode;
|
||||||
@@ -181,6 +165,7 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<void> TTY::chown_impl(uid_t uid, gid_t gid)
|
BAN::ErrorOr<void> TTY::chown_impl(uid_t uid, gid_t gid)
|
||||||
{
|
{
|
||||||
|
// FIXME: make this atomic
|
||||||
m_inode_info.uid = uid;
|
m_inode_info.uid = uid;
|
||||||
m_inode_info.gid = gid;
|
m_inode_info.gid = gid;
|
||||||
return {};
|
return {};
|
||||||
@@ -188,6 +173,7 @@ namespace Kernel
|
|||||||
|
|
||||||
void TTY::update_winsize(unsigned short cols, unsigned short rows)
|
void TTY::update_winsize(unsigned short cols, unsigned short rows)
|
||||||
{
|
{
|
||||||
|
// FIXME: make this atomic
|
||||||
m_winsize.ws_col = cols;
|
m_winsize.ws_col = cols;
|
||||||
m_winsize.ws_row = rows;
|
m_winsize.ws_row = rows;
|
||||||
(void)Process::kill(-m_foreground_pgrp, SIGWINCH);
|
(void)Process::kill(-m_foreground_pgrp, SIGWINCH);
|
||||||
@@ -211,12 +197,14 @@ namespace Kernel
|
|||||||
}
|
}
|
||||||
case TIOCGWINSZ:
|
case TIOCGWINSZ:
|
||||||
{
|
{
|
||||||
|
// FIXME: make this atomic
|
||||||
auto* winsize = static_cast<struct winsize*>(argument);
|
auto* winsize = static_cast<struct winsize*>(argument);
|
||||||
*winsize = m_winsize;
|
*winsize = m_winsize;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case TIOCSWINSZ:
|
case TIOCSWINSZ:
|
||||||
{
|
{
|
||||||
|
// FIXME: make this atomic
|
||||||
const auto* winsize = static_cast<const struct winsize*>(argument);
|
const auto* winsize = static_cast<const struct winsize*>(argument);
|
||||||
m_winsize = *winsize;
|
m_winsize = *winsize;
|
||||||
(void)Process::kill(-m_foreground_pgrp, SIGWINCH);
|
(void)Process::kill(-m_foreground_pgrp, SIGWINCH);
|
||||||
@@ -226,10 +214,13 @@ namespace Kernel
|
|||||||
return BAN::Error::from_errno(ENOTSUP);
|
return BAN::Error::from_errno(ENOTSUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TTY::on_key_event(LibInput::RawKeyEvent event)
|
||||||
|
{
|
||||||
|
on_key_event(LibInput::KeyboardLayout::get().key_event_from_raw(event));
|
||||||
|
}
|
||||||
|
|
||||||
void TTY::on_key_event(LibInput::KeyEvent event)
|
void TTY::on_key_event(LibInput::KeyEvent event)
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
|
||||||
|
|
||||||
if (event.released())
|
if (event.released())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -237,35 +228,55 @@ namespace Kernel
|
|||||||
if (ansi_c_str == nullptr)
|
if (ansi_c_str == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
LockGuard _(m_mutex);
|
||||||
while (*ansi_c_str)
|
while (*ansi_c_str)
|
||||||
handle_input_byte(*ansi_c_str++);
|
handle_input_byte(*ansi_c_str++);
|
||||||
after_write();
|
after_write();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TTY::get_termios(termios* termios)
|
||||||
|
{
|
||||||
|
SpinLockGuard _(m_termios_lock);
|
||||||
|
*termios = m_termios;
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> TTY::set_termios(const termios* termios)
|
||||||
|
{
|
||||||
|
// FIXME: do some validation
|
||||||
|
|
||||||
|
SpinLockGuard _(m_termios_lock);
|
||||||
|
m_termios = *termios;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void TTY::handle_input_byte(uint8_t ch)
|
void TTY::handle_input_byte(uint8_t ch)
|
||||||
{
|
{
|
||||||
if (ch == _POSIX_VDISABLE)
|
if (ch == _POSIX_VDISABLE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LockGuard _(m_mutex);
|
LockGuard _0(m_mutex);
|
||||||
|
|
||||||
if ((m_termios.c_iflag & ISTRIP))
|
termios termios;
|
||||||
|
get_termios(&termios);
|
||||||
|
|
||||||
|
|
||||||
|
if ((termios.c_iflag & ISTRIP))
|
||||||
ch &= 0x7F;
|
ch &= 0x7F;
|
||||||
if ((m_termios.c_iflag & IGNCR) && ch == CR)
|
if ((termios.c_iflag & IGNCR) && ch == CR)
|
||||||
return;
|
return;
|
||||||
if ((m_termios.c_iflag & ICRNL) && ch == CR)
|
if ((termios.c_iflag & ICRNL) && ch == CR)
|
||||||
ch = NL;
|
ch = NL;
|
||||||
else if ((m_termios.c_iflag & INLCR) && ch == NL)
|
else if ((termios.c_iflag & INLCR) && ch == NL)
|
||||||
ch = CR;
|
ch = CR;
|
||||||
|
|
||||||
if (m_termios.c_lflag & ISIG)
|
if (termios.c_lflag & ISIG)
|
||||||
{
|
{
|
||||||
int sig = -1;
|
int sig = -1;
|
||||||
if (ch == m_termios.c_cc[VINTR])
|
if (ch == termios.c_cc[VINTR])
|
||||||
sig = SIGINT;
|
sig = SIGINT;
|
||||||
if (ch == m_termios.c_cc[VQUIT])
|
if (ch == termios.c_cc[VQUIT])
|
||||||
sig = SIGQUIT;
|
sig = SIGQUIT;
|
||||||
if (ch == m_termios.c_cc[VSUSP])
|
if (ch == termios.c_cc[VSUSP])
|
||||||
sig = SIGTSTP;
|
sig = SIGTSTP;
|
||||||
if (sig != -1)
|
if (sig != -1)
|
||||||
{
|
{
|
||||||
@@ -279,30 +290,30 @@ namespace Kernel
|
|||||||
bool should_flush = false;
|
bool should_flush = false;
|
||||||
bool force_echo = false;
|
bool force_echo = false;
|
||||||
|
|
||||||
if (!(m_termios.c_lflag & ICANON))
|
if (!(termios.c_lflag & ICANON))
|
||||||
should_flush = true;
|
should_flush = true;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (ch == m_termios.c_cc[VERASE] && (m_termios.c_lflag & ECHOE))
|
if (ch == termios.c_cc[VERASE] && (termios.c_lflag & ECHOE))
|
||||||
return do_backspace();
|
return do_backspace();
|
||||||
|
|
||||||
if (ch == m_termios.c_cc[VKILL] && (m_termios.c_lflag & ECHOK))
|
if (ch == termios.c_cc[VKILL] && (termios.c_lflag & ECHOK))
|
||||||
{
|
{
|
||||||
while (!m_output.buffer->empty() && m_output.buffer->back() != '\n')
|
while (!m_output.buffer->empty() && m_output.buffer->back() != '\n')
|
||||||
do_backspace();
|
do_backspace();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ch == m_termios.c_cc[VEOF])
|
if (ch == termios.c_cc[VEOF])
|
||||||
{
|
{
|
||||||
should_append = false;
|
should_append = false;
|
||||||
should_flush = true;
|
should_flush = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ch == NL || ch == CR || ch == m_termios.c_cc[VEOL])
|
if (ch == NL || ch == CR || ch == termios.c_cc[VEOL])
|
||||||
{
|
{
|
||||||
should_flush = true;
|
should_flush = true;
|
||||||
force_echo = !!(m_termios.c_lflag & ECHONL);
|
force_echo = !!(termios.c_lflag & ECHONL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,7 +322,7 @@ namespace Kernel
|
|||||||
if (should_append && !m_output.buffer->full())
|
if (should_append && !m_output.buffer->full())
|
||||||
m_output.buffer->push({ &ch, 1 });
|
m_output.buffer->push({ &ch, 1 });
|
||||||
|
|
||||||
if (should_append && (force_echo || (m_termios.c_lflag & ECHO)))
|
if (should_append && (force_echo || (termios.c_lflag & ECHO)))
|
||||||
{
|
{
|
||||||
if ((ch <= 31 || ch == 127) && ch != '\n')
|
if ((ch <= 31 || ch == 127) && ch != '\n')
|
||||||
{
|
{
|
||||||
@@ -380,14 +391,18 @@ namespace Kernel
|
|||||||
|
|
||||||
bool TTY::putchar(uint8_t ch)
|
bool TTY::putchar(uint8_t ch)
|
||||||
{
|
{
|
||||||
SpinLockGuard _(m_write_lock);
|
|
||||||
if (!m_tty_ctrl.draw_graphics)
|
if (!m_tty_ctrl.draw_graphics)
|
||||||
return true;
|
return true;
|
||||||
if (m_termios.c_oflag & OPOST)
|
|
||||||
|
termios termios;
|
||||||
|
get_termios(&termios);
|
||||||
|
|
||||||
|
SpinLockGuard _1(m_write_lock);
|
||||||
|
if (termios.c_oflag & OPOST)
|
||||||
{
|
{
|
||||||
if ((m_termios.c_oflag & ONLCR) && ch == NL)
|
if ((termios.c_oflag & ONLCR) && ch == NL)
|
||||||
return putchar_impl(CR) && putchar_impl(NL);
|
return putchar_impl(CR) && putchar_impl(NL);
|
||||||
if ((m_termios.c_oflag & OCRNL) && ch == CR)
|
if ((termios.c_oflag & OCRNL) && ch == CR)
|
||||||
return putchar_impl(NL);
|
return putchar_impl(NL);
|
||||||
}
|
}
|
||||||
return putchar_impl(ch);
|
return putchar_impl(ch);
|
||||||
@@ -395,6 +410,7 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<size_t> TTY::read_impl(off_t, BAN::ByteSpan buffer)
|
BAN::ErrorOr<size_t> TTY::read_impl(off_t, BAN::ByteSpan buffer)
|
||||||
{
|
{
|
||||||
|
LockGuard _(m_mutex);
|
||||||
while (!m_output.flush)
|
while (!m_output.flush)
|
||||||
TRY(Thread::current().block_or_eintr_indefinite(m_output.thread_blocker, &m_mutex));
|
TRY(Thread::current().block_or_eintr_indefinite(m_output.thread_blocker, &m_mutex));
|
||||||
|
|
||||||
@@ -428,24 +444,24 @@ namespace Kernel
|
|||||||
|
|
||||||
BAN::ErrorOr<size_t> TTY::write_impl(off_t, BAN::ConstByteSpan buffer)
|
BAN::ErrorOr<size_t> TTY::write_impl(off_t, BAN::ConstByteSpan buffer)
|
||||||
{
|
{
|
||||||
while (!can_write_impl())
|
SpinLockGuard write_guard(m_write_lock);
|
||||||
|
|
||||||
|
while (!can_write())
|
||||||
{
|
{
|
||||||
if (master_has_closed())
|
if (master_has_closed())
|
||||||
return BAN::Error::from_errno(EIO);
|
return BAN::Error::from_errno(EIO);
|
||||||
TRY(Thread::current().block_or_eintr_indefinite(m_write_blocker, &m_mutex));
|
|
||||||
|
SpinLockGuardAsMutex smutex(write_guard);
|
||||||
|
TRY(Thread::current().block_or_eintr_indefinite(m_write_blocker, &smutex));
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t written = 0;
|
size_t written = 0;
|
||||||
|
for (; written < buffer.size(); written++)
|
||||||
|
if (!putchar(buffer[written]))
|
||||||
|
break;
|
||||||
|
after_write();
|
||||||
|
|
||||||
{
|
if (can_write())
|
||||||
SpinLockGuard _(m_write_lock);
|
|
||||||
for (; written < buffer.size(); written++)
|
|
||||||
if (!putchar(buffer[written]))
|
|
||||||
break;
|
|
||||||
after_write();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (can_write_impl())
|
|
||||||
epoll_notify(EPOLLOUT);
|
epoll_notify(EPOLLOUT);
|
||||||
|
|
||||||
return written;
|
return written;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ namespace Kernel
|
|||||||
g_terminal_driver = TRY(TextModeTerminalDriver::create_from_boot_info());
|
g_terminal_driver = TRY(TextModeTerminalDriver::create_from_boot_info());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user