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