1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
|
/**
* \file
* \brief SignalsReceiverControlBlock class header
*
* \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
*
* \par License
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
* distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SIGNALSRECEIVERCONTROLBLOCK_HPP_
#define INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SIGNALSRECEIVERCONTROLBLOCK_HPP_
#include "distortos/SignalSet.hpp"
#include <cstdint>
union sigval;
namespace distortos
{
class SignalAction;
class SignalInformation;
class SignalInformationQueueWrapper;
class SignalsCatcher;
namespace internal
{
class SignalInformationQueue;
class SignalsCatcherControlBlock;
class ThreadControlBlock;
/// SignalsReceiverControlBlock class is a structure required by threads for "receiving" of signals
class SignalsReceiverControlBlock
{
public:
/**
* \brief SignalsReceiverControlBlock's constructor
*
* \param [in] signalInformationQueueWrapper is a pointer to SignalInformationQueueWrapper for this receiver,
* nullptr to disable queuing of signals for this receiver
* \param [in] signalsCatcher is a pointer to SignalsCatcher for this receiver, nullptr if this receiver cannot
* catch/handle signals
*/
explicit SignalsReceiverControlBlock(SignalInformationQueueWrapper* signalInformationQueueWrapper,
SignalsCatcher* signalsCatcher);
/**
* \brief Accepts (clears) one of signals that are pending.
*
* This should be called when the signal is "accepted".
*
* \param [in] signalNumber is the signal that will be accepted, [0; 31]
*
* \return pair with return code (0 on success, error code otherwise) and SignalInformation object for accepted
* signal; error codes:
* - EAGAIN - no signal specified by \a signalNumber was pending;
* - EINVAL - \a signalNumber value is invalid;
*/
std::pair<int, SignalInformation> acceptPendingSignal(uint8_t signalNumber);
/**
* \brief Hook function executed when delivery of signals is started.
*
* Calls SignalsCatcherControlBlock::deliveryOfSignalsStartedHook().
*
* \attention This function should be called only by the function that delivers signals (<em>deliverSignals()</em>).
*
* \return 0 on success, error code otherwise:
* - ENOTSUP - catching/handling of signals is disabled for this receiver;
*/
int deliveryOfSignalsStartedHook() const;
/**
* \brief Generates signal for associated thread.
*
* Similar to pthread_kill() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_kill.html
*
* Adds the signalNumber to set of pending signals. If associated thread is currently waiting for this signal, it
* will be unblocked.
*
* \param [in] signalNumber is the signal that will be generated, [0; 31]
* \param [in] threadControlBlock is a reference to associated ThreadControlBlock
*
* \return 0 on success, error code otherwise:
* - EINVAL - \a signalNumber value is invalid;
*/
int generateSignal(uint8_t signalNumber, ThreadControlBlock& threadControlBlock);
/**
* \return set of currently pending signals
*/
SignalSet getPendingSignalSet() const;
/**
* \brief Gets SignalAction associated with given signal number.
*
* Similar to sigaction() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaction.html
*
* \param [in] signalNumber is the signal for which the association is requested, [0; 31]
*
* \return pair with return code (0 on success, error code otherwise) and SignalAction that is associated with
* \a signalNumber, default-constructed object if no association was found;
* error codes:
* - EINVAL - \a signalNumber value is invalid;
* - ENOTSUP - catching/handling of signals is disabled for this receiver;
*/
std::pair<int, SignalAction> getSignalAction(uint8_t signalNumber) const;
/**
* \brief Gets signal mask for associated thread.
*
* Similar to pthread_sigmask() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_sigmask.html#
*
* \return SignalSet with signal mask for associated thread
*/
SignalSet getSignalMask() const;
/**
* \brief Queues signal for associated thread.
*
* Similar to sigqueue() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigqueue.html
*
* Queues the signalNumber and signal value (sigval union) in associated SignalInformationQueue object. If
* associated thread is currently waiting for this signal, it will be unblocked.
*
* \param [in] signalNumber is the signal that will be queued, [0; 31]
* \param [in] value is the signal value
* \param [in] threadControlBlock is a reference to associated ThreadControlBlock
*
* \return 0 on success, error code otherwise:
* - EAGAIN - no resources are available to queue the signal, maximal number of signals is already queued in
* associated SignalInformationQueue object;
* - EINVAL - \a signalNumber value is invalid;
* - ENOTSUP - queuing of signals is disabled for this receiver;
*/
int queueSignal(uint8_t signalNumber, sigval value, ThreadControlBlock& threadControlBlock) const;
/**
* \brief Sets association for given signal number.
*
* Similar to sigaction() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaction.html
*
* \param [in] signalNumber is the signal for which the association will be set, [0; 31]
* \param [in] signalAction is a reference to SignalAction that will be associated with given signal number, object
* in internal storage is copy-constructed
*
* \return pair with return code (0 on success, error code otherwise) and SignalAction that was associated with
* \a signalNumber, default-constructed object if no association was found;
* error codes:
* - EAGAIN - no resources are available to associate \a signalNumber with \a signalAction;
* - EINVAL - \a signalNumber value is invalid;
* - ENOTSUP - catching/handling of signals is disabled for this receiver;
*/
std::pair<int, SignalAction> setSignalAction(uint8_t signalNumber, const SignalAction& signalAction);
/**
* \brief Sets signal mask for associated thread.
*
* Similar to pthread_sigmask() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_sigmask.html#
*
* \param [in] signalMask is the SignalSet with new signal mask for associated thread
* \param [in] requestDelivery selects whether delivery of signals will be requested if any pending signal is
* unblocked (true) or not (false)
*
* \return 0 on success, error code otherwise:
* - ENOTSUP - catching/handling of signals is disabled for this receiver;
*/
int setSignalMask(SignalSet signalMask, bool requestDelivery);
/**
* \param [in] signalSet is a pointer to set of signals that will be "waited for", nullptr when wait was terminated
*/
void setWaitingSignalSet(const SignalSet* const signalSet)
{
waitingSignalSet_ = signalSet;
}
private:
/**
* \brief Checks whether signal is ignored.
*
* Signal is ignored if it has no SignalAction object associated. Signal is never ignored if catching/handling of
* signals is disabled for this receiver.
*
* \param [in] signalNumber is the signal for which the check will be performed, [0; 31]
*
* \return pair with return code (0 on success, error code otherwise) and boolean telling whether the signal is
* ignored (true) or not (false);
* error codes:
* - EINVAL - \a signalNumber value is invalid;
*/
std::pair<int, bool> isSignalIgnored(uint8_t signalNumber) const;
/**
* \brief Actions executed after signal is "generated" with generateSignal() or queueSignal().
*
* If associated thread is currently waiting for the signal that was generated, it will be unblocked.
*
* \param [in] signalNumber is the signal that was generated, [0; 31]
* \param [in] threadControlBlock is a reference to associated ThreadControlBlock
*
* \return 0 on success, error code otherwise:
* - EINVAL - \a signalNumber value is invalid;
*/
int postGenerate(uint8_t signalNumber, ThreadControlBlock& threadControlBlock) const;
/// set of pending signals
SignalSet pendingSignalSet_;
/// pointer to set of "waited for" signals, nullptr if associated thread is not waiting for any signals
const SignalSet* waitingSignalSet_;
/// pointer to SignalsCatcherControlBlock for this receiver, nullptr if this receiver cannot catch/handle signals
SignalsCatcherControlBlock* signalsCatcherControlBlock_;
/// pointer to SignalInformationQueue for this receiver, nullptr if this receiver cannot queue signals
SignalInformationQueue* signalInformationQueue_;
};
} // namespace internal
} // namespace distortos
#endif // INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SIGNALSRECEIVERCONTROLBLOCK_HPP_
|