mirror of
https://github.com/fergalmoran/ladybird.git
synced 2026-01-07 17:15:26 +00:00
Instead of locking it twice, we now frontload all the work that doesn't touch the fd table, and then only lock it towards the end of the syscall. The benefit here is simplicity. The downside is that we do a bit of unnecessary work in the EMFILE error case, but we don't need to optimize that case anyway.
56 lines
1.7 KiB
C++
56 lines
1.7 KiB
C++
/*
|
|
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <Kernel/FileSystem/FIFO.h>
|
|
#include <Kernel/Process.h>
|
|
|
|
namespace Kernel {
|
|
|
|
ErrorOr<FlatPtr> Process::sys$pipe(Userspace<int*> pipefd, int flags)
|
|
{
|
|
VERIFY_NO_PROCESS_BIG_LOCK(this)
|
|
TRY(require_promise(Pledge::stdio));
|
|
|
|
// Reject flags other than O_CLOEXEC, O_NONBLOCK
|
|
if ((flags & (O_CLOEXEC | O_NONBLOCK)) != flags)
|
|
return EINVAL;
|
|
|
|
u32 fd_flags = (flags & O_CLOEXEC) ? FD_CLOEXEC : 0;
|
|
auto fifo = TRY(FIFO::try_create(uid()));
|
|
|
|
auto reader_description = TRY(fifo->open_direction(FIFO::Direction::Reader));
|
|
auto writer_description = TRY(fifo->open_direction(FIFO::Direction::Writer));
|
|
|
|
reader_description->set_readable(true);
|
|
writer_description->set_writable(true);
|
|
if (flags & O_NONBLOCK) {
|
|
reader_description->set_blocking(false);
|
|
writer_description->set_blocking(false);
|
|
}
|
|
|
|
TRY(m_fds.with_exclusive([&](auto& fds) -> ErrorOr<void> {
|
|
auto reader_fd_allocation = TRY(fds.allocate());
|
|
auto writer_fd_allocation = TRY(fds.allocate());
|
|
|
|
fds[reader_fd_allocation.fd].set(move(reader_description), fd_flags);
|
|
fds[writer_fd_allocation.fd].set(move(writer_description), fd_flags);
|
|
|
|
int fds_for_userspace[2] = {
|
|
reader_fd_allocation.fd,
|
|
writer_fd_allocation.fd,
|
|
};
|
|
if (copy_to_user(pipefd, fds_for_userspace, sizeof(fds_for_userspace)).is_error()) {
|
|
fds[reader_fd_allocation.fd] = {};
|
|
fds[writer_fd_allocation.fd] = {};
|
|
return EFAULT;
|
|
}
|
|
return {};
|
|
}));
|
|
return 0;
|
|
}
|
|
|
|
}
|