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