ReactOS 0.4.15-dev-7788-g1ad9096
FxTagTracker Class Reference

#include <fxtagtracker.hpp>

Inheritance diagram for FxTagTracker:
Collaboration diagram for FxTagTracker:

Public Member Functions

 ~FxTagTracker ()
 
VOID CheckForAbandondedTags (VOID)
 
VOID UpdateTagHistory (__in PVOID Tag, __in LONG Line, __in_opt PSTR File, __in FxTagRefType RefType, __in ULONG RefCount)
 
- Public Member Functions inherited from FxGlobalsStump
 FxGlobalsStump (__in PFX_DRIVER_GLOBALS FxDriverGlobals)
 
PFX_DRIVER_GLOBALS GetDriverGlobals (VOID)
 
- Public Member Functions inherited from FxStump
PVOID operator new (__in size_t Size, __in PFX_DRIVER_GLOBALS FxDriverGlobals)
 
PVOID operator new (__in size_t Size, __in PFX_DRIVER_GLOBALS FxDriverGlobals, __in POOL_TYPE PoolType)
 
VOID operator delete (__in PVOID pointer)
 
PVOID operator new[] (__in size_t Size, __in PFX_DRIVER_GLOBALS FxDriverGlobals)
 
VOID operator delete[] (__in PVOID pointer)
 

Static Public Member Functions

static _Must_inspect_result_ NTSTATUS __inline CreateAndInitialize (__out FxTagTracker **TagTracker, __in PFX_DRIVER_GLOBALS FxDriverGlobals, __in FxTagTrackerType Type, __in BOOLEAN CaptureStack, __in FxObject *Owner, __in_opt PVOID CreateTag=NULL)
 

Protected Attributes

FxTagTrackerType m_TrackerType
 
BOOLEAN m_CaptureStack
 
FxObjectm_OwningObject
 
LIST_ENTRY m_TrackerEntry
 
LONG m_FailedCount
 
MxLock m_SpinLock
 
FxTagTrackingBlockm_Next
 
FxTagHistory m_TagHistory [TAG_HISTORY_DEPTH]
 
LONG m_CurRefHistory
 

Private Member Functions

 FxTagTracker (__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in FxTagTrackerType Type, __in BOOLEAN CaptureStack, __in FxObject *Owner, __in_opt PVOID CreateTag=NULL)
 
VOID CopyStackFrames (_Inout_ FxTagTrackingStackFrames **StackFrames, _In_ USHORT NumFrames, _In_reads_(NumFrames) PVOID *Frames)
 

Additional Inherited Members

- Protected Member Functions inherited from FxStump
 FxStump (VOID)
 

Detailed Description

Definition at line 151 of file fxtagtracker.hpp.

Constructor & Destructor Documentation

◆ FxTagTracker()

FxTagTracker::FxTagTracker ( __in PFX_DRIVER_GLOBALS  FxDriverGlobals,
__in FxTagTrackerType  Type,
__in BOOLEAN  CaptureStack,
__in FxObject Owner,
__in_opt PVOID  CreateTag = NULL 
)
inlineprivate

Definition at line 160 of file fxtagtracker.hpp.

166 :
167 FxGlobalsStump(FxDriverGlobals),
169 m_CaptureStack(CaptureStack),
170 m_Next(NULL),
171 m_FailedCount(0),
174 {
176
177 //
178 // We keep handle reference trackers in a list,
179 // which wdfkd uses to identify potential handle leaks.
180 //
183 KIRQL irql;
184
185 pExtension = GetDriverGlobals()->DebugExtension;
186 ASSERT(pExtension != NULL);
187
188 //
189 // Insert the tag tracker into the list of allocated trackers
190 //
191 pExtension->AllocatedTagTrackersLock.Acquire(&irql);
194 pExtension->AllocatedTagTrackersLock.Release(irql);
195
196 //
197 // Handle references default to 1 outstanding ref (the object creation ref)
198 //
199 m_Next = new(FxDriverGlobals) FxTagTrackingBlock(CreateTag, 0, NULL, TRUE);
200 if (m_Next == NULL) {
201 m_FailedCount = 1;
202 }
203 }
204 else {
206 }
207 }
Type
Definition: Type.h:7
FxTagTrackerType m_TrackerType
FxObject * m_OwningObject
BOOLEAN m_CaptureStack
FxTagHistory m_TagHistory[TAG_HISTORY_DEPTH]
LIST_ENTRY m_TrackerEntry
FxTagTrackingBlock * m_Next
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
KIRQL irql
Definition: wave.h:1
#define InsertTailList(ListHead, Entry)
UCHAR KIRQL
Definition: env_spec_w32.h:591
@ FxTagTrackerTypePower
@ FxTagTrackerTypeHandle
#define ASSERT(a)
Definition: mode.c:44
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ SaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ OwnerSize PSID Owner
Definition: rtlfuncs.h:1597
LIST_ENTRY AllocatedTagTrackersListHead
Definition: fxglobals.h:134
PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxstump.hpp:98
FxDriverGlobalsDebugExtension * DebugExtension
Definition: fxglobals.h:376
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262

