Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

222 lines
6.1 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. safelock.h
  5. Abstract:
  6. "safe lock" collection of routines
  7. This code is a debug-only replacement for APIs dealing with
  8. critical sections and resources. It is essentially a thin
  9. wrapper around those routines that ensures proper ordering
  10. of locks and helps catch potential deadlock situations.
  11. The code will generate debug spew (and optionally assert)
  12. when locks are acquired outside of the given order.
  13. Utilizing this code will have zero impact on the FRE builds
  14. and negligible impact on DBG builds (as it is lock- and
  15. contention-free)
  16. Here is how you use it:
  17. o #include <safelock.h>
  18. o determine the lock order for your routine and add an enum
  19. such as:
  20. typedef enum {
  21. LockTypeA,
  22. LockTypeB,
  23. LockTypeC
  24. } MY_ENUM;
  25. The code will ensure that, for instance, LockTypeA
  26. is not acquired with LockTypeC held, unless that thread
  27. already holds LockTypeA.
  28. o Once per process initialization, call the SafeLockInit()
  29. routine. This routine should only be called in checked
  30. builds.
  31. o replace every declaration of RTL_CRITICAL_SECTION
  32. with SAFE_CRITICAL_SECTION
  33. o replace every declaration of RTL_RESOURCE
  34. with SAFE_RESOURCE
  35. o replace every call to RtlEnterCriticalSection with
  36. SafeEnterCriticalSection (similary for RtlLeaveCriticalSection
  37. and other Rtl* calls involving RTL_CRITICAL_SECTION)
  38. o replace every call to RtlAcquireResource with
  39. SafeAcquireResource (similarly for RtlReleaseResource and
  40. other Rtl* calls involving RTL_RESOURCE)
  41. o RtlInitializeCriticalSection and RtlInitializeResource
  42. are replaced with SafeEnterCriticalSection and
  43. SafeInitializeResource and take one additional parameter -
  44. the enum value associated with the critical section:
  45. e.g. replace
  46. RtlInitializeCriticalSection( &critsecA );
  47. with
  48. SafeInitializeCriticalSection( &critsecA, LockTypeA );
  49. --*/
  50. #ifndef __SAFELOCK_H
  51. #define __SAFELOCK_H
  52. #include <nturtl.h>
  53. #ifdef DBG
  54. NTSTATUS
  55. SafeLockInit();
  56. typedef struct _SAFE_CRITICAL_SECTION {
  57. RTL_CRITICAL_SECTION CriticalSection;
  58. DWORD Enum;
  59. } SAFE_CRITICAL_SECTION, *PSAFE_CRITICAL_SECTION;
  60. NTSTATUS
  61. SafeEnterCriticalSection(
  62. PSAFE_CRITICAL_SECTION SafeCriticalSection
  63. );
  64. NTSTATUS
  65. SafeLeaveCriticalSection(
  66. PSAFE_CRITICAL_SECTION SafeCriticalSection
  67. );
  68. BOOLEAN
  69. SafeTryEnterCriticalSection(
  70. PSAFE_CRITICAL_SECTION SafeCriticalSection
  71. );
  72. NTSTATUS
  73. SafeInitializeCriticalSection(
  74. PSAFE_CRITICAL_SECTION SafeCriticalSection,
  75. DWORD Enum
  76. );
  77. NTSTATUS
  78. SafeInitializeCriticalSectionAndSpinCount(
  79. PSAFE_CRITICAL_SECTION CriticalSection,
  80. ULONG SpinCount,
  81. DWORD Enum
  82. );
  83. ULONG
  84. SafeSetCriticalSectionSpinCount(
  85. PSAFE_CRITICAL_SECTION CriticalSection,
  86. ULONG SpinCount
  87. );
  88. NTSTATUS
  89. SafeDeleteCriticalSection(
  90. PSAFE_CRITICAL_SECTION CriticalSection
  91. );
  92. #define SafeCritsecLockCount( _critsec ) ((_critsec)->CriticalSection.LockCount )
  93. typedef struct _SAFE_RESOURCE {
  94. RTL_RESOURCE Resource;
  95. DWORD Enum;
  96. } SAFE_RESOURCE, *PSAFE_RESOURCE;
  97. VOID
  98. SafeInitializeResource(
  99. PSAFE_RESOURCE Resource,
  100. DWORD Enum
  101. );
  102. BOOLEAN
  103. SafeAcquireResourceShared(
  104. PSAFE_RESOURCE Resource,
  105. BOOLEAN Wait
  106. );
  107. BOOLEAN
  108. SafeAcquireResourceExclusive(
  109. PSAFE_RESOURCE Resource,
  110. BOOLEAN Wait
  111. );
  112. VOID
  113. SafeReleaseResource(
  114. PSAFE_RESOURCE Resource
  115. );
  116. VOID
  117. SafeConvertSharedToExclusive(
  118. PSAFE_RESOURCE Resource
  119. );
  120. VOID
  121. SafeConvertExclusiveToShared(
  122. PSAFE_RESOURCE Resource
  123. );
  124. VOID
  125. NTAPI
  126. SafeDeleteResource (
  127. PSAFE_RESOURCE Resource
  128. );
  129. #define SafeEnterResourceCritsec( _resrc ) RtlEnterCriticalSection( &(_resrc)->Resource.CriticalSection )
  130. #define SafeLeaveResourceCritsec( _resrc ) RtlLeaveCriticalSection( &(_resrc)->Resource.CriticalSection )
  131. #define SafeNumberOfActive( _resrc ) ((_resrc)->Resource.NumberOfActive )
  132. #define SafeNumberOfWaitingShared( _resrc ) ((_resrc)->Resource.NumberOfWaitingShared )
  133. #define SafeNumberOfWaitingExclusive( _resrc ) ((_resrc)->Resource.NumberOfWaitingExclusive )
  134. #else
  135. #define SAFE_CRITICAL_SECTION RTL_CRITICAL_SECTION
  136. #define PSAFE_CRITICAL_SECTION PRTL_CRITICAL_SECTION
  137. #define SafeEnterCriticalSection RtlEnterCriticalSection
  138. #define SafeLeaveCriticalSection RtlLeaveCriticalSection
  139. #define SafeTryEnterCriticalSection RtlTryEnterCriticalSection
  140. #define SafeInitializeCriticalSection( _cs, _enum ) RtlInitializeCriticalSection( _cs )
  141. #define SafeInitializeCriticalSectionAndSpinCount( _cs, _count, _enum ) RtlInitializeCriticalSectionAndSpinCount( _cs, _count )
  142. #define SafeSetCriticalSectionSpinCount RtlSetCriticalSectionSpinCount
  143. #define SafeDeleteCriticalSection RtlDeleteCriticalSection
  144. #define SafeCritsecLockCount( _critsec ) ((_critsec)->LockCount )
  145. #define SAFE_RESOURCE RTL_RESOURCE
  146. #define PSAFE_RESOURCE PRTL_RESOURCE
  147. #define SafeInitializeResource( _res, _enum ) RtlInitializeResource( _res )
  148. #define SafeAcquireResourceShared RtlAcquireResourceShared
  149. #define SafeAcquireResourceExclusive RtlAcquireResourceExclusive
  150. #define SafeReleaseResource RtlReleaseResource
  151. #define SafeConvertSharedToExclusive RtlConvertSharedToExclusive
  152. #define SafeConvertExclusiveToShared RtlConvertExclusiveToShared
  153. #define SafeDeleteResource RtlDeleteResource
  154. #define SafeEnterResourceCritsec( _resrc ) RtlEnterCriticalSection( &(_resrc)->CriticalSection )
  155. #define SafeLeaveResourceCritsec( _resrc ) RtlLeaveCriticalSection( &(_resrc)->CriticalSection )
  156. #define SafeNumberOfActive( _resrc ) ((_resrc)->NumberOfActive )
  157. #define SafeNumberOfWaitingShared( _resrc ) ((_resrc)->NumberOfWaitingShared )
  158. #define SafeNumberOfWaitingExclusive( _resrc ) ((_resrc)->NumberOfWaitingExclusive )
  159. #endif
  160. #endif // __SAFELOCK_H