xref: /haiku/headers/private/kernel/ksignal.h (revision 0d452c8f34013b611a54c746a71c05e28796eae2)
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