diff --git a/src/system/kernel/UserEvent.cpp b/src/system/kernel/UserEvent.cpp index 7d890d9cf5..fb8c0b9725 100644 --- a/src/system/kernel/UserEvent.cpp +++ b/src/system/kernel/UserEvent.cpp @@ -31,22 +31,20 @@ struct SignalEvent::EventSignal : Signal { { } - bool IsInUse() const + bool MarkUsed() { - return fInUse; + return atomic_set(reinterpret_cast(&fInUse), true); } - void SetInUse(bool inUse) + void SetUnused() { - fInUse = inUse; + fInUse = false; } virtual void Handled() { // mark not-in-use - InterruptsSpinLocker schedulerLocker(gSchedulerLock); fInUse = false; - schedulerLocker.Unlock(); Signal::Handled(); } @@ -111,20 +109,22 @@ TeamSignalEvent::Create(Team* team, uint32 signalNumber, int32 signalCode, status_t TeamSignalEvent::Fire() { - // called with the scheduler lock held - if (fSignal->IsInUse()) + if (fSignal->MarkUsed()) return B_BUSY; fSignal->AcquireReference(); // one reference is transferred to send_signal_to_team_locked + + InterruptsSpinLocker locker(gSchedulerLock); status_t error = send_signal_to_team_locked(fTeam, fSignal->Number(), fSignal, B_DO_NOT_RESCHEDULE); if (error == B_OK) { - // Mark the signal in-use. There are situations (for certain signals), - // in which send_signal_to_team_locked() succeeds without queuing the - // signal. - fSignal->SetInUse(fSignal->IsPending()); + // There are situations (for certain signals), in which + // send_signal_to_team_locked() succeeds without queuing the signal. + if (!fSignal->IsPending()) + fSignal->SetUnused(); } + locker.Unlock(); return error; } @@ -165,20 +165,22 @@ ThreadSignalEvent::Create(Thread* thread, uint32 signalNumber, int32 signalCode, status_t ThreadSignalEvent::Fire() { - // called with the scheduler lock held - if (fSignal->IsInUse()) + if (fSignal->MarkUsed()) return B_BUSY; fSignal->AcquireReference(); // one reference is transferred to send_signal_to_team_locked + + InterruptsSpinLocker locker(gSchedulerLock); status_t error = send_signal_to_thread_locked(fThread, fSignal->Number(), fSignal, B_DO_NOT_RESCHEDULE); if (error == B_OK) { - // Mark the signal in-use. There are situations (for certain signals), - // in which send_signal_to_team_locked() succeeds without queuing the - // signal. - fSignal->SetInUse(fSignal->IsPending()); + // There are situations (for certain signals), in which + // send_signal_to_team_locked() succeeds without queuing the signal. + if (!fSignal->IsPending()) + fSignal->SetUnused(); } + locker.Unlock(); return error; } @@ -216,12 +218,11 @@ CreateThreadEvent::Create(const ThreadCreationAttributes& attributes) status_t CreateThreadEvent::Fire() { - if (fPendingDPC) + bool wasPending = atomic_set(reinterpret_cast(&fPendingDPC), true); + if (wasPending) return B_BUSY; - fPendingDPC = true; - - DPCQueue::DefaultQueue(B_NORMAL_PRIORITY)->Add(this, true); + DPCQueue::DefaultQueue(B_NORMAL_PRIORITY)->Add(this); return B_OK; } @@ -231,10 +232,7 @@ void CreateThreadEvent::DoDPC(DPCQueue* queue) { // We're no longer queued in the DPC queue, so we can be reused. - { - InterruptsSpinLocker schedulerLocker(gSchedulerLock); - fPendingDPC = false; - } + fPendingDPC = false; // create the thread thread_id threadID = thread_create_thread(fCreationAttributes, false);