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