1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-22 16:55:09 +00:00

Kernel: Add bitwise operators for Thread::FileBlocker::BlockFlags enum

Switch to using type-safe bitwise operators for the BlockFlags class,
this cleans up a lot of boilerplate casts which are necessary when the
enum is declared as `enum class`.
This commit is contained in:
Brian Gianforcaro 2021-03-07 03:01:11 -08:00 committed by Andreas Kling
parent eaef57443c
commit 5f6ab77352
7 changed files with 57 additions and 47 deletions

View file

@ -98,22 +98,23 @@ KResult FileDescription::attach()
Thread::FileBlocker::BlockFlags FileDescription::should_unblock(Thread::FileBlocker::BlockFlags block_flags) const Thread::FileBlocker::BlockFlags FileDescription::should_unblock(Thread::FileBlocker::BlockFlags block_flags) const
{ {
u32 unblock_flags = (u32)Thread::FileBlocker::BlockFlags::None; using BlockFlags = Thread::FileBlocker::BlockFlags;
if (((u32)block_flags & (u32)Thread::FileBlocker::BlockFlags::Read) && can_read()) BlockFlags unblock_flags = BlockFlags::None;
unblock_flags |= (u32)Thread::FileBlocker::BlockFlags::Read; if (has_flag(block_flags, BlockFlags::Read) && can_read())
if (((u32)block_flags & (u32)Thread::FileBlocker::BlockFlags::Write) && can_write()) unblock_flags |= BlockFlags::Read;
unblock_flags |= (u32)Thread::FileBlocker::BlockFlags::Write; if (has_flag(block_flags, BlockFlags::Write) && can_write())
unblock_flags |= BlockFlags::Write;
// TODO: Implement Thread::FileBlocker::BlockFlags::Exception // TODO: Implement Thread::FileBlocker::BlockFlags::Exception
if ((u32)block_flags & (u32)Thread::FileBlocker::BlockFlags::SocketFlags) { if (has_flag(block_flags, BlockFlags::SocketFlags)) {
auto* sock = socket(); auto* sock = socket();
VERIFY(sock); VERIFY(sock);
if (((u32)block_flags & (u32)Thread::FileBlocker::BlockFlags::Accept) && sock->can_accept()) if (has_flag(block_flags, BlockFlags::Accept) && sock->can_accept())
unblock_flags |= (u32)Thread::FileBlocker::BlockFlags::Accept; unblock_flags |= BlockFlags::Accept;
if (((u32)block_flags & (u32)Thread::FileBlocker::BlockFlags::Connect) && sock->setup_state() == Socket::SetupState::Completed) if (has_flag(block_flags, BlockFlags::Connect) && sock->setup_state() == Socket::SetupState::Completed)
unblock_flags |= (u32)Thread::FileBlocker::BlockFlags::Connect; unblock_flags |= BlockFlags::Connect;
} }
return (Thread::FileBlocker::BlockFlags)unblock_flags; return unblock_flags;
} }
KResult FileDescription::stat(::stat& buffer) KResult FileDescription::stat(::stat& buffer)

View file

