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_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 46 struct 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 58 namespace BKernel { 59 60 61 struct QueuedSignalsCounter : BReferenceable { 62 QueuedSignalsCounter(int32 limit); 63 64 bool Increment(); 65 void Decrement() { ReleaseReference(); } 66 67 private: 68 int32 fLimit; 69 }; 70 71 72 struct Signal : KernelReferenceable, DoublyLinkedListLinkImpl<Signal> { 73 public: 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 132 protected: 133 virtual void LastReferenceReleased(); 134 135 private: 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 151 struct 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 175 private: 176 typedef DoublyLinkedList<Signal> SignalList; 177 178 private: 179 int32 _GetHighestPrioritySignal(sigset_t nonBlocked, 180 Signal*& _queuedSignal, 181 int32& _unqueuedSignal) const; 182 void _UpdateQueuedSignalMask(); 183 184 private: 185 sigset_t fQueuedSignalsMask; 186 sigset_t fUnqueuedSignalsMask; 187 SignalList fQueuedSignals; 188 }; 189 190 191 } // namespace BKernel 192 193 194 using BKernel::PendingSignals; 195 using BKernel::QueuedSignalsCounter; 196 using BKernel::Signal; 197 198 199 #ifdef __cplusplus 200 extern "C" { 201 #endif 202 203 void handle_signals(Thread* thread); 204 bool is_team_signal_blocked(Team* team, int signal); 205 void signal_get_user_stack(addr_t address, stack_t* stack); 206 207 status_t send_signal_to_thread_locked(Thread* thread, uint32 signalNumber, 208 Signal* signal, uint32 flags); 209 status_t send_signal_to_thread(Thread* thread, const Signal& signal, 210 uint32 flags); 211 status_t send_signal_to_thread_id(thread_id threadID, const Signal& signal, 212 uint32 flags); 213 214 status_t send_signal_to_team_locked(Team* team, uint32 signalNumber, 215 Signal* signal, uint32 flags); 216 status_t send_signal_to_team(Team* team, const Signal& signal, uint32 flags); 217 status_t send_signal_to_team_id(team_id teamID, const Signal& signal, 218 uint32 flags); 219 220 status_t send_signal_to_process_group_locked(ProcessGroup* group, 221 const Signal& signal, uint32 flags); 222 status_t send_signal_to_process_group(pid_t groupID, const Signal& signal, 223 uint32 flags); 224 225 status_t _user_send_signal(int32 id, uint32 signal, 226 const union sigval* userValue, uint32 flags); 227 status_t _user_set_signal_mask(int how, const sigset_t *set, sigset_t *oldSet); 228 status_t _user_sigaction(int sig, const struct sigaction *newAction, 229 struct sigaction *oldAction); 230 bigtime_t _user_set_alarm(bigtime_t time, uint32 mode); 231 status_t _user_sigwait(const sigset_t *set, siginfo_t *info, uint32 flags, 232 bigtime_t timeout); 233 status_t _user_sigsuspend(const sigset_t *mask); 234 status_t _user_sigpending(sigset_t *set); 235 status_t _user_set_signal_stack(const stack_t *newUserStack, 236 stack_t *oldUserStack); 237 int64 _user_restore_signal_frame(struct signal_frame_data* signalFrameData); 238 239 #ifdef __cplusplus 240 } 241 #endif 242 243 #endif /* _KERNEL_SIGNAL_H */ 244