◆ ~FxTagTracker()

FxTagTracker::~FxTagTracker ( )

Definition at line 53 of file fxtagtracker.cpp.

67{
68 KIRQL irql;
70
73
75
76 pExtension = GetDriverGlobals()->DebugExtension;
77
78 //
79 // Remove this tracker from the list of allocated trackers
80 //
81 pExtension->AllocatedTagTrackersLock.Acquire(&irql);
83 pExtension->AllocatedTagTrackersLock.Release(irql);
84 } else {
86 }
87
88 //
89 // Delete any outstanding tracking blocks.
90 //
91 m_SpinLock.Acquire(&irql);
92
94 m_Next = NULL;
95
96 while (current != NULL) {
97 next = current->Next;
98 delete current;
99 current = next;
100 }
101
102 m_SpinLock.Release(irql);
103}
VOID CheckForAbandondedTags(VOID)
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] STATPROPSETSTG *rgelt, [out] ULONG *pceltFetched)
struct task_struct * current
Definition: linux.c:32
static unsigned __int64 next
Definition: rand_nt.c:6

Member Function Documentation

◆ CheckForAbandondedTags()

VOID FxTagTracker::CheckForAbandondedTags ( VOID  )

Definition at line 293 of file fxtagtracker.cpp.

310{
313 LONG abandoned;
314 KIRQL irql;
315 BOOLEAN committed;
316
318
319 committed = m_OwningObject->IsCommitted();
320
321 //
322 // If the object was not committed, then it was an FxObject derived
323 // class that was *embedded* as a field in another structure or class.
324 // As such, we are allowing one outstanding reference at this time. We will
325 // catch > 1 outstanding references below in the while loop.
326 //
327 if (committed) {
328 if (m_Next != NULL || m_FailedCount != 0) {
330 "Dropped references on a tag tracker, "
331 "show references with: !wdftagtracker %p", this);
332 //
333 // If this ASSERT fails, look in the history .. you'll
334 // likely find that you released more references than you had
335 //
336 ASSERT(m_Next == NULL && m_FailedCount == 0);
337 }
338 }
339
340 m_SpinLock.Acquire(&irql);
341
342 current = m_Next;
343 abandoned = 0;
344
345 while (current != NULL) {
346 next = current->Next;
347
348 if (committed) {
350 "Abandonded ref on object %p tag %p (%s @ %d)",
351 m_OwningObject, current->Tag, current->File, current->Line);
352 abandoned++;
353 }
354
355 if (committed == FALSE) {
356 //
357 // The next time we encounter an abandoned reference, we will complain
358 // about it...we have used up our allowance of one leaked reference
359 // because the object is an embedded object.
360 //
361 // NOTE: we might be eating the real outstanding reference here
362 // and not tracing it and then tracing the initial creation
363 // reference as the leaked reference which will be confusing.
364 // This is b/c there is no way to distinguish what is the
365 // tracking block used to track the creatio of the object.
366 //
367 committed = TRUE;
368
370 "Possibly Abandonded ref on object %p tag %p (%s @ %d). "
371 "Is benign unless there are other outstanding leaked references.",
372 m_OwningObject, current->Tag, current->File, current->Line);
373 }
374
375 current = next;
376 }
377
378 m_SpinLock.Release(irql);
379
380 ASSERTMSG("Abandoned tags on ref\n", abandoned == 0);
381}
unsigned char BOOLEAN
BOOLEAN IsCommitted(VOID)
Definition: fxobject.hpp:1087
#define TRACINGDEVICE
Definition: dbgtrace.h:58
#define FALSE
Definition: types.h:117
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
PFX_DRIVER_GLOBALS pFxDriverGlobals
#define ASSERTMSG(msg, exp)
Definition: nt_native.h:431
long LONG
Definition: pedump.c:60
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27

Referenced by FxObject::ProcessDestroy(), and ~FxTagTracker().

◆ CopyStackFrames()

VOID FxTagTracker::CopyStackFrames ( _Inout_ FxTagTrackingStackFrames **  StackFrames,
_In_ USHORT  NumFrames,
_In_reads_(NumFrames) PVOID Frames 
)
private

