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.

412 lines
13 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. lock.h
  5. Abstract:
  6. This module defines types and functions for the LAN Manager server
  7. FSP's lock package. This package began as a modification and
  8. streamlining of the executive resource package -- it allowed
  9. recursive acquisition, but didn't provide shared locks. Later,
  10. debugging support in the form of level checking was added.
  11. Coming full circle, the package now serves as a wrapper around the
  12. real resource package. It simply provides debugging support. The
  13. reasons for reverting to using resources include:
  14. 1) The resource package now supports recursive acquisition.
  15. 2) There are a couple of places in the server where shared access
  16. is desirable.
  17. 3) The resource package has a "no-wait" option that disables waiting
  18. for a lock when someone else owns it. This feature is useful to
  19. the server FSD.
  20. Author:
  21. Chuck Lenzmeier (chuckl) 29-Nov-1989
  22. A modification of Gary Kimura's resource package. See lock.c.
  23. David Treadwell (davidtr)
  24. Chuck Lenzmeier (chuckl) 5-Apr-1991
  25. Revert to using resource package.
  26. Environment:
  27. Kernel mode only, LAN Manager server FSP and FSD.
  28. Revision History:
  29. --*/
  30. #ifndef _LOCK_
  31. #define _LOCK_
  32. //#include <ntos.h>
  33. //
  34. // Structure containing global spin locks. Used to isolate each spin
  35. // lock into its own cache line.
  36. //
  37. typedef struct _SRV_GLOBAL_SPIN_LOCKS {
  38. ULONG Reserved1[7];
  39. KSPIN_LOCK Fsd;
  40. ULONG Reserved2[7];
  41. struct {
  42. KSPIN_LOCK Lock;
  43. ULONG Reserved3[7];
  44. } Endpoint[ENDPOINT_LOCK_COUNT];
  45. KSPIN_LOCK Statistics;
  46. ULONG Reserved4[7];
  47. KSPIN_LOCK Timer;
  48. ULONG Reserved5[7];
  49. #if SRVDBG || SRVDBG_HANDLES
  50. KSPIN_LOCK Debug;
  51. ULONG Reserved6[7];
  52. #endif
  53. } SRV_GLOBAL_SPIN_LOCKS, *PSRV_GLOBAL_SPIN_LOCKS;
  54. //
  55. // Macros for accessing spin locks.
  56. //
  57. #define ACQUIRE_SPIN_LOCK(lock,irql) { \
  58. PAGED_CODE_CHECK(); \
  59. ExAcquireSpinLock( (lock), (irql) ); \
  60. }
  61. #define RELEASE_SPIN_LOCK(lock,irql) { \
  62. PAGED_CODE_CHECK(); \
  63. ExReleaseSpinLock( (lock), (irql) ); \
  64. }
  65. #define ACQUIRE_DPC_SPIN_LOCK(lock) { \
  66. PAGED_CODE_CHECK(); \
  67. ExAcquireSpinLockAtDpcLevel( (lock) ); \
  68. }
  69. #define RELEASE_DPC_SPIN_LOCK(lock) { \
  70. PAGED_CODE_CHECK(); \
  71. ExReleaseSpinLockFromDpcLevel( (lock) ); \
  72. }
  73. #define INITIALIZE_SPIN_LOCK(lock) KeInitializeSpinLock( lock );
  74. #define GLOBAL_SPIN_LOCK(lock) SrvGlobalSpinLocks.lock
  75. #define ENDPOINT_SPIN_LOCK(index) SrvGlobalSpinLocks.Endpoint[index].Lock
  76. #define INITIALIZE_GLOBAL_SPIN_LOCK(lock) INITIALIZE_SPIN_LOCK( &GLOBAL_SPIN_LOCK(lock) )
  77. #define ACQUIRE_GLOBAL_SPIN_LOCK(lock,irql) ACQUIRE_SPIN_LOCK( &GLOBAL_SPIN_LOCK(lock), (irql) )
  78. #define RELEASE_GLOBAL_SPIN_LOCK(lock,irql) RELEASE_SPIN_LOCK( &GLOBAL_SPIN_LOCK(lock), (irql) )
  79. #define ACQUIRE_DPC_GLOBAL_SPIN_LOCK(lock) ACQUIRE_DPC_SPIN_LOCK( &GLOBAL_SPIN_LOCK(lock) )
  80. #define RELEASE_DPC_GLOBAL_SPIN_LOCK(lock) RELEASE_DPC_SPIN_LOCK( &GLOBAL_SPIN_LOCK(lock) )
  81. //
  82. // Macros for initializing, deleting, acquiring, and releasing locks.
  83. //
  84. #if !SRVDBG_LOCK
  85. //
  86. // When debugging is disabled, the lock macros simply equate to calls to
  87. // the corresponding resource package functions.
  88. //
  89. #define INITIALIZE_LOCK( lock, level, name ) ExInitializeResourceLite( (lock) )
  90. #define DELETE_LOCK( lock ) ExDeleteResourceLite( (lock) )
  91. #define ACQUIRE_LOCK( lock ) \
  92. ExAcquireResourceExclusiveLite( (lock), TRUE )
  93. #define ACQUIRE_LOCK_NO_WAIT( lock ) \
  94. ExAcquireResourceExclusiveLite( (lock), FALSE )
  95. #define ACQUIRE_LOCK_SHARED( lock ) \
  96. ExAcquireResourceSharedLite( (lock), TRUE )
  97. #define ACQUIRE_LOCK_SHARED_NO_WAIT( lock ) \
  98. ExAcquireResourceSharedLite( (lock), FALSE )
  99. #define RELEASE_LOCK(lock) ExReleaseResourceLite( (lock) )
  100. #define LOCK_NUMBER_OF_ACTIVE( lock ) ((lock)->ActiveCount)
  101. #else // !SRVDBG_LOCK
  102. //
  103. // When debugging is enabled, the lock macros equate to calls to
  104. // functions in the server. These functions are implemented in lock.c.
  105. //
  106. #define INITIALIZE_LOCK( lock, level, name ) \
  107. SrvInitializeLock( (lock), (level), (name) )
  108. #define DELETE_LOCK( lock ) SrvDeleteLock( (lock) )
  109. #define ACQUIRE_LOCK( lock ) \
  110. SrvAcquireLock( (lock), TRUE, TRUE )
  111. #define ACQUIRE_LOCK_NO_WAIT( lock ) \
  112. SrvAcquireLock( (lock), FALSE, TRUE )
  113. #define ACQUIRE_LOCK_SHARED( lock ) \
  114. SrvAcquireLock( (lock), TRUE, FALSE )
  115. #define ACQUIRE_LOCK_SHARED_NO_WAIT( lock ) \
  116. SrvAcquireLock( (lock), FALSE, FALSE )
  117. #define RELEASE_LOCK( lock ) SrvReleaseLock( (lock) )
  118. #define LOCK_NUMBER_OF_ACTIVE( lock ) ((lock)->Resource.ActiveCount)
  119. #define LOCK_NAME( lock ) ((lock)->Header.LockName)
  120. #define LOCK_LEVEL( lock ) ((lock)->Header.LockLevel)
  121. #define LOCK_THREAD_LIST( lock ) (&((lock)->Header.ThreadListEntry))
  122. #endif // else !SRVDBG_LOCK
  123. #if !SRVDBG_LOCK
  124. //
  125. // When debugging is disabled, a server lock is identical to an
  126. // executive resource.
  127. //
  128. typedef ERESOURCE SRV_LOCK, *PSRV_LOCK;
  129. #define RESOURCE_OF(_l_) (_l_)
  130. #else // !SRVDBG_LOCK
  131. //
  132. // SRV_LOCK_HEADER is a structure that contains debugging information
  133. // used by the server lock package. Server locks contain a
  134. // SRV_LOCK_HEADER.
  135. //
  136. typedef struct _SRV_LOCK_HEADER {
  137. //
  138. // To prevent deadlocks, locks are assigned level numbers. If a
  139. // thread holds a lock with level N, it may only acquire new locks
  140. // with a level greater then N. Level numbers are assigned during
  141. // lock initialization.
  142. //
  143. // *** Due to the problems involved in retaining the information
  144. // necessary to do level checking for shared locks, the lock
  145. // package only does level checking for exclusive locks.
  146. //
  147. ULONG LockLevel;
  148. //
  149. // A doubly-linked list of all the locks owned by a thread is stored
  150. // in a thread's TEB. The list is in order of lock level (from
  151. // highest to lowest), which is also, by definition of lock levels,
  152. // the order in which the thread acquired the locks. This allows
  153. // the thread to release the locks in any order while maintaining
  154. // easy access to the highest-level lock that the thread owns,
  155. // thereby providing a mechanism for ensuring that locks are
  156. // acquired in increasing order.
  157. //
  158. LIST_ENTRY ThreadListEntry;
  159. //
  160. // The symbolic name of the lock is used in DbgPrint calls.
  161. //
  162. PSZ LockName;
  163. } SRV_LOCK_HEADER, *PSRV_LOCK_HEADER;
  164. //
  165. // When debugging is enabled, a server lock is a wrapper around an
  166. // executive resource.
  167. //
  168. typedef struct _SRV_LOCK {
  169. //
  170. // The SRV_LOCK_HEADER must appear first!
  171. //
  172. SRV_LOCK_HEADER Header;
  173. //
  174. // The actual "lock" is maintained by the resource package.
  175. //
  176. ERESOURCE Resource;
  177. } SRV_LOCK, *PSRV_LOCK;
  178. #define RESOURCE_OF(_sl_) (_sl_).Resource
  179. //
  180. // Lock functions used when debugging.
  181. //
  182. VOID
  183. SrvInitializeLock(
  184. IN PSRV_LOCK Lock,
  185. IN ULONG LockLevel,
  186. IN PSZ LockName
  187. );
  188. VOID
  189. SrvDeleteLock (
  190. IN PSRV_LOCK Lock
  191. );
  192. BOOLEAN
  193. SrvAcquireLock(
  194. IN PSRV_LOCK Lock,
  195. IN BOOLEAN Wait,
  196. IN BOOLEAN Exclusive
  197. );
  198. VOID
  199. SrvReleaseLock(
  200. IN PSRV_LOCK Lock
  201. );
  202. //
  203. // Macros that define locations in the UserReserved field of the TEB
  204. // where lock level information is stored.
  205. //
  206. #define SRV_TEB_LOCK_LIST 0
  207. #define SRV_TEB_LOCK_INIT 2
  208. #define SRV_TEB_USER_SIZE (3 * sizeof(ULONG))
  209. //
  210. // Max value for lock levels is 0x7FFFFFFF.
  211. //
  212. // Levels for locks used in the server. The following must be true:
  213. //
  214. // EndpointLock must be lower than ConnectionLock (really
  215. // connection->Lock) because SrvCloseConnectionsFromClient holds
  216. // EndpointLock when it acquires ConnectionLock to check a connection's
  217. // client name, and because a number of callers hold EndpointLock when
  218. // they call SrvCloseConnection, which acquires ConnectionLock. Note
  219. // also that SrvDeleteServedNet and TerminateServer hold EndpointLock
  220. // when they call SrvCloseEndpoint; any attempt to change
  221. // SrvCloseEndpoint must take this into account.
  222. // ExamineAndProcessConnections also depends on this ordering.
  223. //
  224. // EndpointLock must be lower than MfcbListLock and MfcbLock because
  225. // EndpointLock is held while stopping the server and closing
  226. // connections, thereby closing files on the connections.
  227. //
  228. // ShareLock must be lower than ConnectionLock because
  229. // SrvCloseTreeConnectsOnShare holds ShareLock when it calls
  230. // SrvCloseTreeConnect. Note that SrvSmbTreeConnect and
  231. // SrvSmbTreeConnectAndX depend on this ordering, because they take out
  232. // both locks concurrently.
  233. //
  234. // Similarly, ShareLock must be lower than MfcbListLock and MfcbLock
  235. // because SrvCloseTreeConnectsOnShare holds ShareLock when it calls
  236. // SrvCloseRfcbsOnTree.
  237. //
  238. // MfcbListLock must be lower than MfcbLock (really mfcb->Lock) because
  239. // SrvMoveFile and DoDelete hold MfcbListLock to find an MFCB, then take
  240. // MfcbLock before releasing MfcbListLock.
  241. //
  242. // MfcbLock must be lower than OrderedListLock and ConnectionLock
  243. // because CompleteOpen acquires these locks while holding the MfcbLock.
  244. //
  245. // OrderedListLock must be lower than ConnectionLock because
  246. // SrvFindEntryInOrderedList holds the ordered list lock when in calls
  247. // the check-and-reference routine for sessions and tree connects. For
  248. // other ordered lists, this is not a problem, because the other lists
  249. // are either protected the same locks that the check-and-reference
  250. // routine uses (endpoints, connections, and shares), or the
  251. // check-and-reference routine uses a spin lock (files). Note also that
  252. // OrderedListLock and ConnectionLock are acquired concurrently and in
  253. // the proper order in SrvSmbSessionSetupAndX, SrvSmbTreeConnect, and
  254. // CompleteOpen.
  255. //
  256. // *** WARNING: If the ordered RFCB list (SrvRfcbList) or the ordered
  257. // session list (SrvSessionList) are changed to use a lock other
  258. // than SrvOrderedListLock, the above requirement may change, and
  259. // the routines listed above may need to change. Changing other
  260. // ordered lists that currently use some other global lock also may
  261. // change the requirements.
  262. //
  263. // DebugLock must be higher than MfcbLock because CompleteOpen holds
  264. // the MfcbLock when it allocates the LFCB and RFCB. The DebugLock
  265. // is held for all memory allocations. Note that because of the
  266. // way DebugLock is currently used, it is impossible to acquire other
  267. // locks while holding DebugLock.
  268. //
  269. // ConnectionLock must be higher than SearchLock because the scavenger
  270. // thread holds the search lock while walking the search list looking
  271. // for search blocks to time out, and if a block to time out is found it
  272. // closes the search which acquires the the connection lock in order to
  273. // dereference the session in by the search block.
  274. //
  275. // EndpointLock must be higher than SearchLock because in the above
  276. // scenario, SrvDereferenceSession may call SrvDereferenceConnection
  277. // which acquires the endpoint lock.
  278. //
  279. // SearchLock must be at a higher level than ShareLock because
  280. // SrvCloseShare gets the ShareLock, but SrvCloseSessionsOnTreeConnect
  281. // aquires the SearchLock.
  282. //
  283. // CommDeviceLock must be higher than MfcbLock because DoCommDeviceOpen
  284. // acquires the CommDeviceLock while holding MfcbLock.
  285. //
  286. // OplockListLock needs to be lower than ShareLock as the server may
  287. // need to call SrvDereferenceRfcb while holding the OplockListLock.
  288. // This routine may call SrvDereferenceLfcb which may call
  289. // SrvDereferenceShare which acquires the ShareLock.
  290. //
  291. // This is a summary of the above (the top lock is acquired first and
  292. // therefore must have a lower level):
  293. //
  294. // endp endp endp share share share mfcbl mfcb mfcb order mfcb
  295. // conn mfcbl mfcb conn mfcbl mfcb mfcb order conn conn debug
  296. //
  297. // search search share oplock oplock
  298. // conn endp search mfcb share
  299. //
  300. // Merging this, we find the following "threads" of requirements:
  301. //
  302. // share mfcb mfcb oplock
  303. // search debug comm share
  304. // endp
  305. // mfcbl
  306. // mfcb
  307. // order
  308. // conn
  309. //
  310. // The following locks are not affected by the above requirements:
  311. //
  312. // configuration
  313. // smbbufferlist
  314. // Connection->LicenseLock
  315. //
  316. // The levels of all of these locks are made equal and high in an
  317. // attempt to find level requirements not listed above.
  318. //
  319. #define OPLOCK_LIST_LOCK_LEVEL (ULONG)0x00000800
  320. #define SHARE_LOCK_LEVEL (ULONG)0x00000900
  321. #define SEARCH_LOCK_LEVEL (ULONG)0x00001000
  322. #define ENDPOINT_LOCK_LEVEL (ULONG)0x00002000
  323. #define MFCB_LIST_LOCK_LEVEL (ULONG)0x00003000
  324. #define MFCB_LOCK_LEVEL (ULONG)0x00004000
  325. #define COMM_DEVICE_LOCK_LEVEL (ULONG)0x00005000
  326. #define ORDERED_LIST_LOCK_LEVEL (ULONG)0x00006000
  327. #define CONNECTION_LOCK_LEVEL (ULONG)0x00007000
  328. #define CONFIGURATION_LOCK_LEVEL (ULONG)0x00010000
  329. #define UNLOCKABLE_CODE_LOCK_LEVEL (ULONG)0x00010000
  330. #define STARTUPSHUTDOWN_LOCK_LEVEL (ULONG)0x00020000
  331. #define DEBUG_LOCK_LEVEL (ULONG)0x00050000
  332. #define LICENSE_LOCK_LEVEL (ULONG)0x00100000
  333. #define FCBLIST_LOCK_LEVEL (ULONG)0x00200000
  334. #endif // else !SRVDBG_LOCK
  335. #endif // ndef _LOCK_