mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 12:28:12 +00:00
Kernel: Implement FIFOs/named pipes
This commit is contained in:
parent
76e34968fa
commit
d01eba6fa3
5 changed files with 69 additions and 0 deletions
|
@ -60,6 +60,35 @@ NonnullRefPtr<FileDescription> FIFO::open_direction(FIFO::Direction direction)
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NonnullRefPtr<FileDescription> FIFO::open_direction_blocking(FIFO::Direction direction)
|
||||||
|
{
|
||||||
|
Locker locker(m_open_lock);
|
||||||
|
|
||||||
|
auto description = open_direction(direction);
|
||||||
|
|
||||||
|
if (direction == Direction::Reader) {
|
||||||
|
m_read_open_queue.wake_all();
|
||||||
|
|
||||||
|
if (m_writers == 0) {
|
||||||
|
locker.unlock();
|
||||||
|
Thread::current()->wait_on(m_write_open_queue, "FIFO");
|
||||||
|
locker.lock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (direction == Direction::Writer) {
|
||||||
|
m_write_open_queue.wake_all();
|
||||||
|
|
||||||
|
if (m_readers == 0) {
|
||||||
|
locker.unlock();
|
||||||
|
Thread::current()->wait_on(m_read_open_queue, "FIFO");
|
||||||
|
locker.lock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
FIFO::FIFO(uid_t uid)
|
FIFO::FIFO(uid_t uid)
|
||||||
: m_uid(uid)
|
: m_uid(uid)
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,7 +28,9 @@
|
||||||
|
|
||||||
#include <Kernel/DoubleBuffer.h>
|
#include <Kernel/DoubleBuffer.h>
|
||||||
#include <Kernel/FileSystem/File.h>
|
#include <Kernel/FileSystem/File.h>
|
||||||
|
#include <Kernel/Lock.h>
|
||||||
#include <Kernel/UnixTypes.h>
|
#include <Kernel/UnixTypes.h>
|
||||||
|
#include <Kernel/WaitQueue.h>
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
|
@ -48,6 +50,7 @@ public:
|
||||||
uid_t uid() const { return m_uid; }
|
uid_t uid() const { return m_uid; }
|
||||||
|
|
||||||
NonnullRefPtr<FileDescription> open_direction(Direction);
|
NonnullRefPtr<FileDescription> open_direction(Direction);
|
||||||
|
NonnullRefPtr<FileDescription> open_direction_blocking(Direction);
|
||||||
|
|
||||||
void attach(Direction);
|
void attach(Direction);
|
||||||
void detach(Direction);
|
void detach(Direction);
|
||||||
|
@ -71,6 +74,10 @@ private:
|
||||||
uid_t m_uid { 0 };
|
uid_t m_uid { 0 };
|
||||||
|
|
||||||
int m_fifo_id { 0 };
|
int m_fifo_id { 0 };
|
||||||
|
|
||||||
|
WaitQueue m_read_open_queue;
|
||||||
|
WaitQueue m_write_open_queue;
|
||||||
|
Lock m_open_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -205,6 +205,18 @@ void Inode::unregister_watcher(Badge<InodeWatcher>, InodeWatcher& watcher)
|
||||||
m_watchers.remove(&watcher);
|
m_watchers.remove(&watcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FIFO& Inode::fifo()
|
||||||
|
{
|
||||||
|
ASSERT(metadata().is_fifo());
|
||||||
|
|
||||||
|
// FIXME: Release m_fifo when it is closed by all readers and writers
|
||||||
|
if (!m_fifo)
|
||||||
|
m_fifo = FIFO::create(metadata().uid);
|
||||||
|
|
||||||
|
ASSERT(m_fifo);
|
||||||
|
return *m_fifo;
|
||||||
|
}
|
||||||
|
|
||||||
void Inode::set_metadata_dirty(bool metadata_dirty)
|
void Inode::set_metadata_dirty(bool metadata_dirty)
|
||||||
{
|
{
|
||||||
if (m_metadata_dirty == metadata_dirty)
|
if (m_metadata_dirty == metadata_dirty)
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include <AK/RefCounted.h>
|
#include <AK/RefCounted.h>
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
#include <AK/WeakPtr.h>
|
#include <AK/WeakPtr.h>
|
||||||
|
#include <Kernel/FileSystem/FIFO.h>
|
||||||
#include <Kernel/FileSystem/FileSystem.h>
|
#include <Kernel/FileSystem/FileSystem.h>
|
||||||
#include <Kernel/FileSystem/InodeIdentifier.h>
|
#include <Kernel/FileSystem/InodeIdentifier.h>
|
||||||
#include <Kernel/FileSystem/InodeMetadata.h>
|
#include <Kernel/FileSystem/InodeMetadata.h>
|
||||||
|
@ -111,6 +112,8 @@ public:
|
||||||
void register_watcher(Badge<InodeWatcher>, InodeWatcher&);
|
void register_watcher(Badge<InodeWatcher>, InodeWatcher&);
|
||||||
void unregister_watcher(Badge<InodeWatcher>, InodeWatcher&);
|
void unregister_watcher(Badge<InodeWatcher>, InodeWatcher&);
|
||||||
|
|
||||||
|
FIFO& fifo();
|
||||||
|
|
||||||
// For InlineLinkedListNode.
|
// For InlineLinkedListNode.
|
||||||
Inode* m_next { nullptr };
|
Inode* m_next { nullptr };
|
||||||
Inode* m_prev { nullptr };
|
Inode* m_prev { nullptr };
|
||||||
|
@ -134,6 +137,7 @@ private:
|
||||||
RefPtr<LocalSocket> m_socket;
|
RefPtr<LocalSocket> m_socket;
|
||||||
HashTable<InodeWatcher*> m_watchers;
|
HashTable<InodeWatcher*> m_watchers;
|
||||||
bool m_metadata_dirty { false };
|
bool m_metadata_dirty { false };
|
||||||
|
RefPtr<FIFO> m_fifo;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -292,6 +292,23 @@ KResultOr<NonnullRefPtr<FileDescription>> VFS::open(StringView path, int options
|
||||||
if (auto preopen_fd = inode.preopen_fd())
|
if (auto preopen_fd = inode.preopen_fd())
|
||||||
return *preopen_fd;
|
return *preopen_fd;
|
||||||
|
|
||||||
|
if (metadata.is_fifo()) {
|
||||||
|
if (options & O_WRONLY) {
|
||||||
|
auto description = inode.fifo().open_direction_blocking(FIFO::Direction::Writer);
|
||||||
|
description->set_rw_mode(options);
|
||||||
|
description->set_file_flags(options);
|
||||||
|
description->set_original_inode({}, inode);
|
||||||
|
return description;
|
||||||
|
} else if (options & O_RDONLY) {
|
||||||
|
auto description = inode.fifo().open_direction_blocking(FIFO::Direction::Reader);
|
||||||
|
description->set_rw_mode(options);
|
||||||
|
description->set_file_flags(options);
|
||||||
|
description->set_original_inode({}, inode);
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
return KResult(-EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
if (metadata.is_device()) {
|
if (metadata.is_device()) {
|
||||||
if (custody.mount_flags() & MS_NODEV)
|
if (custody.mount_flags() & MS_NODEV)
|
||||||
return KResult(-EACCES);
|
return KResult(-EACCES);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue