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