ReactOS 0.4.16-dev-122-g325d74c
fxtransactionedlist.cpp
Go to the documentation of this file.
1/*++
2
3Copyright (c) Microsoft Corporation. All rights reserved.
4
5Module Name:
6
7 FxTransactionedList.cpp
8
9Abstract:
10
11 This module implements a simple transactioned list which allows the caller
12 to lock the list and then iterate over it without worrying about deletes
13 and adds.
14
15Author:
16
17
18
19Environment:
20
21 Both kernel and user mode
22
23Revision History:
24
25--*/
26
27#include "fxsupportpch.hpp"
28
30{
34 m_Retries = 0;
36
39}
40
42{
45
46 //
47 // If m_DeleteOnRemove is FALSE, there is no need to iterate over any of the
48 // lists to free anything.
49 //
50 if (m_DeleteOnRemove == FALSE) {
53 return;
54 }
55
57
58 while (!IsListEmpty(&m_ListHead)) {
61
63
64 switch (pEntry->m_Transaction) {
66 //
67 // Nothing to do, no pending transaction
68 //
69 break;
70
72 //
73 // Should not have an add transaction and be on the main list at the
74 // same time!
75 //
77 break;
78
80 //
81 // Make sure it is not on the transaction list
82 //
83 RemoveEntryList(&pEntry->m_TransactionLink);
84 InitializeListHead(&pEntry->m_TransactionLink);
85
86 //
87 // When inserted as a remove transaction, we add this reference in
88 // RemoveLocked
89 //
90 pEntry->GetTransactionedObject()->RELEASE(pEntry);
91 break;
92
93 }
94
95 pEntry->GetTransactionedObject()->DeleteObject();
96 }
97
101
102 pEntry = CONTAINING_RECORD(ple, FxTransactionedEntry, m_TransactionLink);
103
104 //
105 // We yanked out all of the removes in the previous loop
106 //
107 ASSERT(pEntry->m_Transaction == FxTransactionActionAdd);
108
109 //
110 // Delete the object since this list owns it.
111 //
112 pEntry->GetTransactionedObject()->DeleteObject();
113 }
114}
115
116VOID
118 __in PFX_DRIVER_GLOBALS FxDriverGlobals
119 )
120{
121 KIRQL irql;
122
123 AcquireLock(FxDriverGlobals, &irql);
125 ReleaseLock(FxDriverGlobals, irql);
126}
127
128VOID
130 __in PFX_DRIVER_GLOBALS FxDriverGlobals
131 )
132{
133 LIST_ENTRY releaseHead;
134 KIRQL irql;
135 MxEvent* event;
136
137 InitializeListHead(&releaseHead);
138 event = NULL;
139 AcquireLock(FxDriverGlobals, &irql);
141 ProcessTransactionList(&releaseHead);
142
144 event = m_DeletingDoneEvent;
146 }
147 ReleaseLock(FxDriverGlobals, irql);
148
149 ProcessObjectsToRelease(&releaseHead);
150
151 if (event != NULL) {
152 event->Set();
153 }
154}
155
156VOID
158 __in PLIST_ENTRY ReleaseHead
159 )
160{
163
164 //
165 // If there are other iterators, do not process transactions until they are
166 // done.
167 //
169 return;
170 }
171
172 while (!IsListEmpty(&m_TransactionHead)) {
175
176 pEntry = CONTAINING_RECORD(ple, FxTransactionedEntry, m_TransactionLink);
177
178 ASSERT(pEntry->m_Transaction != FxTransactionActionNothing);
179
180 if (pEntry->m_Transaction == FxTransactionActionAdd) {
181 //
182 // Add to the main list
183 //
184 InsertTailList(&m_ListHead, &pEntry->m_ListLink);
185
186 //
187 // Virtual notification of addition
188 //
190 }
191 else if (pEntry->m_Transaction == FxTransactionActionRemove) {
192 //
193 // Remove it from the main list and move it to a free list
194 //
195 RemoveEntryList(&pEntry->m_ListLink);
196 InsertTailList(ReleaseHead, &pEntry->m_TransactionLink);
197
198 //
199 // Virtual notification of removal
200 //
202 }
203
204 pEntry->m_Transaction = FxTransactionActionNothing;
205 }
206}
207
208VOID
210 __in PLIST_ENTRY ReleaseHead
211 )
212{
215
216 while (!IsListEmpty(ReleaseHead)) {
217 ple = RemoveHeadList(ReleaseHead);
219
220 pEntry = CONTAINING_RECORD(ple, FxTransactionedEntry, m_TransactionLink);
221
222 //
223 // We always release our reference we took when we post the change
224 // to the list
225 //
226 pEntry->GetTransactionedObject()->RELEASE(pEntry);
227
228 //
229 // 2ndary release if the list is set to do this
230 //
231 if (m_DeleteOnRemove) {
232 pEntry->GetTransactionedObject()->DeleteObject();
233 }
234 }
235}
236
239 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
240 __in_opt MxEvent* DeleteDoneEvent
241 )
242{
243 KIRQL irql;
245
246 result = TRUE;
247
248 AcquireLock(FxDriverGlobals, &irql);
250
252 m_DeletingDoneEvent = DeleteDoneEvent;
253 result = FALSE;
254 }
255
256 ReleaseLock(FxDriverGlobals, irql);
257
258 return result;
259}
260
264 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
266 )
267{
269 KIRQL irql;
270
271 AcquireLock(FxDriverGlobals, &irql);
272
273 if (m_Deleting) {
275 }
276 else {
278 }
279
280 if (NT_SUCCESS(status)) {
282 //
283 // We can insert the entry now, do so
284 //
285 InsertTailList(&m_ListHead, &Entry->m_ListLink);
286
288 }
289 else {
290 //
291 // List is locked, queue a transaction
292 //
293 Entry->m_Transaction = FxTransactionActionAdd;
294 InsertTailList(&m_TransactionHead, &Entry->m_TransactionLink);
295 }
296 }
297
298 ReleaseLock(FxDriverGlobals, irql);
299
300 return status;
301}
302
303VOID
305 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
306 __in PVOID EntryData
307 )
308{
309 KIRQL irql;
312 BOOLEAN removed;
313
314 removed = FALSE;
315
316 AcquireLock(FxDriverGlobals, &irql);
317
320 ple = ple->Flink) {
321
322 pEntry = CONTAINING_RECORD(ple, FxTransactionedEntry, m_TransactionLink);
323
324 if (Compare(pEntry, EntryData)) {
325 if (pEntry->GetTransactionAction() == FxTransactionActionAdd) {
326 RemoveEntryList(&pEntry->m_TransactionLink);
327 InitializeListHead(&pEntry->m_TransactionLink);
328
329 removed = TRUE;
330 }
331 else {
332 //
333 // Already being removed, just return
334 //
335 ASSERT(pEntry->GetTransactionAction() ==
337 }
338
339 goto Done;
340 }
341 }
342
343 //
344 // Walk the committed list
345 //
346 pEntry = NULL;
347
348 while ((pEntry = GetNextEntryLocked(pEntry)) != NULL) {
349 if (Compare(pEntry, EntryData)) {
350 removed = RemoveLocked(pEntry);
351 break;
352 }
353 }
354
355Done:
356 ReleaseLock(FxDriverGlobals, irql);
357
358 if (removed && m_DeleteOnRemove) {
359 pEntry->GetTransactionedObject()->DeleteObject();
360 }
361}
362
363VOID
365 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
367 )
368{
369 BOOLEAN removed;
370 KIRQL irql;
371
372 AcquireLock(FxDriverGlobals, &irql);
373 removed = RemoveLocked(Entry);
374 ReleaseLock(FxDriverGlobals,irql);
375
376 if (removed && m_DeleteOnRemove) {
377 Entry->GetTransactionedObject()->DeleteObject();
378 }
379}
380
384 )
385{
386 BOOLEAN removed;
387
388 removed = FALSE;
389
390 if (Entry->m_Transaction == FxTransactionActionAdd) {
391 //
392 // Not yet added to the list proper, remove it from the transaction list
393 //
394 removed = TRUE;
395 RemoveEntryList(&Entry->m_TransactionLink);
396 InitializeListHead(&Entry->m_TransactionLink);
397
398 Entry->m_Transaction = FxTransactionActionNothing;
399 }
400 else {
401 ASSERT(!IsListEmpty(&Entry->m_ListLink));
402
404 //
405 // List is not locked, remove it now
406 //
407 RemoveEntryList(&Entry->m_ListLink);
408 InitializeListHead(&Entry->m_ListLink);
409
410 //
411 // Virtual notification
412 //
414
415 removed = TRUE;
416 }
417 else {
418 //
419 // List is locked for enumeration, queue a transaction
420 //
421 Entry->m_Transaction = FxTransactionActionRemove;
422 InsertTailList(&m_TransactionHead, &Entry->m_TransactionLink);
423 Entry->GetTransactionedObject()->ADDREF(Entry);
424 }
425 }
426
427 return removed;
428}
429
434 )
435/*++
436
437Routine Description:
438 Gets the next entry. Assumes the caller has called LockedForEnum
439
440Arguments:
441 Entry the current entry in the iteratation, NULL for the first
442
443Return Value:
444 next entry in the iteration, NULL if there are no more entries
445
446 --*/
447{
448 //
449 // The caller should have locked the list for enumeration
450 //
452
454}
455
460 )
461/*++
462
463Routine Description:
464 Returns the next entry. Assumes that the caller has the list locked through
465 a call to AcquireLock() or through LockForEnum()
466
467Arguments:
468 Entry the current entry in the iteratation, NULL for the first
469
470Return Value:
471 next entry in the iteration, NULL if there are no more entries
472
473 --*/
474{
476
477 if (Entry == NULL) {
479 }
480 else {
481 ple = Entry->m_ListLink.Flink;
482 }
483
484 //
485 // Find the next entry which does not have a pending transaction on it
486 //
487 for ( ; ple != &m_ListHead; ple = ple->Flink) {
489
492 return pNext;
493 }
494 }
495
496 //
497 // Reached the end of the list
498 //
499 return NULL;
500}
501
504{
505}
506
509VOID
511 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
513 )
514{
515 UNREFERENCED_PARAMETER(FxDriverGlobals);
516 m_ListLock.Acquire(Irql);
517}
518
520VOID
522 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
524 )
525{
526 UNREFERENCED_PARAMETER(FxDriverGlobals);
527 m_ListLock.Release(Irql);
528}
529
530_Acquires_lock_(_Global_critical_region_)
531VOID
533 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
535 )
536{
538 m_StateChangeListLock.AcquireLock(FxDriverGlobals);
539}
540
541_Releases_lock_(_Global_critical_region_)
542VOID
544 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
546 )
547{
549 m_StateChangeListLock.ReleaseLock(FxDriverGlobals);
550}
551
552
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
_Must_inspect_result_ FxTransactionedEntry * GetNextEntryLocked(__in_opt FxTransactionedEntry *Entry)
virtual _Must_inspect_result_ NTSTATUS ProcessAdd(__in FxTransactionedEntry *Entry)
_Must_inspect_result_ FxTransactionedEntry * GetNextEntry(__in_opt FxTransactionedEntry *Entry)
VOID SearchForAndRemove(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in PVOID EntryData)
VOID ProcessObjectsToRelease(__in PLIST_ENTRY ReleaseHead)
VOID ProcessTransactionList(__in PLIST_ENTRY ReleaseHead)
VOID UnlockFromEnum(__in PFX_DRIVER_GLOBALS FxDriverGlobals)
BOOLEAN RemoveLocked(__in FxTransactionedEntry *Entry)
virtual VOID EntryRemoved(__in FxTransactionedEntry *Entry)
NTSTATUS Add(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in FxTransactionedEntry *Entry)
virtual VOID EntryAdded(__in FxTransactionedEntry *Entry)
VOID LockForEnum(__in PFX_DRIVER_GLOBALS FxDriverGlobals)
VOID Remove(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in FxTransactionedEntry *Entry)
virtual VOID ReleaseLock(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in KIRQL Irql)=0
BOOLEAN Deleting(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in_opt MxEvent *DeleteDoneEvent)
virtual VOID AcquireLock(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __out PKIRQL Irql)=0
virtual BOOLEAN Compare(__in FxTransactionedEntry *Entry, __in PVOID Data)
FxWaitLockInternal m_StateChangeListLock
#define _Acquires_lock_(lock)
#define _Releases_lock_(lock)
_Out_ PKIRQL Irql
Definition: csq.h:179
#define __in
Definition: dbghelp.h:35
#define __in_opt
Definition: dbghelp.h:38
#define __out
Definition: dbghelp.h:62
#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 __drv_restoresIRQL
Definition: driverspecs.h:322
#define __drv_requiresIRQL(irql)
Definition: driverspecs.h:321
#define __drv_raisesIRQL(irql)
Definition: driverspecs.h:312
#define __drv_maxIRQL(irql)
Definition: driverspecs.h:291
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
UCHAR KIRQL
Definition: env_spec_w32.h:591
KIRQL * PKIRQL
Definition: env_spec_w32.h:592
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
PSINGLE_LIST_ENTRY ple
PLIST_ENTRY pEntry
Definition: fxioqueue.cpp:4484
@ FxTransactionActionNothing
@ FxTransactionActionAdd
@ FxTransactionActionRemove
struct _cl_event * event
Definition: glext.h:7739
GLuint64EXT * result
Definition: glext.h:11304
#define ASSERT(a)
Definition: mode.c:44
#define _Must_inspect_result_
Definition: ms_sal.h:558
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
base of all file and directory entries
Definition: entries.h:83
static FxTransactionedEntry * _FromEntry(__in PLIST_ENTRY Entry)
FxListTransactionAction m_Transaction
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
Definition: ps.c:97
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
#define STATUS_INVALID_DEVICE_STATE
Definition: udferr_usr.h:178