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