1/* 2 * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2003-2008, Axel Dörfler, axeld@pinc-software.de. 4 * All rights reserved. 5 * Distributed under the terms of the MIT License. 6 */ 7#ifndef _KERNEL_SIGNAL_H 8#define _KERNEL_SIGNAL_H 9 10 11#include <signal.h> 12 13#include <KernelExport.h> 14 15#include <signal_defs.h> 16 17#include <heap.h> 18#include <util/DoublyLinkedList.h> 19#include <util/KernelReferenceable.h> 20 21 22namespace BKernel { 23 struct ProcessGroup; 24 struct Team; 25 struct Thread; 26} 27 28using BKernel::ProcessGroup; 29using BKernel::Team; 30using BKernel::Thread; 31 32 33#define KILL_SIGNALS \ 34 (((sigset_t)1 << (SIGKILL - 1)) | ((sigset_t)1 << (SIGKILLTHR - 1))) 35 36#define SYSCALL_RESTART_PARAMETER_SIZE 32 37 38// kernel-internal signals 39#define SIGNAL_CANCEL_THREAD 63 40 // Cancel a thread. Non-blockable. 41#define SIGNAL_CONTINUE_THREAD 64 42 // Continue a thread. Used by resume_thread(). Non-blockable, prevents 43 // syscall restart. 44 45 46struct signal_frame_data { 47 siginfo_t info; 48 ucontext_t context; 49 void* user_data; 50 void* handler; 51 bool siginfo_handler; 52 int32 thread_flags; 53 uint64 syscall_restart_return_value; 54 uint8 syscall_restart_parameters[SYSCALL_RESTART_PARAMETER_SIZE]; 55}; 56 57 58namespace BKernel { 59 60 61struct QueuedSignalsCounter : BReferenceable { 62 QueuedSignalsCounter(int32 limit); 63 64 bool Increment(); 65 void Decrement() { ReleaseReference(); } 66 67private: 68 int32 fLimit; 69}; 70 71 72struct Signal : KernelReferenceable, DoublyLinkedListLinkImpl<Signal> { 73public: 74 Signal(); 75 // cheap no-init constructor 76 Signal(const Signal& other); 77 Signal(uint32 number, int32 signalCode, 78 int32 errorCode, pid_t sendingProcess); 79 virtual ~Signal(); 80 81 static status_t CreateQueuable(const Signal& signal, 82 bool queuingRequired, 83 Signal*& _signalToQueue); 84 85 void SetTo(uint32 number); 86 87 uint32 Number() const { return fNumber; } 88 void SetNumber(uint32 number) 89 { fNumber = number; } 90 91 int32 Priority() const; 92 93 int32 SignalCode() const 94 { return fSignalCode; } 95 int32 ErrorCode() const 96 { return fErrorCode; } 97 pid_t SendingProcess() const 98 { return fSendingProcess; } 99 100 uid_t SendingUser() const 101 { return fSendingUser; } 102 void SetSendingUser(uid_t user) 103 { fSendingUser = user; } 104 105 int32 Status() const 106 { return fStatus; } 107 void SetStatus(int32 status) 108 { fStatus = status; } 109 110 int32 PollBand() const 111 { return fPollBand; } 112 void SetPollBand(int32 pollBand) 113 { fPollBand = pollBand; } 114 115 void* Address() const 116 { return fAddress; } 117 void SetAddress(void* address) 118 { fAddress = address; } 119 120 union sigval UserValue() const 121 { return fUserValue; } 122 void SetUserValue(union sigval userValue) 123 { fUserValue = userValue; } 124 125 bool IsPending() const 126 { return fPending; } 127 void SetPending(bool pending) 128 { fPending = pending; } 129 130 virtual void Handled(); 131 132protected: 133 virtual void LastReferenceReleased(); 134 135private: 136 QueuedSignalsCounter* fCounter; 137 uint32 fNumber; 138 int32 fSignalCode; 139 int32 fErrorCode; // error code associated with the 140 // signal 141 pid_t fSendingProcess; 142 uid_t fSendingUser; 143 int32 fStatus; // exit value 144 int32 fPollBand; // for SIGPOLL 145 void* fAddress; 146 union sigval fUserValue; 147 bool fPending; 148}; 149 150 151struct PendingSignals { 152 PendingSignals(); 153 ~PendingSignals(); 154 155 sigset_t AllSignals() const 156 { return fQueuedSignalsMask 157 | fUnqueuedSignalsMask; } 158 159 int32 HighestSignalPriority(sigset_t nonBlocked) 160 const; 161 162 void Clear(); 163 void AddSignal(int32 signal) 164 { fUnqueuedSignalsMask 165 |= SIGNAL_TO_MASK(signal); } 166 void AddSignal(Signal* signal); 167 void RemoveSignal(int32 signal) 168 { RemoveSignals(SIGNAL_TO_MASK(signal)); } 169 void RemoveSignal(Signal* signal); 170 void RemoveSignals(sigset_t mask); 171 172 Signal* DequeueSignal(sigset_t nonBlocked, 173 Signal& buffer); 174 175private: 176 typedef DoublyLinkedList<Signal> SignalList; 177 178private: 179 int32 _GetHighestPrioritySignal(sigset_t nonBlocked, 180 Signal*& _queuedSignal, 181 int32& _unqueuedSignal) const; 182 void _UpdateQueuedSignalMask(); 183 184private: 185 sigset_t fQueuedSignalsMask; 186 sigset_t fUnqueuedSignalsMask; 187 SignalList fQueuedSignals; 188}; 189 190 191} // namespace BKernel 192 193 194using BKernel::PendingSignals; 195using BKernel::QueuedSignalsCounter; 196using BKernel::Signal; 197 198 199#ifdef __cplusplus 200extern "C" { 201#endif 202 203void handle_signals(Thread* thread); 204bool is_team_signal_blocked(Team* team, int signal); 205void signal_get_user_stack(addr_t address, stack_t* stack); 206 207status_t send_signal_to_thread_locked(Thread* thread, uint32 signalNumber, 208 Signal* signal, uint32 flags); 209status_t send_signal_to_thread(Thread* thread, const Signal& signal, 210 uint32 flags); 211status_t send_signal_to_thread_id(thread_id threadID, const Signal& signal, 212 uint32 flags); 213 214status_t send_signal_to_team_locked(Team* team, uint32 signalNumber, 215 Signal* signal, uint32 flags); 216status_t send_signal_to_team(Team* team, const Signal& signal, uint32 flags); 217status_t send_signal_to_team_id(team_id teamID, const Signal& signal, 218 uint32 flags); 219 220status_t send_signal_to_process_group_locked(ProcessGroup* group, 221 const Signal& signal, uint32 flags); 222status_t send_signal_to_process_group(pid_t groupID, const Signal& signal, 223 uint32 flags); 224 225status_t _user_send_signal(int32 id, uint32 signal, 226 const union sigval* userValue, uint32 flags); 227status_t _user_set_signal_mask(int how, const sigset_t *set, sigset_t *oldSet); 228status_t _user_sigaction(int sig, const struct sigaction *newAction, 229 struct sigaction *oldAction); 230bigtime_t _user_set_alarm(bigtime_t time, uint32 mode); 231status_t _user_sigwait(const sigset_t *set, siginfo_t *info, uint32 flags, 232 bigtime_t timeout); 233status_t _user_sigsuspend(const sigset_t *mask); 234status_t _user_sigpending(sigset_t *set); 235status_t _user_set_signal_stack(const stack_t *newUserStack, 236 stack_t *oldUserStack); 237int64 _user_restore_signal_frame(struct signal_frame_data* signalFrameData); 238 239#ifdef __cplusplus 240} 241#endif 242 243#endif /* _KERNEL_SIGNAL_H */ 244