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