libluna+kernel: Add Bitset and use it for signals
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
d144a818d8
commit
a35ca0b367
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -79,7 +79,8 @@ Result<u64> sys_sigprocmask(Registers*, SyscallArgs args)
|
||||
|
||||
if (oldset)
|
||||
{
|
||||
if (!MemoryManager::copy_to_user_typed(oldset, ¤t->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);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 };
|
||||
|
58
libluna/include/luna/Bitset.h
Normal file
58
libluna/include/luna/Bitset.h
Normal 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;
|
||||
};
|
Loading…
Reference in New Issue
Block a user