Definition at line 106 of file fxtagtracker.cpp.

111{
113 FxTagTrackingStackFrames* stackFrames;
114
115 //
116 // FxTagHistory structs are stored in a circular buffer and reused,
117 // so we also reuse the FxTagTrackingStackFrames that each allocates.
118 //
119 stackFrames = *StackFrames;
120 if (stackFrames == NULL) {
123 if (stackFrames == NULL) {
124 return;
125 }
126
127 *StackFrames = stackFrames;
128 }
129
130 stackFrames->NumFrames = NumFrames;
131
132 for (int i = 0; i < NumFrames; i++) {
133 stackFrames->Frames[i] = (ULONG64)Frames[i];
134 }
135}
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
unsigned __int64 ULONG64
Definition: imports.h:198
ULONG64 Frames[FRAMES_TO_CAPTURE]

Referenced by UpdateTagHistory().

◆ CreateAndInitialize()

static _Must_inspect_result_ NTSTATUS __inline FxTagTracker::CreateAndInitialize ( __out FxTagTracker **  TagTracker,
__in PFX_DRIVER_GLOBALS  FxDriverGlobals,
__in FxTagTrackerType  Type,
__in BOOLEAN  CaptureStack,
__in FxObject Owner,
__in_opt PVOID  CreateTag = NULL 
)
inlinestatic

Definition at line 222 of file fxtagtracker.hpp.

230 {
232
233 FxTagTracker * tagTracker = new(FxDriverGlobals)
234 FxTagTracker(FxDriverGlobals, Type, CaptureStack, Owner, CreateTag);
235
236 if (NULL == tagTracker) {
238
240 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
241 "Failed to allocate tag tracker, returning %!STATUS!", status);
242
243 goto exit;
244 }
245
246 *TagTracker = tagTracker;
248
249 exit:
250 return status;
251 }
LONG NTSTATUS
Definition: precomp.h:26
#define exit(n)
Definition: config.h:202
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: ps.c:97
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158

Referenced by FxObject::AllocateTagTracker(), and FxPowerIdleMachine::Reset().

◆ UpdateTagHistory()

VOID FxTagTracker::UpdateTagHistory ( __in PVOID  Tag,
__in LONG  Line,
__in_opt PSTR  File,
__in FxTagRefType  RefType,
__in ULONG  RefCount 
)

Definition at line 138 of file fxtagtracker.cpp.

