ReactOS 0.4.16-dev-197-g92996da
fxsystemworkitem.cpp
Go to the documentation of this file.
1/*++
2
3Copyright (c) Microsoft Corporation
4
5Module Name:
6
7 FxSystemWorkItem.hpp
8
9Abstract:
10
11 This module implements a frameworks managed WORKITEM that
12 can synchrononize with driver frameworks object locks.
13
14Author:
15
16
17
18Environment:
19
20 Both kernel and user mode
21
22Revision History:
23
24
25--*/
26
27#include "coreprivshared.hpp"
28
29#include "fxsystemworkitem.hpp"
30
31// Tracing support
32extern "C" {
33// #include "FxSystemWorkItem.tmh"
34}
35
36//
37// Public constructors
38//
42 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
43 __in PVOID WdmObject,
45 )
46{
49
50 wi = new(FxDriverGlobals) FxSystemWorkItem(FxDriverGlobals);
51 if (wi == NULL) {
53 }
54
55 status = wi->Initialize(WdmObject);
56 if (!NT_SUCCESS(status)) {
57 wi->Release();
58 return status;
59 }
60
61 *pObject = wi;
62
63 return status;
64}
65
67 __in PFX_DRIVER_GLOBALS FxDriverGlobals
68 ) :
69 FxNonPagedObject(FX_TYPE_SYSTEMWORKITEM, 0, FxDriverGlobals),
70 m_WorkItemCompleted(NotificationEvent, TRUE),
71 m_RemoveEvent(SynchronizationEvent, FALSE)
72{
79}
80
82{
83 PFX_DRIVER_GLOBALS FxDriverGlobals = GetDriverGlobals();
84
85 //
86 // If this hits, it's because someone destroyed the WORKITEM by
87 // removing too many references by mistake without calling WdfObjectDelete
88 //
91 "WorkItem destroyed without calling "
92 "FxSystemWorkItem::Delete, or by Framework "
93 "processing DeviceRemove. "
94 "Possible reference count problem?");
95 FxVerifierDbgBreakPoint(FxDriverGlobals);
96 }
97
98 // Free the workitem
99 if( m_WorkItem.GetWorkItem() != NULL ) {
101 }
102
105
106 return;
107}
108
112 __in PVOID WdmObject
113 )
114{
115 PFX_DRIVER_GLOBALS FxDriverGlobals = GetDriverGlobals();
117
118 //
119 // Mark this object as passive level to ensure that Dispose() is passive
120 //
122
124
125#if (FX_CORE_MODE == FX_CORE_USER_MODE)
127 if (!NT_SUCCESS(status)) {
129 "Could not initialize m_WorkItemCompleted event "
130 "status %!status!", status);
131 return status;
132 }
133
135 if(!NT_SUCCESS(status)) {
137 "Could not initialize m_RemoveEvent event "
138 "status %!status!", status);
139 return status;
140 }
141#endif
142
143 //
144 // Allocate the PIO_WORKITEM we will re-use
145 //
147 if(!NT_SUCCESS(status)) {
149 "Could not allocate IoWorkItem, insufficient resources");
150 return status;
151 }
152
154
155 return STATUS_SUCCESS;
156}
157
162 __in BOOLEAN AssertIfAlreadyQueued
163 )
164/*++
165
166Routine Description:
167
168 Called to queue the workitem. This function, under verifier, will
169 throw an assert if AssertIfAlreadyQueued parameter is set.
170
171Arguments:
172 Func - Callback function.
173
174 Parameter - Callback's context.
175
176 AssertIfAlreadyQueued - is used to make sure that caller doesn't
177 miss any workitem callback.
178
179Return Value:
180
181 FALSE
182 - if the previously queued workitem hasn't run to completion.
183 - if the object is running down.
184
185 TRUE - workitem is queued.
186--*/
187{
189 KIRQL irql;
190
192
193 Lock(&irql);
194
195 if( m_Enqueued ) {
196 if (AssertIfAlreadyQueued) {
198 "WorkItem 0x%p already enqueued IoWorkItem 0x%p",
199 this, m_WorkItem.GetWorkItem());
201 }
202
203 Unlock(irql);
204 return FALSE;
205 }
206
207 //
208 // If running down, fail
209 //
210 if( m_RunningDown ) {
212 "WorkItem 0x%p is already deleted", this);
214 Unlock(irql);
215 return FALSE;
216 }
217
219
222
224
225 // Add a reference while outstanding
227
228 Unlock(irql);
229
231
232 return TRUE;
233}
234
235VOID
237{
239 PVOID CallbackArg;
240 KIRQL irql;
241
243
244 Lock(&irql);
245
247
249 CallbackArg = m_CallbackArg;
250
252
253 //
254 // We should only see this count rise to a small number (like 10 or so).
255 //
257
259
260 Unlock(irql);
261
262 Callback(CallbackArg);
263
264 Lock(&irql);
265
267
268 //
269 // The driver could re-enqueue a new callback from within the
270 // callback handler, which could make m_Enqueued no longer false.
271 //
272 // We only set the event specifying the callback as completed when
273 // we are ensured that no more workitems are enqueued.
274 //
277 }
278
279 Unlock(irql);
280
281 return;
282}
283
284VOID
288 )
289
290/*++
291
292Routine Description:
293
294 This is the static routine called by the kernel's PIO_WORKITEM handler.
295
296 A reference count was taken by Enqueue, which this routine releases
297 on return.
298
299Arguments:
300
301Return Value:
302
303 Nothing.
304
305--*/
306
307{
309
311
312 pWorkItem->WorkItemHandler();
313
314 // Release the reference taken when enqueued
315 pWorkItem->DecrementWorkItemQueued();
316
317 return;
318}
319
320//
321// Invoked when DeleteObject is called on the object, or its parent.
322//
325 )
326{
327 KIRQL irql;
328
330
331 Lock(&irql);
332
334
336
337 Unlock(irql);
338
340
341 return TRUE;
342}
343
344//
345// Wait until any outstanding WorkItem has completed safely
346//
347// Can only be called after Delete
348//
349// The caller must call AddRef() and Release() around this call
350// to ensure the FxSystemWorkItem remains valid while it is doing the
351// wait.
352//
353VOID
355 )
356{
358
359 //
360 // Wait for current workitem to complete processing
361 //
363
366
367 //
368 // This assert is not under a lock, but the code in WorkItemHandler()
369 // clears m_Enqueued under the lock, thus releasing it with a memory
370 // barrier. Since we have ensured above that no one can re-queue a request
371 // due to m_RunningDown, we should not hit this assert unless there
372 // is a code problem with wakeup occuring while an outstanding
373 // workitem is running.
374 //
376
377 return;
378}
379
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
__inline PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxobject.hpp:734
__drv_restoresIRQL KIRQL __in BOOLEAN Unlock
Definition: fxobject.hpp:1474
virtual ULONG Release(__in_opt PVOID Tag=NULL, __in LONG Line=0, __in_opt PSTR File=NULL)
Definition: fxobject.hpp:853
VOID MarkPassiveCallbacks(__in FxObjectLockState State=ObjectLock)
Definition: fxobject.hpp:972
VOID MarkDisposeOverride(__in FxObjectLockState State=ObjectLock)
Definition: fxobject.hpp:1101
FxCREvent m_WorkItemCompleted
static _Must_inspect_result_ NTSTATUS _Create(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in PVOID WdmObject, __out FxSystemWorkItem **pObject)
FxSystemWorkItem(__in PFX_DRIVER_GLOBALS FxDriverGlobals)
__inline VOID ReleaseWorkItemQueuedCountAndWait()
__inline VOID IncrementWorkItemQueued()
PFN_WDF_SYSTEMWORKITEM m_Callback
virtual BOOLEAN Dispose(VOID)
_Must_inspect_result_ NTSTATUS Initialize(__in PVOID WdmObject)
__inline VOID DecrementWorkItemQueued()
BOOLEAN EnqueueWorker(__in PFN_WDF_SYSTEMWORKITEM Func, __in PVOID Parameter, __in BOOLEAN AssertIfAlreadyQueued)
static MX_WORKITEM_ROUTINE _WorkItemThunk
virtual ~FxSystemWorkItem()
__inline MdWorkItem GetWorkItem()
Definition: mxworkitemkm.h:73
__inline VOID Enqueue(__in PMX_WORKITEM_ROUTINE Callback, __in PVOID Context)
Definition: mxworkitemkm.h:58
__inline VOID Free()
Definition: mxworkitemkm.h:90
_Must_inspect_result_ __inline NTSTATUS Allocate(__in MdDeviceObject DeviceObject, __in_opt PVOID ThreadPoolEnv=NULL)
Definition: mxworkitemkm.h:41
static __inline KIRQL MxGetCurrentIrql()
Definition: mxgeneralkm.h:86
#define __in
Definition: dbghelp.h:35
#define __in_opt
Definition: dbghelp.h:38
#define __out
Definition: dbghelp.h:62
#define TRACINGDEVICE
Definition: dbgtrace.h:58
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
KIRQL irql
Definition: wave.h:1
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
UCHAR KIRQL
Definition: env_spec_w32.h:591
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
PFX_DRIVER_GLOBALS pFxDriverGlobals
FX_TRACK_DRIVER(fxDriverGlobals)
FxVerifierDbgBreakPoint(pFxDriverGlobals)
@ ObjectDoNotLock
Definition: fxobject.hpp:128
FxObject * pObject
EVT_SYSTEMWORKITEM * PFN_WDF_SYSTEMWORKITEM
@ FX_TYPE_SYSTEMWORKITEM
Definition: fxtypes.h:84
Status
Definition: gdiplustypes.h:25
#define ASSERT(a)
Definition: mode.c:44
#define _Must_inspect_result_
Definition: ms_sal.h:558
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
@ NotificationEvent
@ SynchronizationEvent
#define L(x)
Definition: ntvdm.h:50
void(* Func)(int)
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
NTSTATUS EnterCRAndWaitAndLeave(VOID)
Definition: fxwaitlock.hpp:87
VOID Set(VOID)
Definition: fxwaitlock.hpp:144
VOID Clear(VOID)
Definition: fxwaitlock.hpp:152
CHECK_RETURN_IF_USER_MODE NTSTATUS Initialize(__in BOOLEAN InitialState=FALSE)
Definition: fxwaitlock.hpp:51
Definition: ps.c:97
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFINTERRUPT _In_ PFN_WDF_INTERRUPT_SYNCHRONIZE Callback
Definition: wdfinterrupt.h:458
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:127
_Inout_opt_ PVOID Parameter
Definition: rtltypes.h:336