From d7e1e3e0120b00c88cae7a6828dd727062873dfe Mon Sep 17 00:00:00 2001 From: Pawel Dziepak Date: Mon, 17 Mar 2014 01:56:03 +0100 Subject: [PATCH] kernel/UserEvent: Make sure UserEvent object is valid during DPC Most of the actual UserEvent work is done in DPC so that we don't have to care about the limitations of the context in which UserEvent::Fire() is invoked. This requires appropriate management of lifetime of UserEvent instances to make sure that DoDPC() method is always called on a valid object. --- headers/private/kernel/UserEvent.h | 3 ++- src/system/kernel/UserEvent.cpp | 7 +++++++ src/system/kernel/UserTimer.cpp | 4 +++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/headers/private/kernel/UserEvent.h b/headers/private/kernel/UserEvent.h index 8e0a931afe..19a44a366a 100644 --- a/headers/private/kernel/UserEvent.h +++ b/headers/private/kernel/UserEvent.h @@ -1,4 +1,5 @@ /* + * Copyright 2014, Paweł Dziepak, pdziepak@quarnos.org. * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ @@ -21,7 +22,7 @@ struct Team; struct Thread; -struct UserEvent { +struct UserEvent : public BReferenceable { virtual ~UserEvent(); virtual status_t Fire() = 0; diff --git a/src/system/kernel/UserEvent.cpp b/src/system/kernel/UserEvent.cpp index 46acc63344..a60d230455 100644 --- a/src/system/kernel/UserEvent.cpp +++ b/src/system/kernel/UserEvent.cpp @@ -1,4 +1,5 @@ /* + * Copyright 2014, Paweł Dziepak, pdziepak@quarnos.org. * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ @@ -87,6 +88,7 @@ SignalEvent::Fire() return B_BUSY; } + AcquireReference(); DPCQueue::DefaultQueue(B_NORMAL_PRIORITY)->Add(this); return B_OK; @@ -143,6 +145,8 @@ TeamSignalEvent::DoDPC(DPCQueue* queue) // We're no longer queued in the DPC queue, so we can be reused. atomic_set(&fPendingDPC, 0); + + ReleaseReference(); } @@ -197,6 +201,8 @@ ThreadSignalEvent::DoDPC(DPCQueue* queue) // We're no longer queued in the DPC queue, so we can be reused. atomic_set(&fPendingDPC, 0); + + ReleaseReference(); } @@ -236,6 +242,7 @@ CreateThreadEvent::Fire() if (wasPending) return B_BUSY; + AcquireReference(); DPCQueue::DefaultQueue(B_NORMAL_PRIORITY)->Add(this); return B_OK; diff --git a/src/system/kernel/UserTimer.cpp b/src/system/kernel/UserTimer.cpp index db816a426f..88aa78a07b 100644 --- a/src/system/kernel/UserTimer.cpp +++ b/src/system/kernel/UserTimer.cpp @@ -1,4 +1,5 @@ /* + * Copyright 2014, Paweł Dziepak, pdziepak@quarnos.org. * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ @@ -128,7 +129,8 @@ UserTimer::UserTimer() UserTimer::~UserTimer() { - delete fEvent; + if (fEvent != NULL) + fEvent->ReleaseReference(); }