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