167{
169 FxTagHistory* pTagHistory;
170 FxTagTrackingBlock* pBlock;
171 LONG pos;
172 KIRQL irql;
173 USHORT numFrames = 0;
174 PVOID frames[FRAMES_TO_CAPTURE];
175
177
180
181 //
182 // Prefast reports that m_CurRefHistory can be negative which can lead to
183 // underflow. But we know that m_CurRefHistory would never be negative.
184 // Hence we assert for the condition below and assume that it would be true.
185 //
187
188 pTagHistory = m_TagHistory + pos;
189
190 pTagHistory->RefType = RefType;
191 pTagHistory->RefCount = RefCount;
192 pTagHistory->Line = Line;
193 pTagHistory->Tag = Tag;
194 pTagHistory->File = File;
195
196 if (m_CaptureStack) {
199 frames,
200 NULL);
201 if (numFrames > 0) {
202 CopyStackFrames(&pTagHistory->StackFrames, numFrames, frames);
203 }
204 }
205
206 //
207 // We use the perf counter here and the tick count in the tracking block.
208 // Use the tick count here as well until we decide that correlating the
209 // perf counter to system time is not important.
210 //
211 // pTagHistory->Time = KeQueryPerformanceCounter(NULL);
212 Mx::MxQueryTickCount(&pTagHistory->Time);
213
214 if (RefType == TagAddRef) {
215
216 //
217 // Try to allocate some memory for the new block. If unsuccessful,
218 // fallback to a failed count increment.
219 //
221
222 if (pBlock == NULL) {
224 }
225 else {
226 m_SpinLock.Acquire(&irql);
227 pBlock->Next = m_Next;
228 m_Next = pBlock;
229 m_SpinLock.Release(irql);
230
231 if (m_CaptureStack && numFrames > 0) {
232 CopyStackFrames(&pBlock->StackFrames, numFrames, frames);
233 }
234 }
235 }
236 else {
237 FxTagTrackingBlock **prev;
238
239 //
240 // Walk the list of current blocks and attempt to find the tag being
241 // released. If not found, decrement the failed count. If no failed
242 // tags exists, ASSERT immediately.
243 //
244
245 m_SpinLock.Acquire(&irql);
246 prev = &m_Next;
247 pBlock = *prev;
248
249 while (pBlock != NULL) {
250 if (pBlock->Tag == Tag) {
251 *prev = pBlock->Next;
252 break;
253 }
254
255 prev = &pBlock->Next;
256 pBlock = pBlock->Next;
257 }
258
259 m_SpinLock.Release(irql);
260
261 if (pBlock == NULL) {
262 //
263 // Check to see if we have any credits in our Low Memory Count.
264 // In this fassion we can tell if we have acquired any locks without
265 // the memory for adding tracking blocks.
266 //
268 //
269 // We have just released a lock that neither had a corresponding
270 // tracking block, nor a credit in LowMemoryCount.
271 //
273
276 "releasing %s %p on object %p that was not acquired, !wdftagtracker %p",
277 m_TrackerType == FxTagTrackerTypePower ? "power tag" : "tag",
278 Tag,
280 this);
281
283 }
284 }
285 else {
286 delete pBlock;
287 pBlock = NULL;
288 }
289 }
290}
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
Definition: File.h:16
VOID CopyStackFrames(_Inout_ FxTagTrackingStackFrames **StackFrames, _In_ USHORT NumFrames, _In_reads_(NumFrames) PVOID *Frames)
static __inline VOID MxQueryTickCount(__out PLARGE_INTEGER TickCount)
Definition: mxgeneralkm.h:116
FxVerifierDbgBreakPoint(pFxDriverGlobals)
#define FX_ASSERT_AND_ASSUME_FOR_PREFAST(b)
Definition: fxmacros.hpp:284
@ TagAddRef
#define FRAMES_TO_CAPTURE
#define TAG_HISTORY_DEPTH
#define FRAMES_TO_SKIP
unsigned short USHORT
Definition: pedump.c:61
FxTagTrackingStackFrames * StackFrames
LARGE_INTEGER Time
FxTagRefType RefType
FxTagTrackingStackFrames * StackFrames
struct FxTagTrackingBlock * Next
Definition: ncftp.h:79
_Must_inspect_result_ _In_ WDFDEVICE _In_ BOOLEAN _In_opt_ PVOID Tag
Definition: wdfdevice.h:4065
NTSYSAPI USHORT NTAPI RtlCaptureStackBackTrace(_In_ ULONG FramesToSkip, _In_ ULONG FramesToCapture, _Out_writes_to_(FramesToCapture, return) PVOID *BackTrace, _Out_opt_ PULONG BackTraceHash)

Referenced by FxObject::AddRef(), FxPowerIdleMachine::IoDecrement(), FxPowerIdleMachine::PowerReferenceWorker(), and FxObject::Release().

Member Data Documentation

◆ m_CaptureStack

BOOLEAN FxTagTracker::m_CaptureStack
protected

Definition at line 278 of file fxtagtracker.hpp.

Referenced by UpdateTagHistory().

◆ m_CurRefHistory

LONG FxTagTracker::m_CurRefHistory
protected

Definition at line 313 of file fxtagtracker.hpp.

Referenced by UpdateTagHistory().

◆ m_FailedCount

LONG FxTagTracker::m_FailedCount
protected

Definition at line 293 of file fxtagtracker.hpp.

Referenced by CheckForAbandondedTags(), FxTagTracker(), and UpdateTagHistory().

◆ m_Next

FxTagTrackingBlock* FxTagTracker::m_Next
protected

◆ m_OwningObject

FxObject* FxTagTracker::m_OwningObject
protected

Definition at line 283 of file fxtagtracker.hpp.

Referenced by CheckForAbandondedTags(), and UpdateTagHistory().

◆ m_SpinLock

MxLock FxTagTracker::m_SpinLock
protected

Definition at line 298 of file fxtagtracker.hpp.

Referenced by CheckForAbandondedTags(), UpdateTagHistory(), and ~FxTagTracker().

◆ m_TagHistory

FxTagHistory FxTagTracker::m_TagHistory[TAG_HISTORY_DEPTH]
protected

Definition at line 308 of file fxtagtracker.hpp.

Referenced by FxTagTracker(), and UpdateTagHistory().

◆ m_TrackerEntry

LIST_ENTRY FxTagTracker::m_TrackerEntry
protected

Definition at line 288 of file fxtagtracker.hpp.

Referenced by FxTagTracker(), and ~FxTagTracker().

◆ m_TrackerType

FxTagTrackerType FxTagTracker::m_TrackerType
protected

Definition at line 273 of file fxtagtracker.hpp.

Referenced by FxTagTracker(), UpdateTagHistory(), and ~FxTagTracker().


The documentation for this class was generated from the following files: