ReactOS  0.4.15-dev-2700-g4b4ffa9
fxdisposelist.cpp
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7  FxDisposeList.hpp
8 
9 Abstract:
10 
11  This class implements a Disposal list for deferring Dispose
12  processing from dispatch to passive level.
13 
14  It works tightly with FxObject, and is a friend class.
15 
16 Author:
17 
18 
19 
20 
21 
22 
23 Environment:
24 
25  Both kernel and user mode
26 
27 Revision History:
28 
29 
30 --*/
31 
32 #include "coreprivshared.hpp"
33 
34 #include "fxdisposelist.hpp"
35 
36 // Tracing support
37 extern "C" {
38 // #include "FxDisposeList.tmh"
39 }
40 
42  PFX_DRIVER_GLOBALS FxDriverGlobals
43  ) :
44  FxNonPagedObject(FX_TYPE_DISPOSELIST, 0, FxDriverGlobals)
45 {
46  m_List.Next = NULL;
48 
51 }
52 
54 {
55  ASSERT(m_List.Next == NULL);
56 }
57 
60  PFX_DRIVER_GLOBALS FxDriverGlobals,
61  PVOID WdmObject,
63  )
64 {
67 
68  *pObject = NULL;
69 
70  list = new(FxDriverGlobals) FxDisposeList(FxDriverGlobals);
71 
72  if (list == NULL) {
74  }
75 
76  status = list->Initialize(WdmObject);
77 
78  if (NT_SUCCESS(status)) {
79  *pObject = list;
80  }
81  else {
82  list->DeleteFromFailedCreate();
83  }
84 
85  return status;
86 }
87 
90  PVOID WdmObject
91  )
92 {
94  PFX_DRIVER_GLOBALS FxDriverGlobals = GetDriverGlobals();
95 
97 
98  status = FxSystemWorkItem::_Create(FxDriverGlobals,
99  WdmObject,
101  );
102  if (!NT_SUCCESS(status)) {
104  "Could not allocate workitem: %!STATUS!", status);
105  return status;
106  }
107 
108  m_WdmObject = WdmObject;
109 
110  return STATUS_SUCCESS;
111 }
112 
113 BOOLEAN
115  )
116 {
117  if (m_SystemWorkItem != NULL) {
120  }
121 
122  ASSERT(m_List.Next == NULL);
123 
124  FxNonPagedObject::Dispose(); // __super call
125 
126  return TRUE;
127 }
128 
129 VOID
132  )
133 
134 /*++
135 
136 Routine Description:
137 
138  Add an object to the cleanup list.
139 
140 
141 
142 
143 
144 
145 
146  The caller is expected to manage any reference counts on
147  the object while on the cleanup list
148 
149 Arguments:
150 
151  object - Object to cleanup at passive level
152 
153 Returns:
154 
155  None
156 
157 --*/
158 
159 {
160  KIRQL irql;
161  BOOLEAN previouslyEmpty;
162 
163  Lock(&irql);
164 
165  ASSERT(Object->m_DisposeSingleEntry.Next == NULL);
166 
167  previouslyEmpty = m_List.Next == NULL ? TRUE : FALSE;
168 
169  //
170  // Add to the end of m_List
171  //
172  *m_ListEnd = &Object->m_DisposeSingleEntry;
173 
174  //
175  // Update the end
176  //
177  m_ListEnd = &Object->m_DisposeSingleEntry.Next;
178 
179  if (previouslyEmpty) {
181  }
182 
183  Unlock(irql);
184 }
185 
186 VOID
188  PKIRQL PreviousIrql
189  )
190 {
191  FxObject* pObject;
193 
194  //
195  // Process items on the list until it is empty
196  //
197  while (m_List.Next != NULL) {
198  pEntry = m_List.Next;
199 
200  //
201  // Remove pEntry from the list
202  //
203  m_List.Next = pEntry->Next;
204 
205  //
206  // Indicate pEntry is no longer in the list
207  //
208  pEntry->Next = NULL;
209 
210  //
211  // Convert back to the object
212  //
214 
215  //
216  // If the list is empty, we just popped off the entry and we need to
217  // update m_ListEnd to a head of the list so it points to valid pool.
218  //
219  if (m_List.Next == NULL) {
220  m_ListEnd = &m_List.Next;
221  }
222 
223  Unlock(*PreviousIrql);
224 
225  //
226  // Invoke the objects deferred dispose entry
227  //
229 
230  //
231  // pObject may be invalid at this point due to its dereferencing itself
232  //
233  Lock(PreviousIrql);
234  }
235 }
236 
237 VOID
240  )
241 {
242  FxDisposeList* pThis;
243  KIRQL irql;
244 
245  pThis = (FxDisposeList*) Parameter;
246 
247  pThis->Lock(&irql);
248 
249  pThis->DrainListLocked(&irql);
250 
251  pThis->Unlock(irql);
252 }
253 
254 VOID
256  )
257 
258 /*++
259 
260 Routine Description:
261 
262  Wait until the list goes empty with no items.
263 
264  Note, on wakeup, new items could have been added, only the assurance
265  is that the list at least went empty for a moment.
266 
267  This allows a waiter to wait for all previous Add() items to
268  finishing processing before return.
269 
270 Arguments:
271 
272 Returns:
273 
274 --*/
275 
276 {
277  KIRQL irql;
278  BOOLEAN wait;
279 
280  Lock(&irql);
281 
282  wait = TRUE;
283 
285 
286 
287 
288 
289 
290 
291 
292  ASSERT(FALSE);
294  wait = FALSE;
295  }
296 
297  Unlock(irql);
298 
299  if (wait) {
301  }
302 
303  // Should only be true for an empty list
304  ASSERT(m_List.Next == NULL);
305 }
__drv_restoresIRQL KIRQL __in BOOLEAN Unlock
Definition: fxobject.hpp:1474
virtual VOID DeleteObject(VOID)
FxObject * pObject
static VOID _WorkItemThunk(__in PVOID Parameter)
static _Must_inspect_result_ NTSTATUS _Create(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in PVOID WdmObject, __out FxSystemWorkItem **pObject)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
Definition: ntbasedef.h:628
static FxObject * _FromDisposeEntry(__in PSINGLE_LIST_ENTRY Entry)
Definition: fxobject.hpp:580
#define TRUE
Definition: types.h:120
LONG NTSTATUS
Definition: precomp.h:26
SINGLE_LIST_ENTRY m_List
VOID DeferredDisposeWorkItem(VOID)
KIRQL irql
Definition: wave.h:1
_In_ PVOID Parameter
Definition: ldrtypes.h:241
FxDisposeList(PFX_DRIVER_GLOBALS FxDriverGlobals)
__inline BOOLEAN TryToEnqueue(__in PFN_WDF_SYSTEMWORKITEM CallbackFunc, __in PVOID Parameter)
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define FALSE
Definition: types.h:117
NTSTATUS Initialize(PVOID wdmObject)
FxSystemWorkItem * m_SystemWorkItem
SINGLE_LIST_ENTRY ** m_ListEnd
VOID MarkDisposeOverride(__in FxObjectLockState State=ObjectLock)
Definition: fxobject.hpp:1101
unsigned char BOOLEAN
virtual BOOLEAN Dispose(VOID)
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
VOID Add(FxObject *object)
struct _SINGLE_LIST_ENTRY * Next
Definition: ntbasedef.h:629
VOID DrainListLocked(PKIRQL PreviousIrql)
KIRQL * PKIRQL
Definition: env_spec_w32.h:592
Definition: _list.h:228
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
static NTSTATUS _Create(PFX_DRIVER_GLOBALS FxDriverGlobals, PVOID WdmObject, FxDisposeList **pObject)
static __inline MxThread MxGetCurrentThread()
Definition: mxgeneralkm.h:61
__inline PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxobject.hpp:734
VOID WaitForEmpty(VOID)
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
#define list
Definition: rosglue.h:35
#define NULL
Definition: types.h:112
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:124
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TRACINGIO
Definition: dbgtrace.h:66
MxThread m_WorkItemThread
virtual BOOLEAN Dispose(VOID)
PLIST_ENTRY pEntry
Definition: fxioqueue.cpp:4484
#define __in
Definition: dbghelp.h:35
static SERVICE_STATUS status
Definition: service.c:31
Definition: ps.c:97