1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 17:17:44 +00:00

Kernel: Switch process file descriptor table from spinlock to mutex

There's no reason for this to use a spinlock. Instead, let's allow
threads to block if someone else is using the descriptor table.
This commit is contained in:
Andreas Kling 2022-01-29 01:29:07 +01:00
parent 8ebec2938c
commit b56646e293
16 changed files with 37 additions and 37 deletions

View file

@ -37,7 +37,7 @@ ErrorOr<FlatPtr> Process::sys$anon_create(size_t size, int options)
if (options & O_CLOEXEC)
fd_flags |= FD_CLOEXEC;
m_fds.with([&](auto& fds) { fds[new_fd.fd].set(move(description), fd_flags); });
m_fds.with_exclusive([&](auto& fds) { fds[new_fd.fd].set(move(description), fd_flags); });
return new_fd.fd;
}

View file

@ -13,7 +13,7 @@ ErrorOr<FlatPtr> Process::sys$dup2(int old_fd, int new_fd)
{
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this);
TRY(require_promise(Pledge::stdio));
return m_fds.with([&](auto& fds) -> ErrorOr<FlatPtr> {
return m_fds.with_exclusive([&](auto& fds) -> ErrorOr<FlatPtr> {
auto description = TRY(fds.open_file_description(old_fd));
if (old_fd == new_fd)
return new_fd;

View file

@ -536,7 +536,7 @@ ErrorOr<void> Process::do_exec(NonnullRefPtr<OpenFileDescription> main_program_d
clear_futex_queues_on_exec();
m_fds.with([&](auto& fds) {
m_fds.with_exclusive([&](auto& fds) {
fds.change_each([&](auto& file_description_metadata) {
if (file_description_metadata.is_valid() && file_description_metadata.flags() & FD_CLOEXEC)
file_description_metadata = {};
@ -545,7 +545,7 @@ ErrorOr<void> Process::do_exec(NonnullRefPtr<OpenFileDescription> main_program_d
if (main_program_fd_allocation.has_value()) {
main_program_description->set_readable(true);
m_fds.with([&](auto& fds) { fds[main_program_fd_allocation->fd].set(move(main_program_description), FD_CLOEXEC); });
m_fds.with_exclusive([&](auto& fds) { fds[main_program_fd_allocation->fd].set(move(main_program_description), FD_CLOEXEC); });
}
new_main_thread = nullptr;

View file

@ -23,16 +23,16 @@ ErrorOr<FlatPtr> Process::sys$fcntl(int fd, int cmd, u32 arg)
int arg_fd = (int)arg;
if (arg_fd < 0)
return EINVAL;
return m_fds.with([&](auto& fds) -> ErrorOr<FlatPtr> {
return m_fds.with_exclusive([&](auto& fds) -> ErrorOr<FlatPtr> {
auto fd_allocation = TRY(fds.allocate(arg_fd));
fds[fd_allocation.fd].set(*description);
return fd_allocation.fd;
});
}
case F_GETFD:
return m_fds.with([fd](auto& fds) { return fds[fd].flags(); });
return m_fds.with_exclusive([fd](auto& fds) { return fds[fd].flags(); });
case F_SETFD:
m_fds.with([fd, arg](auto& fds) { fds[fd].set_flags(arg); });
m_fds.with_exclusive([fd, arg](auto& fds) { fds[fd].set_flags(arg); });
break;
case F_GETFL:
return description->file_flags();

View file

@ -23,8 +23,8 @@ ErrorOr<FlatPtr> Process::sys$fork(RegisterState& regs)
child->m_veil_state = m_veil_state;
child->m_unveiled_paths = m_unveiled_paths.deep_copy();
TRY(child->m_fds.with([&](auto& child_fds) {
return m_fds.with([&](auto& parent_fds) {
TRY(child->m_fds.with_exclusive([&](auto& child_fds) {
return m_fds.with_exclusive([&](auto& parent_fds) {
return child_fds.try_clone(parent_fds);
});
}));

View file

@ -26,7 +26,7 @@ ErrorOr<FlatPtr> Process::sys$create_inode_watcher(u32 flags)
if (flags & static_cast<unsigned>(InodeWatcherFlags::Nonblock))
description->set_blocking(false);
return m_fds.with([&](auto& fds) -> ErrorOr<FlatPtr> {
return m_fds.with_exclusive([&](auto& fds) -> ErrorOr<FlatPtr> {
fds[fd_allocation.fd].set(move(description));
if (flags & static_cast<unsigned>(InodeWatcherFlags::CloseOnExec))

View file

@ -59,7 +59,7 @@ ErrorOr<FlatPtr> Process::sys$open(Userspace<const Syscall::SC_open_params*> use
if (description->inode() && description->inode()->socket())
return ENXIO;
return m_fds.with([&](auto& fds) -> ErrorOr<FlatPtr> {
return m_fds.with_exclusive([&](auto& fds) -> ErrorOr<FlatPtr> {
u32 fd_flags = (options & O_CLOEXEC) ? FD_CLOEXEC : 0;
fds[fd_allocation.fd].set(move(description), fd_flags);
return fd_allocation.fd;
@ -72,7 +72,7 @@ ErrorOr<FlatPtr> Process::sys$close(int fd)
TRY(require_promise(Pledge::stdio));
auto description = TRY(open_file_description(fd));
auto result = description->close();
m_fds.with([fd](auto& fds) { fds[fd] = {}; });
m_fds.with_exclusive([fd](auto& fds) { fds[fd] = {}; });
if (result.is_error())
return result.release_error();
return 0;

View file

@ -13,7 +13,7 @@ ErrorOr<FlatPtr> Process::sys$pipe(int pipefd[2], int flags)
{
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
TRY(require_promise(Pledge::stdio));
auto open_count = fds().with([](auto& fds) { return fds.open_count(); });
auto open_count = fds().with_shared([](auto& fds) { return fds.open_count(); });
if (open_count + 2 > OpenFileDescriptions::max_open())
return EMFILE;
// Reject flags other than O_CLOEXEC, O_NONBLOCK
@ -26,7 +26,7 @@ ErrorOr<FlatPtr> Process::sys$pipe(int pipefd[2], int flags)
ScopedDescriptionAllocation reader_fd_allocation;
ScopedDescriptionAllocation writer_fd_allocation;
TRY(m_fds.with([&](auto& fds) -> ErrorOr<void> {
TRY(m_fds.with_exclusive([&](auto& fds) -> ErrorOr<void> {
reader_fd_allocation = TRY(fds.allocate());
writer_fd_allocation = TRY(fds.allocate());
return {};
@ -42,7 +42,7 @@ ErrorOr<FlatPtr> Process::sys$pipe(int pipefd[2], int flags)
writer_description->set_blocking(false);
}
TRY(m_fds.with([&](auto& fds) -> ErrorOr<void> {
TRY(m_fds.with_exclusive([&](auto& fds) -> ErrorOr<void> {
fds[reader_fd_allocation.fd].set(move(reader_description), fd_flags);
fds[writer_fd_allocation.fd].set(move(writer_description), fd_flags);
return {};

View file

@ -49,7 +49,7 @@ ErrorOr<FlatPtr> Process::sys$poll(Userspace<const Syscall::SC_poll_params*> use
for (size_t i = 0; i < params.nfds; i++) {
auto& pfd = fds_copy[i];
auto description = TRY(m_fds.with([&](auto& fds) { return fds.open_file_description(pfd.fd); }));
auto description = TRY(m_fds.with_shared([&](auto& fds) { return fds.open_file_description(pfd.fd); }));
BlockFlags block_flags = BlockFlags::Exception; // always want POLLERR, POLLHUP, POLLNVAL
if (pfd.events & POLLIN)
block_flags |= BlockFlags::Read;

View file

@ -14,7 +14,7 @@ using BlockFlags = Thread::FileBlocker::BlockFlags;
static ErrorOr<NonnullRefPtr<OpenFileDescription>> open_readable_file_description(auto& fds, int fd)
{
auto description = TRY(fds.with([&](auto& fds) { return fds.open_file_description(fd); }));
auto description = TRY(fds.with_shared([&](auto& fds) { return fds.open_file_description(fd); }));
if (!description->is_readable())
return EBADF;
if (description->is_directory())

View file

@ -40,7 +40,7 @@ ErrorOr<FlatPtr> Process::sys$recvfd(int sockfd, int options)
if (!socket.is_local())
return EAFNOSUPPORT;
auto fd_allocation = TRY(m_fds.with([](auto& fds) { return fds.allocate(); }));
auto fd_allocation = TRY(m_fds.with_exclusive([](auto& fds) { return fds.allocate(); }));
auto& local_socket = static_cast<LocalSocket&>(socket);
auto received_description = TRY(local_socket.recvfd(*socket_description));
@ -49,7 +49,7 @@ ErrorOr<FlatPtr> Process::sys$recvfd(int sockfd, int options)
if (options & O_CLOEXEC)
fd_flags |= FD_CLOEXEC;
m_fds.with([&](auto& fds) { fds[fd_allocation.fd].set(move(received_description), fd_flags); });
m_fds.with_exclusive([&](auto& fds) { fds[fd_allocation.fd].set(move(received_description), fd_flags); });
return fd_allocation.fd;
}

View file

@ -39,7 +39,7 @@ ErrorOr<FlatPtr> Process::sys$socket(int domain, int type, int protocol)
if ((type & SOCK_TYPE_MASK) == SOCK_RAW && !is_superuser())
return EACCES;
return m_fds.with([&](auto& fds) -> ErrorOr<FlatPtr> {
return m_fds.with_exclusive([&](auto& fds) -> ErrorOr<FlatPtr> {
auto fd_allocation = TRY(fds.allocate());
auto socket = TRY(Socket::create(domain, type, protocol));
auto description = TRY(OpenFileDescription::try_create(socket));
@ -51,7 +51,7 @@ ErrorOr<FlatPtr> Process::sys$socket(int domain, int type, int protocol)
ErrorOr<FlatPtr> Process::sys$bind(int sockfd, Userspace<const sockaddr*> address, socklen_t address_length)
{
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
return m_fds.with([&](auto& fds) -> ErrorOr<FlatPtr> {
return m_fds.with_exclusive([&](auto& fds) -> ErrorOr<FlatPtr> {
auto description = TRY(fds.open_file_description(sockfd));
if (!description->is_socket())
return ENOTSOCK;
@ -67,7 +67,7 @@ ErrorOr<FlatPtr> Process::sys$listen(int sockfd, int backlog)
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
if (backlog < 0)
return EINVAL;
return m_fds.with([&](auto& fds) -> ErrorOr<FlatPtr> {
return m_fds.with_exclusive([&](auto& fds) -> ErrorOr<FlatPtr> {
auto description = TRY(fds.open_file_description(sockfd));
if (!description->is_socket())
return ENOTSOCK;
@ -99,7 +99,7 @@ ErrorOr<FlatPtr> Process::sys$accept4(Userspace<const Syscall::SC_accept4_params
ScopedDescriptionAllocation fd_allocation;
RefPtr<OpenFileDescription> accepting_socket_description;
TRY(m_fds.with([&](auto& fds) -> ErrorOr<void> {
TRY(m_fds.with_exclusive([&](auto& fds) -> ErrorOr<void> {
fd_allocation = TRY(fds.allocate());
accepting_socket_description = TRY(fds.open_file_description(accepting_socket_fd));
return {};
@ -138,7 +138,7 @@ ErrorOr<FlatPtr> Process::sys$accept4(Userspace<const Syscall::SC_accept4_params
if (flags & SOCK_CLOEXEC)
fd_flags |= FD_CLOEXEC;
TRY(m_fds.with([&](auto& fds) -> ErrorOr<void> {
TRY(m_fds.with_exclusive([&](auto& fds) -> ErrorOr<void> {
fds[fd_allocation.fd].set(move(accepted_socket_description), fd_flags);
return {};
}));
@ -361,7 +361,7 @@ ErrorOr<FlatPtr> Process::sys$socketpair(Userspace<const Syscall::SC_socketpair_
auto pair = TRY(LocalSocket::try_create_connected_pair(params.type & SOCK_TYPE_MASK));
return m_fds.with([&](auto& fds) -> ErrorOr<FlatPtr> {
return m_fds.with_exclusive([&](auto& fds) -> ErrorOr<FlatPtr> {
auto fd_allocation0 = TRY(fds.allocate());
auto fd_allocation1 = TRY(fds.allocate());