haiku/headers/private/kernel/ksignal.h
Ingo Weinhold 7a187cd629 _user_debug_thread(): Use new signal SIGNAL_DEBUG_THREAD
This resolves a TODO: We used thread_interrupt() to wake up the thread
from an interruptable wait. However, if the thread was already in the
kernel and about to start waiting, that would have no effect and the
thread would wait anyway. Now there's the new non-blockable signal
SIGNAL_DEBUG_THREAD, which is sent to the thread instead, making sure
that thread doesn't start waiting.
2016-04-24 11:54:17 +02:00

249 lines
6.4 KiB
C++

/*
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2003-2008, Axel Dörfler, axeld@pinc-software.de.
* All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _KERNEL_SIGNAL_H
#define _KERNEL_SIGNAL_H
#include <signal.h>
#include <KernelExport.h>
#include <signal_defs.h>
#include <heap.h>
#include <util/DoublyLinkedList.h>
#include <util/KernelReferenceable.h>
namespace BKernel {
struct ProcessGroup;
struct Team;
struct Thread;
}
using BKernel::ProcessGroup;
using BKernel::Team;
using BKernel::Thread;
#define KILL_SIGNALS \
(((sigset_t)1 << (SIGKILL - 1)) | ((sigset_t)1 << (SIGKILLTHR - 1)))
#define SYSCALL_RESTART_PARAMETER_SIZE 32
// kernel-internal signals
#define SIGNAL_DEBUG_THREAD 62
// Debug a thread. Used together with the B_THREAD_DEBUG_STOP thread debug
// flag. Continues the thread, if suspended, but has no effect otherwise.
// Non-blockable.
#define SIGNAL_CANCEL_THREAD 63
// Cancel a thread. Non-blockable.
#define SIGNAL_CONTINUE_THREAD 64
// Continue a thread. Used by resume_thread(). Non-blockable, prevents
// syscall restart.
struct signal_frame_data {
siginfo_t info;
ucontext_t context;
void* user_data;
void* handler;
bool siginfo_handler;
int32 thread_flags;
uint64 syscall_restart_return_value;
uint8 syscall_restart_parameters[SYSCALL_RESTART_PARAMETER_SIZE];
void* commpage_address;
};
namespace BKernel {
struct QueuedSignalsCounter : BReferenceable {
QueuedSignalsCounter(int32 limit);
bool Increment();
void Decrement() { ReleaseReference(); }
private:
int32 fLimit;
};
struct Signal : KernelReferenceable, DoublyLinkedListLinkImpl<Signal> {
public:
Signal();
// cheap no-init constructor
Signal(const Signal& other);
Signal(uint32 number, int32 signalCode,
int32 errorCode, pid_t sendingProcess);
virtual ~Signal();
static status_t CreateQueuable(const Signal& signal,
bool queuingRequired,
Signal*& _signalToQueue);
void SetTo(uint32 number);
uint32 Number() const { return fNumber; }
void SetNumber(uint32 number)
{ fNumber = number; }
int32 Priority() const;
int32 SignalCode() const
{ return fSignalCode; }
int32 ErrorCode() const
{ return fErrorCode; }
pid_t SendingProcess() const
{ return fSendingProcess; }
uid_t SendingUser() const
{ return fSendingUser; }
void SetSendingUser(uid_t user)
{ fSendingUser = user; }
int32 Status() const
{ return fStatus; }
void SetStatus(int32 status)
{ fStatus = status; }
int32 PollBand() const
{ return fPollBand; }
void SetPollBand(int32 pollBand)
{ fPollBand = pollBand; }
void* Address() const
{ return fAddress; }
void SetAddress(void* address)
{ fAddress = address; }
union sigval UserValue() const
{ return fUserValue; }
void SetUserValue(union sigval userValue)
{ fUserValue = userValue; }
bool IsPending() const
{ return fPending; }
void SetPending(bool pending)
{ fPending = pending; }
virtual void Handled();
protected:
virtual void LastReferenceReleased();
private:
QueuedSignalsCounter* fCounter;
uint32 fNumber;
int32 fSignalCode;
int32 fErrorCode; // error code associated with the
// signal
pid_t fSendingProcess;
uid_t fSendingUser;
int32 fStatus; // exit value
int32 fPollBand; // for SIGPOLL
void* fAddress;
union sigval fUserValue;
bool fPending;
};
struct PendingSignals {
PendingSignals();
~PendingSignals();
sigset_t AllSignals() const
{ return fQueuedSignalsMask
| fUnqueuedSignalsMask; }
int32 HighestSignalPriority(sigset_t nonBlocked)
const;
void Clear();
void AddSignal(int32 signal)
{ fUnqueuedSignalsMask
|= SIGNAL_TO_MASK(signal); }
void AddSignal(Signal* signal);
void RemoveSignal(int32 signal)
{ RemoveSignals(SIGNAL_TO_MASK(signal)); }
void RemoveSignal(Signal* signal);
void RemoveSignals(sigset_t mask);
Signal* DequeueSignal(sigset_t nonBlocked,
Signal& buffer);
private:
typedef DoublyLinkedList<Signal> SignalList;
private:
int32 _GetHighestPrioritySignal(sigset_t nonBlocked,
Signal*& _queuedSignal,
int32& _unqueuedSignal) const;
void _UpdateQueuedSignalMask();
private:
sigset_t fQueuedSignalsMask;
sigset_t fUnqueuedSignalsMask;
SignalList fQueuedSignals;
};
} // namespace BKernel
using BKernel::PendingSignals;
using BKernel::QueuedSignalsCounter;
using BKernel::Signal;
#ifdef __cplusplus
extern "C" {
#endif
void handle_signals(Thread* thread);
bool is_team_signal_blocked(Team* team, int signal);
void signal_get_user_stack(addr_t address, stack_t* stack);
status_t send_signal_to_thread_locked(Thread* thread, uint32 signalNumber,
Signal* signal, uint32 flags);
status_t send_signal_to_thread(Thread* thread, const Signal& signal,
uint32 flags);
status_t send_signal_to_thread_id(thread_id threadID, const Signal& signal,
uint32 flags);
status_t send_signal_to_team_locked(Team* team, uint32 signalNumber,
Signal* signal, uint32 flags);
status_t send_signal_to_team(Team* team, const Signal& signal, uint32 flags);
status_t send_signal_to_team_id(team_id teamID, const Signal& signal,
uint32 flags);
status_t send_signal_to_process_group_locked(ProcessGroup* group,
const Signal& signal, uint32 flags);
status_t send_signal_to_process_group(pid_t groupID, const Signal& signal,
uint32 flags);
status_t _user_send_signal(int32 id, uint32 signal,
const union sigval* userValue, uint32 flags);
status_t _user_set_signal_mask(int how, const sigset_t *set, sigset_t *oldSet);
status_t _user_sigaction(int sig, const struct sigaction *newAction,
struct sigaction *oldAction);
bigtime_t _user_set_alarm(bigtime_t time, uint32 mode);
status_t _user_sigwait(const sigset_t *set, siginfo_t *info, uint32 flags,
bigtime_t timeout);
status_t _user_sigsuspend(const sigset_t *mask);
status_t _user_sigpending(sigset_t *set);
status_t _user_set_signal_stack(const stack_t *newUserStack,
stack_t *oldUserStack);
int64 _user_restore_signal_frame(struct signal_frame_data* signalFrameData);
#ifdef __cplusplus
}
#endif
#endif /* _KERNEL_SIGNAL_H */