86 lines
1.9 KiB
C++
86 lines
1.9 KiB
C++
#include <kernel/FS/Pipe.h>
|
|
#include <kernel/Lock/LockGuard.h>
|
|
#include <kernel/Thread.h>
|
|
#include <kernel/Timer/Timer.h>
|
|
|
|
namespace Kernel
|
|
{
|
|
|
|
BAN::ErrorOr<BAN::RefPtr<Inode>> Pipe::create(const Credentials& credentials)
|
|
{
|
|
Pipe* pipe = new Pipe(credentials);
|
|
if (pipe == nullptr)
|
|
return BAN::Error::from_errno(ENOMEM);
|
|
return BAN::RefPtr<Inode>::adopt(pipe);
|
|
}
|
|
|
|
Pipe::Pipe(const Credentials& credentials)
|
|
: m_uid(credentials.euid())
|
|
, m_gid(credentials.egid())
|
|
{
|
|
timespec current_time = SystemTimer::get().real_time();
|
|
m_atime = current_time;
|
|
m_mtime = current_time;
|
|
m_ctime = current_time;
|
|
}
|
|
|
|
void Pipe::clone_writing()
|
|
{
|
|
LockGuard _(m_mutex);
|
|
ASSERT(m_writing_count > 0);
|
|
m_writing_count++;
|
|
}
|
|
|
|
void Pipe::close_writing()
|
|
{
|
|
LockGuard _(m_mutex);
|
|
ASSERT(m_writing_count > 0);
|
|
m_writing_count--;
|
|
if (m_writing_count == 0)
|
|
m_semaphore.unblock();
|
|
}
|
|
|
|
BAN::ErrorOr<size_t> Pipe::read_impl(off_t, BAN::ByteSpan buffer)
|
|
{
|
|
LockGuard _(m_mutex);
|
|
while (m_buffer.empty())
|
|
{
|
|
if (m_writing_count == 0)
|
|
return 0;
|
|
LockFreeGuard lock_free(m_mutex);
|
|
TRY(Thread::current().block_or_eintr_indefinite(m_semaphore));
|
|
}
|
|
|
|
size_t to_copy = BAN::Math::min<size_t>(buffer.size(), m_buffer.size());
|
|
memcpy(buffer.data(), m_buffer.data(), to_copy);
|
|
|
|
memmove(m_buffer.data(), m_buffer.data() + to_copy, m_buffer.size() - to_copy);
|
|
MUST(m_buffer.resize(m_buffer.size() - to_copy));
|
|
|
|
m_atime = SystemTimer::get().real_time();
|
|
|
|
m_semaphore.unblock();
|
|
|
|
return to_copy;
|
|
}
|
|
|
|
BAN::ErrorOr<size_t> Pipe::write_impl(off_t, BAN::ConstByteSpan buffer)
|
|
{
|
|
LockGuard _(m_mutex);
|
|
|
|
size_t old_size = m_buffer.size();
|
|
|
|
TRY(m_buffer.resize(old_size + buffer.size()));
|
|
memcpy(m_buffer.data() + old_size, buffer.data(), buffer.size());
|
|
|
|
timespec current_time = SystemTimer::get().real_time();
|
|
m_mtime = current_time;
|
|
m_ctime = current_time;
|
|
|
|
m_semaphore.unblock();
|
|
|
|
return buffer.size();
|
|
}
|
|
|
|
}
|