1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxWorkItem.hpp
8 
9 Abstract:
10 
11     This module implements a frameworks managed WorkItem that
12     can synchrononize with driver frameworks object locks.
13 
14 Author:
15 
16 
17 
18 
19 Environment:
20 
21     Both kernel and user mode
22 
23 Revision History:
24 
25 
26 --*/
27 
28 #ifndef _FXWORKITEM_H_
29 #define _FXWORKITEM_H_
30 
31 //
32 // Driver Frameworks WorkItem Design:
33 //
34 // The driver frameworks provides an optional WorkItem wrapper object that allows
35 // a reference counted WorkItem object to be created that can synchronize
36 // automatically with certain frameworks objects.
37 //
38 // This provides automatic synchronization between the WorkItems execution, and the
39 // frameworks objects event callbacks into the device driver.
40 //
41 // The WDFWORKITEM object is designed to be re-useable, in which it can be re-linked
42 // into the WorkItem queue after firing.
43 //
44 // Calling GetWorkItemPtr returns the WDM IoWorkItem.
45 //
46 
47 class FxWorkItem : public FxNonPagedObject {
48 
49 private:
50     //
51     // WDM work item.
52     //
53     MxWorkItem         m_WorkItem;
54 
55     // Ensures only one of either Delete or Cleanup runsdown the object
56     BOOLEAN            m_RunningDown;
57 
58     //
59     // If this is set, a WorkItem has been enqueued
60     //
61     BOOLEAN            m_Enqueued;
62 
63     //
64     // This count is used to prevent the object from being deleted if
65     // one worker thread is preempted right after we drop the lock to call
66     // the client callback and another workitem gets queued and runs
67     // to completion and signals the event.
68     //
69     ULONG           m_WorkItemRunningCount;
70 
71     //
72     // This is the Framework object who is associated with the work
73     // item if supplied
74     //
75     FxObject*          m_Object;
76 
77     //
78     // This is the callback lock for the object this WorkItem will
79     // synchronize with
80     //
81     FxCallbackLock*    m_CallbackLock;
82 
83     //
84     // This is the object whose reference count actually controls
85     // the lifetime of the m_CallbackLock
86     //
87     FxObject*          m_CallbackLockObject;
88 
89     //
90     // This is the user supplied callback function and context
91     //
92     PFN_WDF_WORKITEM   m_Callback;
93 
94     //
95     // This event is signaled when the workitem is done processing
96     // an Enqueue request.
97     //
98     FxCREvent          m_WorkItemCompleted;
99 
100     //
101     // This is a pointer to thread object that invoked our workitem
102     // callback. This value will be used to avoid deadlock when we try
103     // to flush the workitem.
104     //
105     MxThread          m_WorkItemThread;
106 
107 public:
108 
109     static
110     _Must_inspect_result_
111     NTSTATUS
112     _Create(
113         __in PFX_DRIVER_GLOBALS FxDriverGlobals,
114         __in PWDF_WORKITEM_CONFIG Config,
115         __in PWDF_OBJECT_ATTRIBUTES Attributes,
116         __in FxObject* ParentObject,
117         __out WDFWORKITEM* WorkItem
118         );
119 
120 /*++
121 
122 Routine Description:
123 
124     Construct an FxWorkItem
125 
126 Arguments:
127 
128 Returns:
129 
130     NTSTATUS
131 
132 --*/
133 
134     FxWorkItem(
135         __in PFX_DRIVER_GLOBALS FxDriverGlobals
136         );
137 
138     virtual
139     ~FxWorkItem(
140        );
141 
142     MdWorkItem
143     GetWorkItemPtr() {
144         return m_WorkItem.GetWorkItem();
145     }
146 
147 /*++
148 
149 Routine Description:
150 
151     Initialize the WorkItem using either the caller supplied WorkItem
152     struct, or if NULL, our own internally allocated one
153 
154 Arguments:
155 
156 Returns:
157 
158     NTSTATUS
159 
160 --*/
161     _Must_inspect_result_
162     NTSTATUS
163     Initialize(
164         __in PWDF_OBJECT_ATTRIBUTES Attributes,
165         __in PWDF_WORKITEM_CONFIG Config,
166         __in FxObject* ParentObject,
167         __out WDFWORKITEM* WorkItem
168         );
169 
170     virtual
171     BOOLEAN
172     Dispose(
173         VOID
174         );
175 
176     VOID
177     Enqueue(
178         );
179 
180     WDFOBJECT
181     GetAssociatedObject(
182         )
183     {
184         if( m_Object != NULL ) {
185             return m_Object->GetObjectHandle();
186         }
187         else {
188             return NULL;
189         }
190     }
191 
192     WDFWORKITEM
193     GetHandle(
194         VOID
195         )
196     {
197         return (WDFWORKITEM) GetObjectHandle();
198     }
199 
200 private:
201 
202     //
203     // Called from Dispose, or cleanup list to perform final flushing of any
204     // outstanding DPC's and dereferencing of objects.
205     //
206     VOID
207     FlushAndRundown(
208         );
209 
210     VOID
211     WorkItemHandler(
212         );
213 
214     static
215     MX_WORKITEM_ROUTINE
216     WorkItemThunk;
217 
218     VOID
219     WaitForSignal(
220         VOID
221         );
222 
223 public:
224     VOID
225     FlushAndWait(
226         VOID
227         );
228 };
229 
230 #endif // _FXWORKITEM_H_
231 
232