@ -47,6 +47,8 @@ namespace Kernel {
static AK::Singleton<Lockable<HashTable<IPv4Socket*>>> s_table; static AK::Singleton<Lockable<HashTable<IPv4Socket*>>> s_table;
using BlockFlags = Thread::FileDescriptionBlocker::BlockFlags;
Lockable<HashTable<IPv4Socket*>>& IPv4Socket::all_sockets() Lockable<HashTable<IPv4Socket*>>& IPv4Socket::all_sockets()
{ {
return *s_table; return *s_table;
@ -247,11 +249,11 @@ KResultOr<size_t> IPv4Socket::receive_byte_buffered(FileDescription& description
return EAGAIN; return EAGAIN;
locker.unlock(); locker.unlock();
auto unblocked_flags = Thread::FileDescriptionBlocker::BlockFlags::None; auto unblocked_flags = BlockFlags::None;
auto res = Thread::current()->block<Thread::ReadBlocker>({}, description, unblocked_flags); auto res = Thread::current()->block<Thread::ReadBlocker>({}, description, unblocked_flags);
locker.lock(); locker.lock();
if (!((u32)unblocked_flags & (u32)Thread::FileDescriptionBlocker::BlockFlags::Read)) { if (!has_flag(unblocked_flags, BlockFlags::Read)) {
if (res.was_interrupted()) if (res.was_interrupted())
return EINTR; return EINTR;
@ -300,11 +302,11 @@ KResultOr<size_t> IPv4Socket::receive_packet_buffered(FileDescription& descripti
} }
locker.unlock(); locker.unlock();
auto unblocked_flags = Thread::FileDescriptionBlocker::BlockFlags::None; auto unblocked_flags = BlockFlags::None;
auto res = Thread::current()->block<Thread::ReadBlocker>({}, description, unblocked_flags); auto res = Thread::current()->block<Thread::ReadBlocker>({}, description, unblocked_flags);
locker.lock(); locker.lock();
if (!((u32)unblocked_flags & (u32)Thread::FileDescriptionBlocker::BlockFlags::Read)) { if (!has_flag(unblocked_flags, BlockFlags::Read)) {
if (res.was_interrupted()) if (res.was_interrupted())
return EINTR; return EINTR;

View file

@ -192,7 +192,7 @@ KResult LocalSocket::connect(FileDescription& description, Userspace<const socka
dbgln_if(LOCAL_SOCKET_DEBUG, "LocalSocket({}) connect({}) status is {}", this, safe_address, to_string(setup_state())); dbgln_if(LOCAL_SOCKET_DEBUG, "LocalSocket({}) connect({}) status is {}", this, safe_address, to_string(setup_state()));
if (!((u32)unblock_flags & (u32)Thread::FileDescriptionBlocker::BlockFlags::Connect)) { if (!has_flag(unblock_flags, Thread::FileDescriptionBlocker::BlockFlags::Connect)) {
set_connect_side_role(Role::None); set_connect_side_role(Role::None);
return ECONNREFUSED; return ECONNREFUSED;
} }

View file

@ -30,6 +30,8 @@
namespace Kernel { namespace Kernel {
using BlockFlags = Thread::FileBlocker::BlockFlags;
KResultOr<ssize_t> Process::sys$readv(int fd, Userspace<const struct iovec*> iov, int iov_count) KResultOr<ssize_t> Process::sys$readv(int fd, Userspace<const struct iovec*> iov, int iov_count)
{ {
REQUIRE_PROMISE(stdio); REQUIRE_PROMISE(stdio);
@ -65,10 +67,10 @@ KResultOr<ssize_t> Process::sys$readv(int fd, Userspace<const struct iovec*> iov
for (auto& vec : vecs) { for (auto& vec : vecs) {
if (description->is_blocking()) { if (description->is_blocking()) {
if (!description->can_read()) { if (!description->can_read()) {
auto unblock_flags = Thread::FileBlocker::BlockFlags::None; auto unblock_flags = BlockFlags::None;
if (Thread::current()->block<Thread::ReadBlocker>({}, *description, unblock_flags).was_interrupted()) if (Thread::current()->block<Thread::ReadBlocker>({}, *description, unblock_flags).was_interrupted())
return EINTR; return EINTR;
if (!((u32)unblock_flags & (u32)Thread::FileBlocker::BlockFlags::Read)) if (!has_flag(unblock_flags, BlockFlags::Read))
return EAGAIN; return EAGAIN;
// TODO: handle exceptions in unblock_flags // TODO: handle exceptions in unblock_flags
} }
@ -102,10 +104,10 @@ KResultOr<ssize_t> Process::sys$read(int fd, Userspace<u8*> buffer, ssize_t size
return EISDIR; return EISDIR;
if (description->is_blocking()) { if (description->is_blocking()) {
if (!description->can_read()) { if (!description->can_read()) {
auto unblock_flags = Thread::FileBlocker::BlockFlags::None; auto unblock_flags = BlockFlags::None;
if (Thread::current()->block<Thread::ReadBlocker>({}, *description, unblock_flags).was_interrupted()) if (Thread::current()->block<Thread::ReadBlocker>({}, *description, unblock_flags).was_interrupted())
return EINTR; return EINTR;
if (!((u32)unblock_flags & (u32)Thread::FileBlocker::BlockFlags::Read)) if (!has_flag(unblock_flags, BlockFlags::Read))
return EAGAIN; return EAGAIN;
// TODO: handle exceptions in unblock_flags // TODO: handle exceptions in unblock_flags
} }

View file

@ -32,6 +32,8 @@
namespace Kernel { namespace Kernel {
using BlockFlags = Thread::FileBlocker::BlockFlags;
KResultOr<int> Process::sys$select(Userspace<const Syscall::SC_select_params*> user_params) KResultOr<int> Process::sys$select(Userspace<const Syscall::SC_select_params*> user_params)
{ {
REQUIRE_PROMISE(stdio); REQUIRE_PROMISE(stdio);
@ -76,14 +78,14 @@ KResultOr<int> Process::sys$select(Userspace<const Syscall::SC_select_params*> u
Thread::SelectBlocker::FDVector fds_info; Thread::SelectBlocker::FDVector fds_info;
Vector<int, FD_SETSIZE> fds; Vector<int, FD_SETSIZE> fds;
for (int fd = 0; fd < params.nfds; fd++) { for (int fd = 0; fd < params.nfds; fd++) {
u32 block_flags = (u32)Thread::FileBlocker::BlockFlags::None; auto block_flags = BlockFlags::None;
if (params.readfds && FD_ISSET(fd, &fds_read)) if (params.readfds && FD_ISSET(fd, &fds_read))
block_flags |= (u32)Thread::FileBlocker::BlockFlags::Read; block_flags |= BlockFlags::Read;
if (params.writefds && FD_ISSET(fd, &fds_write)) if (params.writefds && FD_ISSET(fd, &fds_write))
block_flags |= (u32)Thread::FileBlocker::BlockFlags::Write; block_flags |= BlockFlags::Write;
if (params.exceptfds && FD_ISSET(fd, &fds_except)) if (params.exceptfds && FD_ISSET(fd, &fds_except))
block_flags |= (u32)Thread::FileBlocker::BlockFlags::Exception; block_flags |= BlockFlags::Exception;
if (block_flags == (u32)Thread::FileBlocker::BlockFlags::None) if (block_flags == BlockFlags::None)
continue; continue;
auto description = file_description(fd); auto description = file_description(fd);
@ -91,7 +93,7 @@ KResultOr<int> Process::sys$select(Userspace<const Syscall::SC_select_params*> u
dbgln("sys$select: Bad fd number {}", fd); dbgln("sys$select: Bad fd number {}", fd);
return EBADF; return EBADF;
} }
fds_info.append({ description.release_nonnull(), (Thread::FileBlocker::BlockFlags)block_flags }); fds_info.append({ description.release_nonnull(), block_flags });
fds.append(fd); fds.append(fd);
} }
@ -113,17 +115,17 @@ KResultOr<int> Process::sys$select(Userspace<const Syscall::SC_select_params*> u
int marked_fd_count = 0; int marked_fd_count = 0;
for (size_t i = 0; i < fds_info.size(); i++) { for (size_t i = 0; i < fds_info.size(); i++) {
auto& fd_entry = fds_info[i]; auto& fd_entry = fds_info[i];
if (fd_entry.unblocked_flags == Thread::FileBlocker::BlockFlags::None) if (fd_entry.unblocked_flags == BlockFlags::None)
continue; continue;
if (params.readfds && ((u32)fd_entry.unblocked_flags & (u32)Thread::FileBlocker::BlockFlags::Read)) { if (params.readfds && has_flag(fd_entry.unblocked_flags, BlockFlags::Read)) {
FD_SET(fds[i], &fds_read); FD_SET(fds[i], &fds_read);
marked_fd_count++; marked_fd_count++;
} }
if (params.writefds && ((u32)fd_entry.unblocked_flags & (u32)Thread::FileBlocker::BlockFlags::Write)) { if (params.writefds && has_flag(fd_entry.unblocked_flags, BlockFlags::Write)) {
FD_SET(fds[i], &fds_write); FD_SET(fds[i], &fds_write);
marked_fd_count++; marked_fd_count++;
} }
if (params.exceptfds && ((u32)fd_entry.unblocked_flags & (u32)Thread::FileBlocker::BlockFlags::Exception)) { if (params.exceptfds && has_flag(fd_entry.unblocked_flags, BlockFlags::Exception)) {
FD_SET(fds[i], &fds_except); FD_SET(fds[i], &fds_except);
marked_fd_count++; marked_fd_count++;
} }
@ -180,14 +182,14 @@ KResultOr<int> Process::sys$poll(Userspace<const Syscall::SC_poll_params*> user_
dbgln("sys$poll: Bad fd number {}", pfd.fd); dbgln("sys$poll: Bad fd number {}", pfd.fd);
return EBADF; return EBADF;
} }
u32 block_flags = (u32)Thread::FileBlocker::BlockFlags::Exception; // always want POLLERR, POLLHUP, POLLNVAL BlockFlags block_flags = BlockFlags::Exception; // always want POLLERR, POLLHUP, POLLNVAL
if (pfd.events & POLLIN) if (pfd.events & POLLIN)
block_flags |= (u32)Thread::FileBlocker::BlockFlags::Read; block_flags |= BlockFlags::Read;
if (pfd.events & POLLOUT) if (pfd.events & POLLOUT)
block_flags |= (u32)Thread::FileBlocker::BlockFlags::Write; block_flags |= BlockFlags::Write;
if (pfd.events & POLLPRI) if (pfd.events & POLLPRI)
block_flags |= (u32)Thread::FileBlocker::BlockFlags::ReadPriority; block_flags |= BlockFlags::ReadPriority;
fds_info.append({ description.release_nonnull(), (Thread::FileBlocker::BlockFlags)block_flags }); fds_info.append({ description.release_nonnull(), block_flags });
} }
auto current_thread = Thread::current(); auto current_thread = Thread::current();
@ -213,26 +215,26 @@ KResultOr<int> Process::sys$poll(Userspace<const Syscall::SC_poll_params*> user_
auto& fds_entry = fds_info[i]; auto& fds_entry = fds_info[i];
pfd.revents = 0; pfd.revents = 0;
if (fds_entry.unblocked_flags == Thread::FileBlocker::BlockFlags::None) if (fds_entry.unblocked_flags == BlockFlags::None)
continue; continue;
if ((u32)fds_entry.unblocked_flags & (u32)Thread::FileBlocker::BlockFlags::Exception) { if (has_flag(fds_entry.unblocked_flags, BlockFlags::Exception)) {
if ((u32)fds_entry.unblocked_flags & (u32)Thread::FileBlocker::BlockFlags::ReadHangUp) if (has_flag(fds_entry.unblocked_flags, BlockFlags::ReadHangUp))
pfd.revents |= POLLRDHUP; pfd.revents |= POLLRDHUP;
if ((u32)fds_entry.unblocked_flags & (u32)Thread::FileBlocker::BlockFlags::WriteError) if (has_flag(fds_entry.unblocked_flags, BlockFlags::WriteError))
pfd.revents |= POLLERR; pfd.revents |= POLLERR;
if ((u32)fds_entry.unblocked_flags & (u32)Thread::FileBlocker::BlockFlags::WriteHangUp) if (has_flag(fds_entry.unblocked_flags, BlockFlags::WriteHangUp))
pfd.revents |= POLLNVAL; pfd.revents |= POLLNVAL;
} else { } else {
if ((u32)fds_entry.unblocked_flags & (u32)Thread::FileBlocker::BlockFlags::Read) { if (has_flag(fds_entry.unblocked_flags, BlockFlags::Read)) {
VERIFY(pfd.events & POLLIN); VERIFY(pfd.events & POLLIN);
pfd.revents |= POLLIN; pfd.revents |= POLLIN;
} }
if ((u32)fds_entry.unblocked_flags & (u32)Thread::FileBlocker::BlockFlags::ReadPriority) { if (has_flag(fds_entry.unblocked_flags, BlockFlags::ReadPriority)) {
VERIFY(pfd.events & POLLPRI); VERIFY(pfd.events & POLLPRI);
pfd.revents |= POLLPRI; pfd.revents |= POLLPRI;
} }
if ((u32)fds_entry.unblocked_flags & (u32)Thread::FileBlocker::BlockFlags::Write) { if (has_flag(fds_entry.unblocked_flags, BlockFlags::Write)) {
VERIFY(pfd.events & POLLOUT); VERIFY(pfd.events & POLLOUT);
pfd.revents |= POLLOUT; pfd.revents |= POLLOUT;
} }

View file

@ -26,6 +26,7 @@
#pragma once #pragma once
#include <AK/EnumBits.h>
#include <AK/Function.h> #include <AK/Function.h>
#include <AK/HashMap.h> #include <AK/HashMap.h>
#include <AK/IntrusiveList.h> #include <AK/IntrusiveList.h>
@ -1267,6 +1268,8 @@ private:
void drop_thread_count(bool); void drop_thread_count(bool);
}; };
AK_ENUM_BITWISE_OPERATORS(Thread::FileBlocker::BlockFlags);
template<typename Callback> template<typename Callback>
inline IterationDecision Thread::for_each(Callback callback) inline IterationDecision Thread::for_each(Callback callback)
{ {

View file

@ -265,17 +265,17 @@ const FileDescription& Thread::FileDescriptionBlocker::blocked_description() con
} }
Thread::AcceptBlocker::AcceptBlocker(FileDescription& description, BlockFlags& unblocked_flags) Thread::AcceptBlocker::AcceptBlocker(FileDescription& description, BlockFlags& unblocked_flags)
: FileDescriptionBlocker(description, (BlockFlags)((u32)BlockFlags::Accept | (u32)BlockFlags::Exception), unblocked_flags) : FileDescriptionBlocker(description, BlockFlags::Accept | BlockFlags::Exception, unblocked_flags)
{ {
} }
Thread::ConnectBlocker::ConnectBlocker(FileDescription& description, BlockFlags& unblocked_flags) Thread::ConnectBlocker::ConnectBlocker(FileDescription& description, BlockFlags& unblocked_flags)
: FileDescriptionBlocker(description, (BlockFlags)((u32)BlockFlags::Connect | (u32)BlockFlags::Exception), unblocked_flags) : FileDescriptionBlocker(description, BlockFlags::Connect | BlockFlags::Exception, unblocked_flags)
{ {
} }
Thread::WriteBlocker::WriteBlocker(FileDescription& description, BlockFlags& unblocked_flags) Thread::WriteBlocker::WriteBlocker(FileDescription& description, BlockFlags& unblocked_flags)
: FileDescriptionBlocker(description, (BlockFlags)((u32)BlockFlags::Write | (u32)BlockFlags::Exception), unblocked_flags) : FileDescriptionBlocker(description, BlockFlags::Write | BlockFlags::Exception, unblocked_flags)
{ {
} }
@ -295,7 +295,7 @@ auto Thread::WriteBlocker::override_timeout(const BlockTimeout& timeout) -> cons
} }
Thread::ReadBlocker::ReadBlocker(FileDescription& description, BlockFlags& unblocked_flags) Thread::ReadBlocker::ReadBlocker(FileDescription& description, BlockFlags& unblocked_flags)
: FileDescriptionBlocker(description, (BlockFlags)((u32)BlockFlags::Read | (u32)BlockFlags::Exception), unblocked_flags) : FileDescriptionBlocker(description, BlockFlags::Read | BlockFlags::Exception, unblocked_flags)
{ {
} }