2020-01-18 05:38:21 -03:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
|
|
|
|
*
|
2021-04-22 05:24:48 -03:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2020-01-18 05:38:21 -03:00
|
|
|
*/
|
|
|
|
|
|
2021-07-18 06:45:13 -03:00
|
|
|
#include <AK/Atomic.h>
|
2019-06-07 06:43:58 -03:00
|
|
|
#include <AK/StdLibExtras.h>
|
2019-04-06 15:29:48 -03:00
|
|
|
#include <Kernel/FileSystem/FIFO.h>
|
2021-09-07 08:39:11 -03:00
|
|
|
#include <Kernel/FileSystem/OpenFileDescription.h>
|
2021-07-18 04:10:27 -03:00
|
|
|
#include <Kernel/Locking/Mutex.h>
|
2019-06-06 05:54:26 -03:00
|
|
|
#include <Kernel/Process.h>
|
|
|
|
|
#include <Kernel/Thread.h>
|
2018-11-11 22:28:46 -02:00
|
|
|
|
2020-02-15 21:27:42 -03:00
|
|
|
namespace Kernel {
|
|
|
|
|
|
2021-07-18 06:45:13 -03:00
|
|
|
static Atomic<int> s_next_fifo_id = 1;
|
2019-04-25 08:52:07 -03:00
|
|
|
|
2023-03-10 03:53:02 -03:00
|
|
|
ErrorOr<NonnullRefPtr<FIFO>> FIFO::try_create(UserID uid)
|
2019-04-25 08:52:07 -03:00
|
|
|
{
|
2022-04-10 19:08:07 -03:00
|
|
|
auto buffer = TRY(DoubleBuffer::try_create("FIFO: Buffer"sv));
|
2023-03-10 03:53:02 -03:00
|
|
|
return adopt_nonnull_ref_or_enomem(new (nothrow) FIFO(uid, move(buffer)));
|
2019-04-25 08:52:07 -03:00
|
|
|
}
|
|
|
|
|
|
2023-03-06 15:29:25 -03:00
|
|
|
ErrorOr<NonnullRefPtr<OpenFileDescription>> FIFO::open_direction(FIFO::Direction direction)
|
2019-04-28 23:55:54 -03:00
|
|
|
{
|
2021-09-07 08:39:11 -03:00
|
|
|
auto description = TRY(OpenFileDescription::try_create(*this));
|
2021-09-05 11:04:33 -03:00
|
|
|
attach(direction);
|
|
|
|
|
description->set_fifo_direction({}, direction);
|
2019-06-13 17:03:04 -03:00
|
|
|
return description;
|
2019-04-28 23:55:54 -03:00
|
|
|
}
|
|
|
|
|
|
2023-03-06 15:29:25 -03:00
|
|
|
ErrorOr<NonnullRefPtr<OpenFileDescription>> FIFO::open_direction_blocking(FIFO::Direction direction)
|
2020-07-16 18:23:03 -03:00
|
|
|
{
|
2021-07-17 20:13:34 -03:00
|
|
|
MutexLocker locker(m_open_lock);
|
2020-07-16 18:23:03 -03:00
|
|
|
|
2021-09-05 11:04:33 -03:00
|
|
|
auto description = TRY(open_direction(direction));
|
2020-07-16 18:23:03 -03:00
|
|
|
|
|
|
|
|
if (direction == Direction::Reader) {
|
|
|
|
|
m_read_open_queue.wake_all();
|
|
|
|
|
|
|
|
|
|
if (m_writers == 0) {
|
|
|
|
|
locker.unlock();
|
2022-07-11 14:32:29 -03:00
|
|
|
m_write_open_queue.wait_forever("FIFO"sv);
|
2020-07-16 18:23:03 -03:00
|
|
|
locker.lock();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (direction == Direction::Writer) {
|
|
|
|
|
m_write_open_queue.wake_all();
|
|
|
|
|
|
|
|
|
|
if (m_readers == 0) {
|
|
|
|
|
locker.unlock();
|
2022-07-11 14:32:29 -03:00
|
|
|
m_read_open_queue.wait_forever("FIFO"sv);
|
2020-07-16 18:23:03 -03:00
|
|
|
locker.lock();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return description;
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-28 17:11:16 -03:00
|
|
|
FIFO::FIFO(UserID uid, NonnullOwnPtr<DoubleBuffer> buffer)
|
2021-08-01 06:30:52 -03:00
|
|
|
: m_buffer(move(buffer))
|
|
|
|
|
, m_uid(uid)
|
2019-04-25 08:52:07 -03:00
|
|
|
{
|
2020-01-07 03:29:50 -03:00
|
|
|
m_fifo_id = ++s_next_fifo_id;
|
2020-11-29 20:05:27 -03:00
|
|
|
|
|
|
|
|
// Use the same block condition for read and write
|
2021-08-01 06:30:52 -03:00
|
|
|
m_buffer->set_unblock_callback([this]() {
|
2020-11-29 20:05:27 -03:00
|
|
|
evaluate_block_conditions();
|
|
|
|
|
});
|
2019-04-25 08:52:07 -03:00
|
|
|
}
|
|
|
|
|
|
2022-03-16 16:15:15 -03:00
|
|
|
FIFO::~FIFO() = default;
|
2018-11-11 22:28:46 -02:00
|
|
|
|
2019-04-28 23:55:54 -03:00
|
|
|
void FIFO::attach(Direction direction)
|
2018-11-11 22:28:46 -02:00
|
|
|
{
|
2019-05-17 23:14:22 -03:00
|
|
|
if (direction == Direction::Reader) {
|
2018-11-11 22:28:46 -02:00
|
|
|
++m_readers;
|
2019-05-17 23:14:22 -03:00
|
|
|
} else if (direction == Direction::Writer) {
|
2018-11-11 22:28:46 -02:00
|
|
|
++m_writers;
|
|
|
|
|
}
|
2020-11-29 20:05:27 -03:00
|
|
|
|
|
|
|
|
evaluate_block_conditions();
|
2018-11-11 22:28:46 -02:00
|
|
|
}
|
|
|
|
|
|
2019-04-28 23:55:54 -03:00
|
|
|
void FIFO::detach(Direction direction)
|
2018-11-11 22:28:46 -02:00
|
|
|
{
|
2019-05-17 23:14:22 -03:00
|
|
|
if (direction == Direction::Reader) {
|
2021-02-23 16:42:32 -03:00
|
|
|
VERIFY(m_readers);
|
2018-11-11 22:28:46 -02:00
|
|
|
--m_readers;
|
2019-05-17 23:14:22 -03:00
|
|
|
} else if (direction == Direction::Writer) {
|
2021-02-23 16:42:32 -03:00
|
|
|
VERIFY(m_writers);
|
2018-11-11 22:28:46 -02:00
|
|
|
--m_writers;
|
|
|
|
|
}
|
2020-11-29 20:05:27 -03:00
|
|
|
|
|
|
|
|
evaluate_block_conditions();
|
2018-11-11 22:28:46 -02:00
|
|
|
}
|
|
|
|
|
|
2022-04-01 14:58:27 -03:00
|
|
|
bool FIFO::can_read(OpenFileDescription const&, u64) const
|
2018-11-11 22:28:46 -02:00
|
|
|
{
|
2021-08-01 06:30:52 -03:00
|
|
|
return !m_buffer->is_empty() || !m_writers;
|
2018-11-11 22:28:46 -02:00
|
|
|
}
|
|
|
|
|
|
2022-04-01 14:58:27 -03:00
|
|
|
bool FIFO::can_write(OpenFileDescription const&, u64) const
|
2018-11-11 22:28:46 -02:00
|
|
|
{
|
2021-08-01 06:30:52 -03:00
|
|
|
return m_buffer->space_for_writing() || !m_readers;
|
2018-11-11 22:28:46 -02:00
|
|
|
}
|
|
|
|
|
|
2021-11-07 20:51:39 -03:00
|
|
|
ErrorOr<size_t> FIFO::read(OpenFileDescription& fd, u64, UserOrKernelBuffer& buffer, size_t size)
|
2018-11-11 22:28:46 -02:00
|
|
|
{
|
2021-08-10 16:03:36 -03:00
|
|
|
if (m_buffer->is_empty()) {
|
|
|
|
|
if (!m_writers)
|
|
|
|
|
return 0;
|
2021-08-28 18:19:45 -03:00
|
|
|
if (!fd.is_blocking())
|
2021-08-10 16:03:36 -03:00
|
|
|
return EAGAIN;
|
|
|
|
|
}
|
2021-08-01 06:30:52 -03:00
|
|
|
return m_buffer->read(buffer, size);
|
2018-11-11 22:28:46 -02:00
|
|
|
}
|
|
|
|
|
|
2022-04-01 14:58:27 -03:00
|
|
|
ErrorOr<size_t> FIFO::write(OpenFileDescription& fd, u64, UserOrKernelBuffer const& buffer, size_t size)
|
2018-11-11 22:28:46 -02:00
|
|
|
{
|
2022-10-23 05:30:12 -03:00
|
|
|
if (!m_readers)
|
2021-03-15 05:04:04 -03:00
|
|
|
return EPIPE;
|
2021-08-10 16:03:36 -03:00
|
|
|
if (!fd.is_blocking() && m_buffer->space_for_writing() == 0)
|
|
|
|
|
return EAGAIN;
|
2021-03-15 05:04:04 -03:00
|
|
|
|
2021-08-01 06:30:52 -03:00
|
|
|
return m_buffer->write(buffer, size);
|
2018-11-11 22:28:46 -02:00
|
|
|
}
|
2019-04-28 23:55:54 -03:00
|
|
|
|
2022-04-01 14:58:27 -03:00
|
|
|
ErrorOr<NonnullOwnPtr<KString>> FIFO::pseudo_path(OpenFileDescription const&) const
|
2019-04-28 23:55:54 -03:00
|
|
|
{
|
2021-11-29 08:05:19 -03:00
|
|
|
return KString::formatted("fifo:{}", m_fifo_id);
|
2019-04-28 23:55:54 -03:00
|
|
|
}
|
2020-02-15 21:27:42 -03:00
|
|
|
|
2021-12-17 07:22:27 -03:00
|
|
|
ErrorOr<struct stat> FIFO::stat() const
|
2020-09-06 13:31:51 -03:00
|
|
|
{
|
2021-12-17 07:22:27 -03:00
|
|
|
struct stat st = {};
|
2020-09-06 13:31:51 -03:00
|
|
|
st.st_mode = S_IFIFO;
|
2021-12-17 07:22:27 -03:00
|
|
|
return st;
|
2020-09-06 13:31:51 -03:00
|
|
|
}
|
|
|
|
|
|
2020-02-15 21:27:42 -03:00
|
|
|
}
|