Leaked source code of windows server 2003
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.

822 lines
16 KiB

  1. /*++
  2. Copyright (c) 2002 Microsoft Corporation
  3. Module Name:
  4. kx.h
  5. Abstract:
  6. This module contains the public (external) header file for the kernel
  7. that must be included after all other header files.
  8. WARNING: There is code in windows\core\ntgdi\gre\i386\locka.asm that
  9. mimics the functions to enter and leave critical regions.
  10. This is very unfortunate since any changes to the subject
  11. routines must be reflected in locka.asm also.
  12. Author:
  13. David N. Cutler (davec) 9-Jul-2002
  14. --*/
  15. #ifndef _KX_
  16. #define _KX_
  17. VOID
  18. KiCheckForKernelApcDelivery (
  19. VOID
  20. );
  21. VOID
  22. FASTCALL
  23. KiWaitForGuardedMutexEvent (
  24. IN PKGUARDED_MUTEX Mutex
  25. );
  26. FORCEINLINE
  27. VOID
  28. KeEnterGuardedRegionThread (
  29. IN PKTHREAD Thread
  30. )
  31. /*++
  32. Routine Description:
  33. This function disables special kernel APC's for the current thread.
  34. N.B. The following code does not require any interlocks. There are
  35. two cases of interest: 1) On an MP system, the thread cannot
  36. be running on two processors as once, and 2) if the thread is
  37. is interrupted to deliver a kernel mode APC which also calls
  38. this routine, the values read and stored will stack and unstack
  39. properly.
  40. Arguments:
  41. Thread - Supplies a pointer to the current thread.
  42. N.B. This must be a pointer to the current thread.
  43. Return Value:
  44. None.
  45. --*/
  46. {
  47. ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
  48. ASSERT(Thread == KeGetCurrentThread());
  49. ASSERT((Thread->SpecialApcDisable <= 0) && (Thread->SpecialApcDisable != -32768));
  50. Thread->SpecialApcDisable -= 1;
  51. KeMemoryBarrierWithoutFence();
  52. return;
  53. }
  54. FORCEINLINE
  55. VOID
  56. KeEnterGuardedRegion (
  57. VOID
  58. )
  59. /*++
  60. Routine Description:
  61. This function disables special kernel APC's for the current thread.
  62. N.B. The following code does not require any interlocks. There are
  63. two cases of interest: 1) On an MP system, the thread cannot
  64. be running on two processors as once, and 2) if the thread is
  65. is interrupted to deliver a kernel mode APC which also calls
  66. this routine, the values read and stored will stack and unstack
  67. properly.
  68. Arguments:
  69. None.
  70. Return Value:
  71. None.
  72. --*/
  73. {
  74. KeEnterGuardedRegionThread(KeGetCurrentThread());
  75. return;
  76. }
  77. FORCEINLINE
  78. VOID
  79. KeLeaveGuardedRegionThread (
  80. IN PKTHREAD Thread
  81. )
  82. /*++
  83. Routine Description:
  84. This function enables special kernel APC's.
  85. N.B. The following code does not require any interlocks. There are
  86. two cases of interest: 1) On an MP system, the thread cannot
  87. be running on two processors as once, and 2) if the thread is
  88. is interrupted to deliver a kernel mode APC which also calls
  89. this routine, the values read and stored will stack and unstack
  90. properly.
  91. Arguments:
  92. Thread - Supplies a pointer to the current thread.
  93. N.B. This must be a pointer to the current thread.
  94. Return Value:
  95. None.
  96. --*/
  97. {
  98. ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
  99. ASSERT(Thread == KeGetCurrentThread());
  100. ASSERT(Thread->SpecialApcDisable < 0);
  101. KeMemoryBarrierWithoutFence();
  102. if ((Thread->SpecialApcDisable = Thread->SpecialApcDisable + 1) == 0) {
  103. KeMemoryBarrier();
  104. if (Thread->ApcState.ApcListHead[KernelMode].Flink !=
  105. &Thread->ApcState.ApcListHead[KernelMode]) {
  106. KiCheckForKernelApcDelivery();
  107. }
  108. }
  109. return;
  110. }
  111. FORCEINLINE
  112. VOID
  113. KeLeaveGuardedRegion (
  114. VOID
  115. )
  116. /*++
  117. Routine Description:
  118. This function enables special kernel APC's.
  119. N.B. The following code does not require any interlocks. There are
  120. two cases of interest: 1) On an MP system, the thread cannot
  121. be running on two processors as once, and 2) if the thread is
  122. is interrupted to deliver a kernel mode APC which also calls
  123. this routine, the values read and stored will stack and unstack
  124. properly.
  125. Arguments:
  126. None.
  127. Return Value:
  128. None.
  129. --*/
  130. {
  131. KeLeaveGuardedRegionThread(KeGetCurrentThread());
  132. return;
  133. }
  134. FORCEINLINE
  135. VOID
  136. KeEnterCriticalRegionThread (
  137. PKTHREAD Thread
  138. )
  139. /*++
  140. Routine Description:
  141. This function disables kernel APC's for the current thread.
  142. N.B. The following code does not require any interlocks. There are
  143. two cases of interest: 1) On an MP system, the thread cannot
  144. be running on two processors as once, and 2) if the thread is
  145. is interrupted to deliver a kernel mode APC which also calls
  146. this routine, the values read and stored will stack and unstack
  147. properly.
  148. Arguments:
  149. Thread - Supplies a pointer to the current thread.
  150. N.B. This must be a pointer to the current thread.
  151. Return Value:
  152. None.
  153. --*/
  154. {
  155. ASSERT(Thread == KeGetCurrentThread());
  156. ASSERT((Thread->KernelApcDisable <= 0) && (Thread->KernelApcDisable != -32768));
  157. Thread->KernelApcDisable -= 1;
  158. KeMemoryBarrierWithoutFence();
  159. return;
  160. }
  161. FORCEINLINE
  162. VOID
  163. KeEnterCriticalRegion (
  164. VOID
  165. )
  166. /*++
  167. Routine Description:
  168. This function disables kernel APC's for the current thread.
  169. N.B. The following code does not require any interlocks. There are
  170. two cases of interest: 1) On an MP system, the thread cannot
  171. be running on two processors as once, and 2) if the thread is
  172. is interrupted to deliver a kernel mode APC which also calls
  173. this routine, the values read and stored will stack and unstack
  174. properly.
  175. Arguments:
  176. None.
  177. Return Value:
  178. None.
  179. --*/
  180. {
  181. KeEnterCriticalRegionThread(KeGetCurrentThread());
  182. return;
  183. }
  184. FORCEINLINE
  185. VOID
  186. KeLeaveCriticalRegionThread (
  187. IN PKTHREAD Thread
  188. )
  189. /*++
  190. Routine Description:
  191. This function enables normal kernel APC's for the current thread.
  192. N.B. The following code does not require any interlocks. There are
  193. two cases of interest: 1) On an MP system, the thread cannot
  194. be running on two processors as once, and 2) if the thread is
  195. is interrupted to deliver a kernel mode APC which also calls
  196. this routine, the values read and stored will stack and unstack
  197. properly.
  198. Arguments:
  199. Thread - Supplies a pointer to the current thread.
  200. N.B. This must be a pointer to the current thread.
  201. Return Value:
  202. None.
  203. --*/
  204. {
  205. ASSERT(Thread == KeGetCurrentThread());
  206. ASSERT(Thread->KernelApcDisable < 0);
  207. KeMemoryBarrierWithoutFence();
  208. if ((Thread->KernelApcDisable = Thread->KernelApcDisable + 1) == 0) {
  209. KeMemoryBarrier();
  210. if (Thread->ApcState.ApcListHead[KernelMode].Flink !=
  211. &Thread->ApcState.ApcListHead[KernelMode]) {
  212. if (Thread->SpecialApcDisable == 0) {
  213. KiCheckForKernelApcDelivery();
  214. }
  215. }
  216. }
  217. return;
  218. }
  219. FORCEINLINE
  220. VOID
  221. KeLeaveCriticalRegion (
  222. VOID
  223. )
  224. /*++
  225. Routine Description:
  226. This function enables normal kernel APC's for the current thread.
  227. N.B. The following code does not require any interlocks. There are
  228. two cases of interest: 1) On an MP system, the thread cannot
  229. be running on two processors as once, and 2) if the thread is
  230. is interrupted to deliver a kernel mode APC which also calls
  231. this routine, the values read and stored will stack and unstack
  232. properly.
  233. Arguments:
  234. None.
  235. Return Value:
  236. None.
  237. --*/
  238. {
  239. KeLeaveCriticalRegionThread(KeGetCurrentThread());
  240. return;
  241. }
  242. FORCEINLINE
  243. BOOLEAN
  244. KeAreApcsDisabled (
  245. VOID
  246. )
  247. /*++
  248. Routine description:
  249. This function returns whether kernel are disabled for the current thread.
  250. Arguments:
  251. None.
  252. Return Value:
  253. If either the kernel or special APC disable count is nonzero, then a value
  254. of TRUE is returned. Otherwise, a value of FALSE is returned.
  255. --*/
  256. {
  257. return (BOOLEAN)(KeGetCurrentThread()->CombinedApcDisable != 0);
  258. }
  259. FORCEINLINE
  260. BOOLEAN
  261. KeAreAllApcsDisabled (
  262. VOID
  263. )
  264. /*++
  265. Routine description:
  266. This function returns whether all APCs are disabled for the current thread.
  267. Arguments:
  268. None.
  269. Return Value:
  270. If either the special APC disable count is nonzero or the IRQL is greater
  271. than or equal to APC_LEVEL, then a value of TRUE is returned. Otherwise,
  272. a value of FALSE is returned.
  273. --*/
  274. {
  275. return (BOOLEAN)((KeGetCurrentThread()->SpecialApcDisable != 0) ||
  276. (KeGetCurrentIrql() >= APC_LEVEL));
  277. }
  278. FORCEINLINE
  279. VOID
  280. KeInitializeGuardedMutex (
  281. IN PKGUARDED_MUTEX Mutex
  282. )
  283. /*++
  284. Routine Description:
  285. This function initializes a guarded mutex.
  286. Arguments:
  287. Mutex - Supplies a pointer to a guarded mutex.
  288. Return Value:
  289. None.
  290. --*/
  291. {
  292. Mutex->Owner = NULL;
  293. Mutex->Count = 1;
  294. Mutex->Contention = 0;
  295. KeInitializeEvent(&Mutex->Event, SynchronizationEvent, FALSE);
  296. return;
  297. }
  298. FORCEINLINE
  299. VOID
  300. KeAcquireGuardedMutex (
  301. IN PKGUARDED_MUTEX Mutex
  302. )
  303. /*++
  304. Routine Description:
  305. This function enters a guarded region and acquires ownership of a guarded
  306. mutex.
  307. Arguments:
  308. Mutex - Supplies a pointer to a guarded mutex.
  309. Return Value:
  310. None.
  311. --*/
  312. {
  313. PKTHREAD Thread;
  314. //
  315. // Enter a guarded region and decrement the ownership count to determine
  316. // if the guarded mutex is owned.
  317. //
  318. Thread = KeGetCurrentThread();
  319. ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
  320. ASSERT(Mutex->Owner != Thread);
  321. KeEnterGuardedRegionThread(Thread);
  322. if (InterlockedDecrementAcquire(&Mutex->Count) != 0) {
  323. //
  324. // The guarded mutex is owned.
  325. //
  326. // Increment contention count and wait for ownership to be granted.
  327. //
  328. KiWaitForGuardedMutexEvent(Mutex);
  329. }
  330. //
  331. // Grant ownership of the guarded mutext to the current thread.
  332. //
  333. Mutex->Owner = Thread;
  334. #if DBG
  335. Mutex->SpecialApcDisable = Thread->SpecialApcDisable;
  336. #endif
  337. return;
  338. }
  339. FORCEINLINE
  340. VOID
  341. KeReleaseGuardedMutex (
  342. IN PKGUARDED_MUTEX Mutex
  343. )
  344. /*++
  345. Routine Description:
  346. This function releases ownership of a guarded mutex and leaves a guarded
  347. region.
  348. Arguments:
  349. Mutex - Supplies a pointer to a guarded mutex.
  350. Return Value:
  351. None.
  352. --*/
  353. {
  354. PKTHREAD Thread;
  355. //
  356. // Clear the owner thread and increment the guarded mutex count to
  357. // detemine if there are any threads waiting for ownership to be
  358. // granted.
  359. //
  360. Thread = KeGetCurrentThread();
  361. ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
  362. ASSERT(Mutex->Owner == Thread);
  363. ASSERT(Thread->SpecialApcDisable == Mutex->SpecialApcDisable);
  364. Mutex->Owner = NULL;
  365. if (InterlockedIncrementRelease(&Mutex->Count) <= 0) {
  366. //
  367. // There are one or more threads waiting for ownership of the guarded
  368. // mutex.
  369. //
  370. KeSetEventBoostPriority(&Mutex->Event, NULL);
  371. }
  372. //
  373. // Leave guarded region.
  374. //
  375. KeLeaveGuardedRegionThread(Thread);
  376. return;
  377. }
  378. FORCEINLINE
  379. BOOLEAN
  380. KeTryToAcquireGuardedMutex (
  381. IN PKGUARDED_MUTEX Mutex
  382. )
  383. /*++
  384. Routine Description:
  385. This function attempts to acquire ownership of a guarded mutex, and if
  386. successful, enters a guarded region.
  387. Arguments:
  388. Mutex - Supplies a pointer to a guarded mutex.
  389. Return Value:
  390. If the guarded mutex was successfully acquired, then a value of TRUE
  391. is returned as the function value. Otherwise, a value of FALSE is
  392. returned.
  393. --*/
  394. {
  395. PKTHREAD Thread;
  396. //
  397. // Enater a guarded region and attempt to acquire ownership of the guarded
  398. // mutex.
  399. //
  400. Thread = KeGetCurrentThread();
  401. ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
  402. KeEnterGuardedRegionThread(Thread);
  403. if (InterlockedCompareExchange(&Mutex->Count, 0, 1) != 1) {
  404. //
  405. // The guarded mutex is owned.
  406. //
  407. // Leave guarded region and return FALSE.
  408. //
  409. KeLeaveGuardedRegionThread(Thread);
  410. return FALSE;
  411. } else {
  412. //
  413. // Grant ownership of the guarded mutex to the current thread and
  414. // return TRUE.
  415. //
  416. Mutex->Owner = Thread;
  417. #if DBG
  418. Mutex->SpecialApcDisable = Thread->SpecialApcDisable;
  419. #endif
  420. return TRUE;
  421. }
  422. }
  423. FORCEINLINE
  424. VOID
  425. KeAcquireGuardedMutexUnsafe (
  426. IN PKGUARDED_MUTEX Mutex
  427. )
  428. /*++
  429. Routine Description:
  430. This function acquires ownership of a guarded mutex, but does enter a
  431. guarded region.
  432. Arguments:
  433. Mutex - Supplies a pointer to a guarded mutex.
  434. Return Value:
  435. None.
  436. --*/
  437. {
  438. PKTHREAD Thread;
  439. //
  440. // Decrement the ownership count to determine if the guarded mutex is
  441. // owned.
  442. //
  443. Thread = KeGetCurrentThread();
  444. ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
  445. (Thread->SpecialApcDisable < 0) ||
  446. (Thread->Teb == NULL) ||
  447. (Thread->Teb >= MM_SYSTEM_RANGE_START));
  448. ASSERT(Mutex->Owner != Thread);
  449. if (InterlockedDecrement(&Mutex->Count) != 0) {
  450. //
  451. // The guarded mutex is owned.
  452. //
  453. // Increment contention count and wait for ownership to be granted.
  454. //
  455. KiWaitForGuardedMutexEvent(Mutex);
  456. }
  457. //
  458. // Grant ownership of the guarded mutex to the current thread.
  459. //
  460. Mutex->Owner = Thread;
  461. return;
  462. }
  463. FORCEINLINE
  464. VOID
  465. KeReleaseGuardedMutexUnsafe (
  466. IN PKGUARDED_MUTEX Mutex
  467. )
  468. /*++
  469. Routine Description:
  470. This function releases ownership of a guarded mutex, and does not leave
  471. a guarded region.
  472. Arguments:
  473. Mutex - Supplies a pointer to a guarded mutex.
  474. Return Value:
  475. None.
  476. --*/
  477. {
  478. PKTHREAD Thread;
  479. //
  480. // Clear the owner thread and increment the guarded mutex count to
  481. // determine if there are any threads waiting for ownership to be
  482. // granted.
  483. //
  484. Thread = KeGetCurrentThread();
  485. ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
  486. (Thread->SpecialApcDisable < 0) ||
  487. (Thread->Teb == NULL) ||
  488. (Thread->Teb >= MM_SYSTEM_RANGE_START));
  489. ASSERT(Mutex->Owner == Thread);
  490. Mutex->Owner = NULL;
  491. if (InterlockedIncrement(&Mutex->Count) <= 0) {
  492. //
  493. // There are one or more threads waiting for ownership of the guarded
  494. // mutex.
  495. //
  496. KeSetEventBoostPriority(&Mutex->Event, NULL);
  497. }
  498. return;
  499. }
  500. FORCEINLINE
  501. PKTHREAD
  502. KeGetOwnerGuardedMutex (
  503. IN PKGUARDED_MUTEX Mutex
  504. )
  505. /*++
  506. Routine Description:
  507. This function returns the owner of the specified guarded mutex.
  508. Arguments:
  509. Mutex - Supplies a pointer to a guarded mutex.
  510. Return Value:
  511. If the guarded mutex is owned, then a pointer to the owner thread is
  512. returned. Otherwise, NULL is returned.
  513. --*/
  514. {
  515. return Mutex->Owner;
  516. }
  517. FORCEINLINE
  518. BOOLEAN
  519. KeIsGuardedMutexOwned (
  520. IN PKGUARDED_MUTEX Mutex
  521. )
  522. /*++
  523. Routine Description:
  524. This function tests whether the specified guarded mutext is owned.
  525. Arguments:
  526. Mutex - Supplies a pointer to a guarded mutex.
  527. Return Value:
  528. A value of TRUE is returned if the guarded mutex is owned. Otherwise,
  529. a value of FALSE is returned.
  530. --*/
  531. {
  532. return (BOOLEAN)(Mutex->Count != 1);
  533. }
  534. #endif