1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 ModuleName:
6 
7     MxLockUm.h
8 
9 Abstract:
10 
11     User mode implementation of lock
12     class defined in MxLock.h
13 
14 Author:
15 
16 
17 
18 Revision History:
19 
20 
21 
22 --*/
23 
24 #pragma once
25 
26 typedef struct {
27     CRITICAL_SECTION Lock;
28     bool Initialized;
29     DWORD OwnerThreadId;
30 } MdLock;
31 
32 #include "DbgMacros.h"
33 #include "MxLock.h"
34 
35 __inline
36 MxLock::MxLock(
37     )
38 {
39     CLEAR_DBGFLAG_INITIALIZED;
40 
41     m_Lock.Initialized = false;
42     m_Lock.OwnerThreadId = 0;
43 
44     MxLock::Initialize();
45 }
46 
47 __inline
48 VOID
49 MxLockNoDynam::Initialize(
50     )
51 {
52     BOOL ret;
53 
54     ASSERT_DBGFLAG_NOT_INITIALIZED;
55 
56     ret = InitializeCriticalSectionAndSpinCount(&m_Lock.Lock, 0);
57 
58     //
59     // InitializeCriticalSectionAndSpinCount always returns TRUE on Vista+
60     // Assert this contract on checked builds using DBGFLAG macro.
61     //
62     if (ret) {
63         m_Lock.Initialized = true;
64         SET_DBGFLAG_INITIALIZED;
65     }
66 
67     ASSERT_DBGFLAG_INITIALIZED;
68 }
69 
70 
71 __inline
72 VOID
73 #pragma prefast(suppress:__WARNING_UNMATCHED_DECL_ANNO, "Can't apply kernel mode annotations.");
74 MxLockNoDynam::Acquire(
75     __out KIRQL * OldIrql
76     )
77 {
78     ASSERT_DBGFLAG_INITIALIZED;
79 
80     EnterCriticalSection(&m_Lock.Lock);
81 
82     DWORD threadId = GetCurrentThreadId();
83 
84     if (threadId == m_Lock.OwnerThreadId) {
85         Mx::MxAssertMsg("Recursive acquision of the lock is not allowed", FALSE);
86     }
87 
88     m_Lock.OwnerThreadId = threadId;
89 
90     *OldIrql = PASSIVE_LEVEL;
91 }
92 
93 __inline
94 BOOLEAN
95 MxLockNoDynam::TryToAcquire(
96     VOID
97     )
98 {
99     BOOLEAN acquired;
100 
101     ASSERT_DBGFLAG_INITIALIZED;
102 
103     acquired = (BOOLEAN) TryEnterCriticalSection(&m_Lock.Lock);
104 
105     if (acquired) {
106         DWORD threadId = GetCurrentThreadId();
107 
108         if (threadId == m_Lock.OwnerThreadId) {
109             Mx::MxAssertMsg("Recursive acquision of the lock is not allowed", FALSE);
110         }
111 
112         m_Lock.OwnerThreadId = threadId;
113     }
114 
115     return acquired;
116 }
117 
118 __inline
119 VOID
120 #pragma prefast(suppress:__WARNING_UNMATCHED_DEFN, "Can't apply kernel mode annotations.");
121 MxLockNoDynam::AcquireAtDpcLevel(
122     )
123 {
124     ASSERT_DBGFLAG_INITIALIZED;
125 
126     KIRQL dontCare;
127 
128     Acquire(&dontCare);
129 }
130 
131 __inline
132 VOID
133 #pragma prefast(suppress:__WARNING_UNMATCHED_DEFN, "Can't apply kernel mode annotations.");
134 MxLockNoDynam::Release(
135     KIRQL NewIrql
136     )
137 {
138     ASSERT_DBGFLAG_INITIALIZED;
139 
140     Mx::MxAssert(NewIrql == PASSIVE_LEVEL);
141 
142     m_Lock.OwnerThreadId = 0;
143 
144     LeaveCriticalSection(&m_Lock.Lock);
145 }
146 
147 __inline
148 VOID
149 #pragma prefast(suppress:__WARNING_UNMATCHED_DEFN, "Can't apply kernel mode annotations.");
150 MxLockNoDynam::ReleaseFromDpcLevel(
151     )
152 {
153     ASSERT_DBGFLAG_INITIALIZED;
154 
155     Release(PASSIVE_LEVEL);
156 }
157 
158 __inline
159 VOID
160 MxLockNoDynam::Uninitialize(
161     )
162 {
163     ASSERT_DBGFLAG_INITIALIZED;
164 
165     DeleteCriticalSection(&m_Lock.Lock);
166     m_Lock.Initialized = false;
167 
168     CLEAR_DBGFLAG_INITIALIZED;
169 }
170 
171 __inline
172 MxLock::~MxLock(
173     )
174 {
175     //
176     // PLEASE NOTE: shared code must not rely of d'tor uninitializing the
177     // lock. d'tor may not be invoked if the event is used in a structure
178     // which is allocated/deallocated using MxPoolAllocate/Free instead of
179     // new/delete
180     //
181 
182     if (m_Lock.Initialized) {
183         this->Uninitialize();
184     }
185 }
186