2 * Copyright 2014, Paweł Dziepak, pdziepak@quarnos.org.
3 * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
4 * Distributed under the terms of the MIT License.
11 #include <thread_types.h>
12 #include <util/AutoLock.h>
15 // #pragma mark - UserEvent
18 UserEvent::~UserEvent()
23 // #pragma mark - SignalEvent
26 struct SignalEvent::EventSignal
: Signal
{
27 EventSignal(uint32 number
, int32 signalCode
, int32 errorCode
,
30 Signal(number
, signalCode
, errorCode
, sendingProcess
),
37 return atomic_get_and_set(&fInUse
, 1) != 0;
43 atomic_set(&fInUse
, 0);
46 virtual void Handled()
58 SignalEvent::SignalEvent(EventSignal
* signal
)
66 SignalEvent::~SignalEvent()
68 fSignal
->ReleaseReference();
73 SignalEvent::SetUserValue(union sigval userValue
)
75 fSignal
->SetUserValue(userValue
);
82 bool wasPending
= atomic_get_and_set(&fPendingDPC
, 1) != 0;
86 if (fSignal
->MarkUsed()) {
87 atomic_set(&fPendingDPC
, 0);
92 DPCQueue::DefaultQueue(B_NORMAL_PRIORITY
)->Add(this);
98 // #pragma mark - TeamSignalEvent
101 TeamSignalEvent::TeamSignalEvent(Team
* team
, EventSignal
* signal
)
109 /*static*/ TeamSignalEvent
*
110 TeamSignalEvent::Create(Team
* team
, uint32 signalNumber
, int32 signalCode
,
114 EventSignal
* signal
= new(std::nothrow
) EventSignal(signalNumber
,
115 signalCode
, errorCode
, team
->id
);
120 TeamSignalEvent
* event
= new TeamSignalEvent(team
, signal
);
131 TeamSignalEvent::Fire()
133 // We need a reference to the team to guarantee that it is still there when
134 // the DPC actually runs.
135 fTeam
->AcquireReference();
136 status_t result
= SignalEvent::Fire();
138 fTeam
->ReleaseReference();
145 TeamSignalEvent::DoDPC(DPCQueue
* queue
)
147 fSignal
->AcquireReference();
148 // one reference is transferred to send_signal_to_team_locked
150 InterruptsSpinLocker
locker(fTeam
->signal_lock
);
151 status_t error
= send_signal_to_team_locked(fTeam
, fSignal
->Number(),
152 fSignal
, B_DO_NOT_RESCHEDULE
);
154 fTeam
->ReleaseReference();
156 // There are situations (for certain signals), in which
157 // send_signal_to_team_locked() succeeds without queuing the signal.
158 if (error
!= B_OK
|| !fSignal
->IsPending())
159 fSignal
->SetUnused();
161 // We're no longer queued in the DPC queue, so we can be reused.
162 atomic_set(&fPendingDPC
, 0);
168 // #pragma mark - ThreadSignalEvent
171 ThreadSignalEvent::ThreadSignalEvent(Thread
* thread
, EventSignal
* signal
)
179 /*static*/ ThreadSignalEvent
*
180 ThreadSignalEvent::Create(Thread
* thread
, uint32 signalNumber
, int32 signalCode
,
181 int32 errorCode
, pid_t sendingTeam
)
184 EventSignal
* signal
= new(std::nothrow
) EventSignal(signalNumber
,
185 signalCode
, errorCode
, sendingTeam
);
190 ThreadSignalEvent
* event
= new ThreadSignalEvent(thread
, signal
);
201 ThreadSignalEvent::Fire()
203 // We need a reference to the thread to guarantee that it is still there
204 // when the DPC actually runs.
205 fThread
->AcquireReference();
206 status_t result
= SignalEvent::Fire();
208 fThread
->ReleaseReference();
215 ThreadSignalEvent::DoDPC(DPCQueue
* queue
)
217 fSignal
->AcquireReference();
218 // one reference is transferred to send_signal_to_team_locked
219 InterruptsReadSpinLocker
teamLocker(fThread
->team_lock
);
220 SpinLocker
locker(fThread
->team
->signal_lock
);
221 status_t error
= send_signal_to_thread_locked(fThread
, fSignal
->Number(),
222 fSignal
, B_DO_NOT_RESCHEDULE
);
225 fThread
->ReleaseReference();
227 // There are situations (for certain signals), in which
228 // send_signal_to_team_locked() succeeds without queuing the signal.
229 if (error
!= B_OK
|| !fSignal
->IsPending())
230 fSignal
->SetUnused();
232 // We're no longer queued in the DPC queue, so we can be reused.
233 atomic_set(&fPendingDPC
, 0);
239 // #pragma mark - UserEvent
242 CreateThreadEvent::CreateThreadEvent(const ThreadCreationAttributes
& attributes
)
244 fCreationAttributes(attributes
),
247 // attributes.name is a pointer to a temporary buffer. Copy the name into
248 // our own buffer and replace the name pointer.
249 strlcpy(fThreadName
, attributes
.name
, sizeof(fThreadName
));
250 fCreationAttributes
.name
= fThreadName
;
254 /*static*/ CreateThreadEvent
*
255 CreateThreadEvent::Create(const ThreadCreationAttributes
& attributes
)
257 return new(std::nothrow
) CreateThreadEvent(attributes
);
262 CreateThreadEvent::Fire()
264 bool wasPending
= atomic_get_and_set(&fPendingDPC
, 1) != 0;
269 DPCQueue::DefaultQueue(B_NORMAL_PRIORITY
)->Add(this);
276 CreateThreadEvent::DoDPC(DPCQueue
* queue
)
278 // We're no longer queued in the DPC queue, so we can be reused.
279 atomic_set(&fPendingDPC
, 0);
282 thread_id threadID
= thread_create_thread(fCreationAttributes
, false);
284 resume_thread(threadID
);