libluna+kernel: Add Bitset and use it for signals
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
apio 2023-08-23 10:51:02 +02:00
parent d144a818d8
commit a35ca0b367
Signed by: apio
GPG Key ID: B8A7D06E42258954
6 changed files with 73 additions and 13 deletions

View File

@ -124,7 +124,7 @@ bool Thread::deliver_signal(int signo, Registers* current_regs)
if (push_mem_on_stack((u8*)&handler.__sa_sigreturn, sizeof(void*)).has_error()) return false;
signal_mask = handler.sa_mask;
if ((handler.sa_flags & SA_NODEFER) == 0) signal_mask |= (1 << (signo - 1));
if ((handler.sa_flags & SA_NODEFER) == 0) signal_mask.set(signo - 1, true);
rsp = regs.rsp;

View File

@ -36,7 +36,7 @@ Result<void> ConsoleDevice::handle_background_process_group(bool can_succeed, in
auto* current = Scheduler::current();
if (current->pgid == foreground_pgrp) return {};
if ((current->signal_mask & (1 << (signo - 1))) || (current->signal_handlers[signo - 1].sa_handler == SIG_IGN))
if ((current->signal_mask.get(signo - 1)) || (current->signal_handlers[signo - 1].sa_handler == SIG_IGN))
{
if (can_succeed) return {};
return err(EIO);

View File

@ -79,7 +79,8 @@ Result<u64> sys_sigprocmask(Registers*, SyscallArgs args)
if (oldset)
{
if (!MemoryManager::copy_to_user_typed(oldset, &current->signal_mask)) return err(EFAULT);
sigset_t mask = current->signal_mask.value();
if (!MemoryManager::copy_to_user_typed(oldset, &mask)) return err(EFAULT);
}
if (set)
@ -89,8 +90,8 @@ Result<u64> sys_sigprocmask(Registers*, SyscallArgs args)
switch (how)
{
case SIG_BLOCK: current->signal_mask |= kset; break;
case SIG_UNBLOCK: current->signal_mask &= ~kset; break;
case SIG_BLOCK: current->signal_mask = current->signal_mask.value() | kset; break;
case SIG_UNBLOCK: current->signal_mask = current->signal_mask.value() & ~kset; break;
case SIG_SETMASK: current->signal_mask = kset; break;
default: return err(EINVAL);
}

View File

@ -148,10 +148,10 @@ void Thread::process_pending_signals(Registers* current_regs)
for (int i = 0; i < NSIG; i++)
{
int signo = i + 1;
if (signo != SIGKILL && signo != SIGSTOP && signal_mask & (1 << i)) continue;
if (pending_signals & (1 << i))
if (signo != SIGKILL && signo != SIGSTOP && signal_mask.get(i)) continue;
if (pending_signals.get(i))
{
pending_signals &= ~(1 << i);
pending_signals.set(i, false);
kinfoln("signal: executing signal %d for thread %d", signo, id);
auto handler = signal_handlers[i];
if (signo != SIGKILL && signo != SIGSTOP && handler.sa_handler == SIG_IGN)
@ -190,11 +190,11 @@ bool Thread::will_ignore_pending_signal()
{
for (int i = 0; i < NSIG; i++)
{
if (pending_signals & (1 << i))
if (pending_signals.get(i))
{
int signo = i + 1;
if (signo == SIGKILL || signo == SIGSTOP) return false;
if (signal_mask & (1 << i)) continue;
if (signal_mask.get(i)) continue;
auto handler = signal_handlers[i];
if (handler.sa_handler == SIG_IGN) return true;
if (handler.sa_handler == SIG_DFL && default_actions[i] == DefaultSignalAction::Ignore) return true;
@ -209,7 +209,7 @@ void Thread::send_signal(int signo)
if (is_kernel) return;
check(signo > 0 && signo <= NSIG);
pending_signals |= 1 << (signo - 1);
pending_signals.set(signo - 1, true);
if (state == ThreadState::Waiting || state == ThreadState::Sleeping)
{

View File

@ -4,6 +4,7 @@
#include "fs/VFS.h"
#include "memory/AddressSpace.h"
#include <bits/signal.h>
#include <luna/Bitset.h>
#include <luna/LinkedList.h>
#include <luna/OwnedPtr.h>
#include <luna/Result.h>
@ -105,8 +106,8 @@ struct Thread : public LinkedListNode<Thread>
SharedPtr<VFS::Inode>* parent_inode = nullptr);
struct sigaction signal_handlers[NSIG];
sigset_t signal_mask { 0 };
sigset_t pending_signals { 0 };
Bitset<sigset_t> signal_mask { 0 };
Bitset<sigset_t> pending_signals { 0 };
bool interrupted { false };
bool unrestricted_task { false };

View File

@ -0,0 +1,58 @@
#pragma once
#include <luna/Check.h>
template <typename T> class Bitset
{
public:
Bitset() : m_value()
{
}
Bitset(T value) : m_value(value)
{
}
Bitset(const Bitset<T>& other) : m_value(other.m_value)
{
}
Bitset<T>& operator=(T value)
{
m_value = value;
return *this;
}
Bitset<T>& operator=(const Bitset<T>& other)
{
if (&other == this) return *this;
m_value = other.m_value;
return *this;
}
T value() const
{
return m_value;
}
void set(int index, bool b)
{
check((usize)index < (sizeof(T) * 8));
if (b) m_value |= (((T)1) << index);
else
m_value &= ~(((T)1) << index);
}
bool get(int index)
{
check((usize)index < (sizeof(T) * 8));
return m_value & (((T)1) << index);
}
void clear()
{
m_value = 0;
}
private:
T m_value;
};