1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxTransactionedList.hpp
8 
9 Abstract:
10 
11     This module defines the abstract FxTransactionedList class.
12 
13 Author:
14 
15 
16 
17 Environment:
18 
19     Both kernel and user mode
20 
21 Revision History:
22 
23 --*/
24 
25 #ifndef _FXTRANSACTIONEDLIST_H_
26 #define _FXTRANSACTIONEDLIST_H_
27 
28 enum FxListTransactionAction {
29     FxTransactionActionNothing = 1,
30     FxTransactionActionAdd,
31     FxTransactionActionRemove,
32 };
33 
34 struct FxTransactionedEntry {
35     friend FxTransactionedList;
36 
FxTransactionedEntryFxTransactionedEntry37     FxTransactionedEntry(
38         __in_opt FxObject* Object = NULL
39         )
40     {
41         m_Transaction = FxTransactionActionNothing;
42         m_TransactionedObject = Object;
43         InitializeListHead(&m_ListLink);
44         InitializeListHead(&m_TransactionLink);
45     }
46 
47     VOID
SetTransactionedObjectFxTransactionedEntry48     SetTransactionedObject(
49         __in FxObject* Object
50         )
51     {
52         m_TransactionedObject = Object;
53     }
54 
55     FxObject*
GetTransactionedObjectFxTransactionedEntry56     GetTransactionedObject(
57         VOID
58         )
59     {
60         return m_TransactionedObject;
61     }
62 
63     static
64     FxTransactionedEntry*
_FromEntryFxTransactionedEntry65     _FromEntry(
66         __in PLIST_ENTRY Entry
67         )
68     {
69         return CONTAINING_RECORD(Entry, FxTransactionedEntry, m_ListLink);
70     }
71 
72     FxListTransactionAction
GetTransactionActionFxTransactionedEntry73     GetTransactionAction(
74         VOID
75         )
76     {
77         return m_Transaction;
78     }
79 
80 private:
81     LIST_ENTRY m_ListLink;
82 
83     LIST_ENTRY m_TransactionLink;
84 
85     FxListTransactionAction m_Transaction;
86 
87     FxObject* m_TransactionedObject;
88 };
89 
90 class FxTransactionedList : public FxStump {
91 public:
92     FxTransactionedList();
93 
94     ~FxTransactionedList();
95 
96     VOID
97     LockForEnum(
98         __in PFX_DRIVER_GLOBALS FxDriverGlobals
99         );
100 
101     VOID
102     UnlockFromEnum(
103         __in PFX_DRIVER_GLOBALS FxDriverGlobals
104         );
105 
106     NTSTATUS
107     Add(
108         __in PFX_DRIVER_GLOBALS FxDriverGlobals,
109         __in FxTransactionedEntry* Entry
110         );
111 
112     VOID
113     Remove(
114         __in PFX_DRIVER_GLOBALS FxDriverGlobals,
115         __in FxTransactionedEntry* Entry
116         );
117 
118     _Must_inspect_result_
119     FxTransactionedEntry*
120     GetNextEntry(
121         __in_opt FxTransactionedEntry* Entry
122         );
123 
124     BOOLEAN
125     Deleting(
126         __in PFX_DRIVER_GLOBALS FxDriverGlobals,
127         __in_opt MxEvent* DeleteDoneEvent
128         );
129 
130 protected:
131     virtual
132     VOID
133     AcquireLock(
134         __in PFX_DRIVER_GLOBALS FxDriverGlobals,
135         __out PKIRQL Irql
136         ) =0;
137 
138     virtual
139     VOID
140     ReleaseLock(
141         __in PFX_DRIVER_GLOBALS FxDriverGlobals,
142         __in KIRQL Irql
143         ) =0;
144 
145     virtual
146     _Must_inspect_result_
147     NTSTATUS
ProcessAdd(__in FxTransactionedEntry * Entry)148     ProcessAdd(
149         __in FxTransactionedEntry* Entry
150         )
151     {
152         UNREFERENCED_PARAMETER(Entry);
153 
154         return STATUS_SUCCESS;
155     }
156 
157     virtual
158     VOID
EntryAdded(__in FxTransactionedEntry * Entry)159     EntryAdded(
160         __in FxTransactionedEntry* Entry
161         )
162     {
163         UNREFERENCED_PARAMETER(Entry);
164     }
165 
166     virtual
167     VOID
EntryRemoved(__in FxTransactionedEntry * Entry)168     EntryRemoved(
169         __in FxTransactionedEntry* Entry
170         )
171     {
172         UNREFERENCED_PARAMETER(Entry);
173     }
174 
175     virtual
176     BOOLEAN
Compare(__in FxTransactionedEntry * Entry,__in PVOID Data)177     Compare(
178         __in FxTransactionedEntry* Entry,
179         __in PVOID Data
180         )
181     {
182         UNREFERENCED_PARAMETER(Entry);
183         UNREFERENCED_PARAMETER(Data);
184 
185         return TRUE;
186     }
187 
188     VOID
189     SearchForAndRemove(
190         __in PFX_DRIVER_GLOBALS FxDriverGlobals,
191         __in PVOID EntryData
192         );
193 
194     _Must_inspect_result_
195     FxTransactionedEntry*
196     GetNextEntryLocked(
197         __in_opt FxTransactionedEntry* Entry
198         );
199 
200     BOOLEAN
201     RemoveLocked(
202         __in FxTransactionedEntry* Entry
203         );
204 
205     VOID
206     ProcessTransactionList(
207         __in PLIST_ENTRY ReleaseHead
208         );
209 
210     VOID
211     ProcessObjectsToRelease(
212         __in PLIST_ENTRY ReleaseHead
213         );
214 
215 protected:
216     LIST_ENTRY m_ListHead;
217 
218     LIST_ENTRY m_TransactionHead;
219 
220     MxEvent* m_DeletingDoneEvent;
221 
222     ULONG m_ListLockedRecursionCount;
223 
224     BOOLEAN m_DeleteOnRemove;
225 
226     BOOLEAN m_Deleting;
227 
228     //
229     // The base class does not use this field, but to save space in the size of
230     // the derived structures, we place it here after the BOOLEANs and there is
231     // minimal structure byte packing.
232     //
233     UCHAR m_Retries;
234 };
235 
236 
237 class FxSpinLockTransactionedList : public FxTransactionedList {
238 
239 public:
240     FxSpinLockTransactionedList();
241 
242 protected:
243 
244     __drv_raisesIRQL(DISPATCH_LEVEL)
245     __drv_maxIRQL(DISPATCH_LEVEL)
246     virtual
247     VOID
248     AcquireLock(
249         __in PFX_DRIVER_GLOBALS FxDriverGlobals,
250         __out PKIRQL Irql
251         );
252 
253     __drv_requiresIRQL(DISPATCH_LEVEL)
254     virtual
255     VOID
256     ReleaseLock(
257         __in PFX_DRIVER_GLOBALS FxDriverGlobals,
258         __in __drv_restoresIRQL KIRQL Irql
259         );
260 
261     MxLock m_ListLock;
262 };
263 
264 class FxWaitLockTransactionedList : public FxTransactionedList {
265 
266 public:
267 
FxWaitLockTransactionedList(__in PFX_DRIVER_GLOBALS FxDriverGlobals)268     FxWaitLockTransactionedList(
269         __in PFX_DRIVER_GLOBALS FxDriverGlobals
270         )
271     {
272         UNREFERENCED_PARAMETER(FxDriverGlobals);
273     }
274 
275     __inline
276     NTSTATUS
277 #ifdef _MSC_VER
278 #pragma prefast(suppress:__WARNING_UNMATCHED_DEFN, "_Must_inspect_result_ not needed in kernel mode as the function always succeeds");
279 #endif
Initialize(VOID)280     Initialize(
281         VOID
282         )
283     {
284         return m_StateChangeListLock.Initialize();
285     }
286 
287 protected:
288     virtual
289     _Acquires_lock_(_Global_critical_region_)
290     VOID
291     AcquireLock(
292         __in PFX_DRIVER_GLOBALS FxDriverGlobals,
293         __out PKIRQL Irql
294         );
295 
296     virtual
297     _Releases_lock_(_Global_critical_region_)
298     VOID
299     ReleaseLock(
300         __in PFX_DRIVER_GLOBALS FxDriverGlobals,
301         __in KIRQL Irql
302         );
303 
304     FxWaitLockInternal m_StateChangeListLock;
305 };
306 
307 #endif // _FXTRANSACTIONEDLIST_H_
308