1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxSpinLock.hpp
8 
9 Abstract:
10 
11 Author:
12 
13 
14 Revision History:
15 
16 --*/
17 
18 #ifndef _FXSPINLOCK_H_
19 #define _FXSPINLOCK_H_
20 
21 #define FX_SPIN_LOCK_NUM_HISTORY_ENTRIES (10)
22 
23 struct FX_SPIN_LOCK_HISTORY_ENTRY {
24     PVOID CallersAddress;
25     LARGE_INTEGER AcquiredAtTime;
26     LONGLONG LockedDuraction;
27 };
28 
29 typedef struct FX_SPIN_LOCK_HISTORY_ENTRY *PFX_SPIN_LOCK_HISTORY_ENTRY;
30 
31 struct FX_SPIN_LOCK_HISTORY {
32     MxThread  OwningThread;
33 
34     PFX_SPIN_LOCK_HISTORY_ENTRY CurrentHistory;
35 
36     FX_SPIN_LOCK_HISTORY_ENTRY History[FX_SPIN_LOCK_NUM_HISTORY_ENTRIES];
37 };
38 
39 typedef struct FX_SPIN_LOCK_HISTORY *PFX_SPIN_LOCK_HISTORY;
40 
41 class FxSpinLock : public FxObject  {
42 
43 public:
44     FxSpinLock(
45         __in PFX_DRIVER_GLOBALS FxDriverGlobals,
46         __in USHORT ExtraSize
47         );
48 
49 
50     __drv_raisesIRQL(DISPATCH_LEVEL)
51     __drv_maxIRQL(DISPATCH_LEVEL)
52     VOID
53     AcquireLock(
54         __in PVOID CallersAddress
55         );
56 
57     __drv_requiresIRQL(DISPATCH_LEVEL)
58     VOID
59     ReleaseLock(
60         VOID
61         );
62 
63 
64     MdLock*
65     GetLock(
66         VOID
67         )
68     {
69         return &m_SpinLock.Get();
70     }
71 
72     VOID
73     SetInterruptSpinLock(
74         VOID
75         )
76     {
77         m_InterruptLock = TRUE;
78     }
79 
80     BOOLEAN
81     IsInterruptLock(
82         VOID
83         )
84     {
85         return m_InterruptLock;
86     }
87 
88 protected:
89     PFX_SPIN_LOCK_HISTORY
90     GetHistory(
91         VOID
92         )
93     {
94         if (GetObjectSize() == WDF_ALIGN_SIZE_UP(sizeof(FxSpinLock),
95                                                  MEMORY_ALLOCATION_ALIGNMENT)) {
96             return NULL;
97         }
98         else {
99             return WDF_PTR_ADD_OFFSET_TYPE(
100                 this,
101                 COMPUTE_RAW_OBJECT_SIZE(sizeof(FxSpinLock)),
102                 PFX_SPIN_LOCK_HISTORY);
103         }
104     }
105 
106 protected:
107     MxLock m_SpinLock;
108 
109     KIRQL m_Irql;
110 
111     //
112     // TRUE, this lock is being used to synchronize FxInterrupts.  As such, the
113     // caller is not allowed to actually call WDFSPINLOCK APIs on the handle
114     // because it would then be acquiring a spinlock at DISPATCH_LEVEL and the
115     // interrupt could be attempting to acquire the same lock at a higher IRQL
116     // on the same processor.
117     //
118     BOOLEAN m_InterruptLock;
119 };
120 
121 #endif // _FXSPINLOCK_H_
122