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.

2685 lines
54 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. ki.h
  5. Abstract:
  6. This module contains the private (internal) header file for the
  7. kernel.
  8. Author:
  9. David N. Cutler (davec) 28-Feb-1989
  10. Revision History:
  11. --*/
  12. #ifndef _KI_
  13. #define _KI_
  14. #pragma warning(disable:4214) // bit field types other than int
  15. #pragma warning(disable:4201) // nameless struct/union
  16. #pragma warning(disable:4324) // alignment sensitive to declspec
  17. #pragma warning(disable:4127) // condition expression is constant
  18. #pragma warning(disable:4115) // named type definition in parentheses
  19. #pragma warning(disable:4706) // assignment within conditional expression
  20. #pragma warning(disable:4206) // translation unit empty
  21. #include "ntos.h"
  22. #include "stdio.h"
  23. #include "stdlib.h"
  24. #include "zwapi.h"
  25. //
  26. // Private (internal) constant definitions.
  27. //
  28. // Priority increment value definitions
  29. //
  30. #define ALERT_INCREMENT 2 // Alerted unwait priority increment
  31. #define BALANCE_INCREMENT 10 // Balance set priority increment
  32. #define RESUME_INCREMENT 0 // Resume thread priority increment
  33. #define TIMER_EXPIRE_INCREMENT 0 // Timer expiration priority increment
  34. //
  35. // Define time critical priority class base.
  36. //
  37. #define TIME_CRITICAL_PRIORITY_BOUND 14
  38. //
  39. // Define NIL pointer value.
  40. //
  41. #define NIL (PVOID)NULL // Null pointer to void
  42. //
  43. // Define macros which are used in the kernel only
  44. //
  45. // Clear member in set
  46. //
  47. #define ClearMember(Member, Set) \
  48. Set = Set & (~((ULONG_PTR)1 << (Member)))
  49. //
  50. // Set member in set
  51. //
  52. #define SetMember(Member, Set) \
  53. Set = Set | ((ULONG_PTR)1 << (Member))
  54. #ifdef CAPKERN_SYNCH_POINTS
  55. VOID
  56. __cdecl
  57. CAP_Log_NInt_Clothed (
  58. IN ULONG Bcode_Bts_Scount,
  59. ...
  60. );
  61. #endif
  62. FORCEINLINE
  63. SCHAR
  64. KiComputeNewPriority (
  65. IN PKTHREAD Thread,
  66. IN SCHAR Adjustment
  67. )
  68. /*++
  69. Routine Description:
  70. This function computes a new priority for the specified thread by
  71. subtracting the priority decrement value plus the adjustment from
  72. the thread priority.
  73. Arguments:
  74. Thread - Supplies a pointer to a thread object.
  75. Adjustment - Supplies an additional adjustment value.
  76. Return Value:
  77. The new priority is returned as the function value.
  78. --*/
  79. {
  80. SCHAR Priority;
  81. //
  82. // Compute the new thread priority.
  83. //
  84. ASSERT((Thread->PriorityDecrement >= 0) && (Thread->PriorityDecrement <= Thread->Priority));
  85. ASSERT((Thread->Priority < LOW_REALTIME_PRIORITY) ? TRUE : (Thread->PriorityDecrement == 0));
  86. Priority = Thread->Priority;
  87. if (Priority < LOW_REALTIME_PRIORITY) {
  88. Priority = Priority - Thread->PriorityDecrement - Adjustment;
  89. if (Priority < Thread->BasePriority) {
  90. Priority = Thread->BasePriority;
  91. }
  92. Thread->PriorityDecrement = 0;
  93. }
  94. return Priority;
  95. }
  96. VOID
  97. FASTCALL
  98. KiExitDispatcher (
  99. IN KIRQL OldIrql
  100. );
  101. FORCEINLINE
  102. KIRQL
  103. FASTCALL
  104. KiAcquireSpinLockForDpc (
  105. IN PKSPIN_LOCK SpinLock
  106. )
  107. /*++
  108. Routine Description:
  109. This function conditionally raises IRQL to DISPATCH_LEVEL and acquires
  110. the specified spin lock.
  111. N.B. The conditional IRQL raise is predicated on whether a thread DPC
  112. is enabled.
  113. Arguments:
  114. SpinLock - Supplies the address of a spin lock.
  115. Return Value:
  116. If the IRQL is raised, then the previous IRQL is returned. Otherwise, zero
  117. is returned.
  118. --*/
  119. {
  120. KIRQL OldIrql;
  121. //
  122. // If the DPC thread is active, then raise IRQL and acquire the specified
  123. // spin lock. Otherwise, zero the previous IRQL and acquire the specified
  124. // spin lock at DISPATCH_LEVEL.
  125. //
  126. if (KeGetCurrentPrcb()->DpcThreadActive != FALSE) {
  127. KeAcquireSpinLock(SpinLock, &OldIrql);
  128. } else {
  129. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  130. OldIrql = DISPATCH_LEVEL;
  131. KeAcquireSpinLockAtDpcLevel(SpinLock);
  132. }
  133. return OldIrql;
  134. }
  135. FORCEINLINE
  136. VOID
  137. FASTCALL
  138. KiReleaseSpinLockForDpc (
  139. IN PKSPIN_LOCK SpinLock,
  140. IN KIRQL OldIrql
  141. )
  142. /*++
  143. Routine Description:
  144. This function releases the specified spin lock and conditionally lowers
  145. IRQL to its previous value.
  146. N.B. The conditional IRQL raise is predicated on whether a thread DPC
  147. is enabled.
  148. Arguments:
  149. SpinLock - Supplies the address of a spin lock.
  150. OldIrql - Supplies the previous IRQL.
  151. Return Value:
  152. None.
  153. --*/
  154. {
  155. //
  156. // If the DPC thread is active, then release the specified spin lock and
  157. // lower IRQL to its previous value. Otherwise, release specified spin
  158. // lock from DISPATCH_LEVEL.
  159. //
  160. if (KeGetCurrentPrcb()->DpcThreadActive != FALSE) {
  161. KeReleaseSpinLock(SpinLock, OldIrql);
  162. } else {
  163. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  164. KeReleaseSpinLockFromDpcLevel(SpinLock);
  165. }
  166. return;
  167. }
  168. FORCEINLINE
  169. VOID
  170. FASTCALL
  171. KiAcquireInStackQueuedSpinLockForDpc (
  172. IN PKSPIN_LOCK SpinLock,
  173. IN PKLOCK_QUEUE_HANDLE LockHandle
  174. )
  175. /*++
  176. Routine Description:
  177. This function conditionally raises IRQL to DISPATCH_LEVEL and acquires
  178. the specified in-stack spin lock.
  179. N.B. The conditional IRQL raise is predicated on whether a thread DPC
  180. is enabled.
  181. Arguments:
  182. SpinLock - Supplies the address of a spin lock.
  183. LockHandle - Supplies the address of a lock handle.
  184. Return Value:
  185. None.
  186. --*/
  187. {
  188. //
  189. // If the DPC thread is active, then raise IRQL and acquire the specified
  190. // in-stack spin lock. Otherwise, acquire the specified in-stack spin lock
  191. // at DISPATCH_LEVEL.
  192. //
  193. if (KeGetCurrentPrcb()->DpcThreadActive != FALSE) {
  194. KeAcquireInStackQueuedSpinLock(SpinLock, LockHandle);
  195. } else {
  196. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  197. KeAcquireInStackQueuedSpinLockAtDpcLevel(SpinLock, LockHandle);
  198. }
  199. return;
  200. }
  201. FORCEINLINE
  202. VOID
  203. FASTCALL
  204. KiReleaseInStackQueuedSpinLockForDpc (
  205. IN PKLOCK_QUEUE_HANDLE LockHandle
  206. )
  207. /*++
  208. Routine Description:
  209. This function releases the specified in-stack spin lock and conditionally
  210. lowers IRQL to its previous value.
  211. N.B. The conditional IRQL raise is predicated on whether a thread DPC
  212. is enabled.
  213. Arguments:
  214. LockHandle - Supplies the address of a lock handle.
  215. Return Value:
  216. None.
  217. --*/
  218. {
  219. //
  220. // If threaded DPCs are enabled, then release the specified in-stack
  221. // spin lock and lower IRQL to its previous value. Otherwise, release
  222. // the specified in-stack spin lock from DISPATCH_LEVEL.
  223. //
  224. if (KeGetCurrentPrcb()->DpcThreadActive != FALSE) {
  225. KeReleaseInStackQueuedSpinLock(LockHandle);
  226. } else {
  227. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  228. KeReleaseInStackQueuedSpinLockFromDpcLevel(LockHandle);
  229. }
  230. return;
  231. }
  232. FORCEINLINE
  233. VOID
  234. KzAcquireSpinLock (
  235. IN PKSPIN_LOCK SpinLock
  236. )
  237. /*++
  238. Routine Description:
  239. This function acquires a spin lock at the current IRQL.
  240. Arguments:
  241. SpinLock - Supplies a pointer to an spin lock.
  242. Return Value:
  243. None.
  244. --*/
  245. {
  246. #if !defined(NT_UP)
  247. #ifdef CAPKERN_SYNCH_POINTS
  248. ULONG Count = 0;
  249. CAP_Log_NInt_Clothed(0x00010101, (PVOID)SpinLock);
  250. #endif
  251. #if defined(_WIN64)
  252. #if defined(_AMD64_)
  253. while (InterlockedBitTestAndSet64((LONG64 *)SpinLock, 0)) {
  254. #else
  255. while (InterlockedExchangeAcquire64((PLONGLONG)SpinLock, 1) != 0) {
  256. #endif
  257. #else
  258. while (InterlockedExchange((PLONG)SpinLock, 1) != 0) {
  259. #endif
  260. do {
  261. #ifdef CAPKERN_SYNCH_POINTS
  262. Count += 1;
  263. #endif
  264. KeYieldProcessor();
  265. #if defined(_AMD64_)
  266. KeMemoryBarrierWithoutFence();
  267. } while (BitTest64((LONG64 *)SpinLock, 0));
  268. #else
  269. } while (*(volatile LONG_PTR *)SpinLock != 0);
  270. #endif
  271. }
  272. #ifdef CAPKERN_SYNCH_POINTS
  273. if (Count != 0) {
  274. CAP_Log_NInt_Clothed(0x00020102, Count, (PVOID)SpinLock);
  275. }
  276. #endif
  277. #else
  278. UNREFERENCED_PARAMETER(SpinLock);
  279. #endif // !defined(NT_UP)
  280. return;
  281. }
  282. FORCEINLINE
  283. VOID
  284. KiAcquirePrcbLock (
  285. IN PKPRCB Prcb
  286. )
  287. /*++
  288. Routine Description:
  289. This routine acquires the PRCB lock for the specified processor.
  290. N.B. This routine must be called from an IRQL greater than or equal to
  291. dispatch level.
  292. Arguments:
  293. Prcb - Supplies a pointer to a processor control block.
  294. Return Value:
  295. None.
  296. --*/
  297. {
  298. ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
  299. KzAcquireSpinLock(&Prcb->PrcbLock);
  300. return;
  301. }
  302. FORCEINLINE
  303. VOID
  304. KiAcquireTwoPrcbLocks (
  305. IN PKPRCB FirstPrcb,
  306. IN PKPRCB SecondPrcb
  307. )
  308. /*++
  309. Routine Description:
  310. This routine acquires the specified PRCB locks in address order.
  311. N.B. This routine must be called from an IRQL greater than or equal to
  312. dispatch level.
  313. Arguments:
  314. FirstPrcb - Supplies a pointer to a processor control block.
  315. SecondPrcb - Supplies a pointer to a processor control block.
  316. Return Value:
  317. None.
  318. --*/
  319. {
  320. ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
  321. if (FirstPrcb < SecondPrcb) {
  322. KzAcquireSpinLock(&FirstPrcb->PrcbLock);
  323. KzAcquireSpinLock(&SecondPrcb->PrcbLock);
  324. } else {
  325. if (FirstPrcb != SecondPrcb) {
  326. KzAcquireSpinLock(&SecondPrcb->PrcbLock);
  327. }
  328. KzAcquireSpinLock(&FirstPrcb->PrcbLock);
  329. }
  330. return;
  331. }
  332. FORCEINLINE
  333. VOID
  334. KiReleasePrcbLock (
  335. IN PKPRCB Prcb
  336. )
  337. /*++
  338. Routine Description:
  339. This routine release the PRCB lock for the specified processor.
  340. N.B. This routine must be called from an IRQL greater than or equal to
  341. dispatch level.
  342. Arguments:
  343. Prcb - Supplies a pointer to a processor control block.
  344. Return Value:
  345. None.
  346. --*/
  347. {
  348. ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
  349. #if !defined(NT_UP)
  350. #ifdef CAPKERN_SYNCH_POINTS
  351. CAP_Log_NInt_Clothed(0x00010107, (PVOID)&Prcb->PrcbLock);
  352. #endif
  353. ASSERT(Prcb->PrcbLock != 0);
  354. #if defined (_X86_)
  355. InterlockedAnd ((volatile LONG *)&Prcb->PrcbLock, 0);
  356. #else
  357. KeMemoryBarrierWithoutFence();
  358. *((volatile ULONG_PTR *)&Prcb->PrcbLock) = 0;
  359. #endif
  360. #else
  361. UNREFERENCED_PARAMETER(Prcb);
  362. #endif
  363. return;
  364. }
  365. FORCEINLINE
  366. VOID
  367. KiReleaseTwoPrcbLocks (
  368. IN PKPRCB FirstPrcb,
  369. IN PKPRCB SecondPrcb
  370. )
  371. /*++
  372. Routine Description:
  373. This routine releases the specified PRCB locks.
  374. N.B. This routine must be called from an IRQL greater than or equal to
  375. dispatch level.
  376. Arguments:
  377. FirstPrcb - Supplies a pointer to a processor control block.
  378. SecondPrcb - Supplies a pointer to a processor control block.
  379. Return Value:
  380. None.
  381. --*/
  382. {
  383. ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
  384. #if !defined(NT_UP)
  385. #ifdef CAPKERN_SYNCH_POINTS
  386. CAP_Log_NInt_Clothed(0x00010107, (PVOID)&FirstPrcb->PrcbLock);
  387. #endif
  388. KiReleasePrcbLock (FirstPrcb);
  389. if (FirstPrcb != SecondPrcb) {
  390. KiReleasePrcbLock (SecondPrcb);
  391. }
  392. #ifdef CAPKERN_SYNCH_POINTS
  393. CAP_Log_NInt_Clothed(0x00010107, (PVOID)&SecondPrcb->PrcbLock);
  394. #endif
  395. #else
  396. UNREFERENCED_PARAMETER(FirstPrcb);
  397. UNREFERENCED_PARAMETER(SecondPrcb);
  398. #endif
  399. return;
  400. }
  401. FORCEINLINE
  402. VOID
  403. KiAcquireThreadLock (
  404. IN PKTHREAD Thread
  405. )
  406. /*++
  407. Routine Description:
  408. This routine acquires the thread lock for the specified thread.
  409. N.B. This routine must be called from an IRQL greater than or equal to
  410. dispatch level.
  411. Arguments:
  412. Thread - Supplies a pointer to a thread object.
  413. Return Value:
  414. None.
  415. --*/
  416. {
  417. ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
  418. KzAcquireSpinLock(&Thread->ThreadLock);
  419. return;
  420. }
  421. FORCEINLINE
  422. VOID
  423. KiReleaseThreadLock (
  424. IN PKTHREAD Thread
  425. )
  426. /*++
  427. Routine Description:
  428. This routine releases the thread lock for the specified thread.
  429. N.B. This routine must be called from an IRQL greater than or equal to
  430. dispatch level.
  431. Arguments:
  432. Thread - Supplies a pointer to a thread object.
  433. Return Value:
  434. None.
  435. --*/
  436. {
  437. ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
  438. #if !defined(NT_UP)
  439. KeMemoryBarrierWithoutFence();
  440. #if defined (_X86_)
  441. InterlockedAnd ((volatile LONG *)&Thread->ThreadLock, 0);
  442. #else
  443. *((volatile ULONG_PTR *)&Thread->ThreadLock) = 0;
  444. #endif
  445. #else
  446. UNREFERENCED_PARAMETER(Thread);
  447. #endif
  448. return;
  449. }
  450. FORCEINLINE
  451. VOID
  452. KiClearIdleSummary (
  453. IN KAFFINITY Mask
  454. )
  455. /*++
  456. Routine Description:
  457. This function interlocked clears the specified mask into the current idle
  458. summary.
  459. Arguments:
  460. Mask - Supplies the affinity mask to merge.
  461. Return Value:
  462. None.
  463. --*/
  464. {
  465. #if defined(NT_UP)
  466. KiIdleSummary &= ~Mask;
  467. #else
  468. #if defined(_X86_)
  469. InterlockedAnd((volatile LONG *)&KiIdleSummary, ~(LONG)Mask);
  470. #else
  471. InterlockedAnd64((volatile LONG64 *)&KiIdleSummary, ~(LONG64)Mask);
  472. #endif
  473. #endif
  474. return;
  475. }
  476. FORCEINLINE
  477. VOID
  478. KiSetIdleSummary (
  479. IN KAFFINITY Mask
  480. )
  481. /*++
  482. Routine Description:
  483. This function interlocked merges the specified mask into the current idle
  484. summary.
  485. Arguments:
  486. Mask - Supplies the affinity mask to merge.
  487. Return Value:
  488. None.
  489. --*/
  490. {
  491. #if defined(NT_UP)
  492. KiIdleSummary |= Mask;
  493. #else
  494. #if defined(_X86_)
  495. InterlockedOr((volatile LONG *)&KiIdleSummary, (LONG)Mask);
  496. #else
  497. InterlockedOr64((volatile LONG64 *)&KiIdleSummary, (LONG64)Mask);
  498. #endif
  499. #endif
  500. return;
  501. }
  502. extern volatile KAFFINITY KiIdleSMTSummary;
  503. FORCEINLINE
  504. VOID
  505. KiClearSMTSummary (
  506. IN KAFFINITY Mask
  507. )
  508. /*++
  509. Routine Description:
  510. This function interlocked clears the specified mask into the current SMT
  511. summary.
  512. Arguments:
  513. Mask - Supplies the affinity mask to merge.
  514. Return Value:
  515. None.
  516. --*/
  517. {
  518. #if defined(NT_SMT)
  519. #if defined(_X86_)
  520. InterlockedAnd((volatile LONG *)&KiIdleSMTSummary, ~(LONG)Mask);
  521. #else
  522. InterlockedAnd64((volatile LONG64 *)&KiIdleSMTSummary, ~(LONG64)Mask);
  523. #endif
  524. #else
  525. UNREFERENCED_PARAMETER(Mask);
  526. #endif
  527. return;
  528. }
  529. FORCEINLINE
  530. VOID
  531. KiSetSMTSummary (
  532. IN KAFFINITY Mask
  533. )
  534. /*++
  535. Routine Description:
  536. This function interlocked merges the specified mask into the current SMT
  537. summary.
  538. Arguments:
  539. Mask - Supplies the affinity mask to merge.
  540. Return Value:
  541. None.
  542. --*/
  543. {
  544. #if defined(NT_SMT)
  545. #if defined(_X86_)
  546. InterlockedOr((volatile LONG *)&KiIdleSMTSummary, (LONG)Mask);
  547. #else
  548. InterlockedOr64((volatile LONG64 *)&KiIdleSMTSummary, (LONG64)Mask);
  549. #endif
  550. #else
  551. UNREFERENCED_PARAMETER(Mask);
  552. #endif
  553. return;
  554. }
  555. FORCEINLINE
  556. VOID
  557. KiBoostPriorityThread (
  558. IN PKTHREAD Thread,
  559. IN KPRIORITY Increment
  560. )
  561. /*++
  562. Routine Description:
  563. This function boosts the priority of the specified thread using
  564. the same algorithm used when a thread gets a boost from a wait
  565. operation.
  566. Arguments:
  567. Thread - Supplies a pointer to a dispatcher object of type thread.
  568. Increment - Supplies the priority increment that is to be applied to
  569. the thread's priority.
  570. Return Value:
  571. None.
  572. --*/
  573. {
  574. KPRIORITY NewPriority;
  575. PKPROCESS Process;
  576. //
  577. // If the thread is not a real time thread and does not already
  578. // have an unusual boost, then boost the priority as specified.
  579. //
  580. KiAcquireThreadLock(Thread);
  581. if ((Thread->Priority < LOW_REALTIME_PRIORITY) &&
  582. (Thread->PriorityDecrement == 0)) {
  583. NewPriority = Thread->BasePriority + Increment;
  584. if (NewPriority > Thread->Priority) {
  585. if (NewPriority >= LOW_REALTIME_PRIORITY) {
  586. NewPriority = LOW_REALTIME_PRIORITY - 1;
  587. }
  588. Process = Thread->ApcState.Process;
  589. Thread->Quantum = Process->ThreadQuantum;
  590. KiSetPriorityThread(Thread, NewPriority);
  591. }
  592. }
  593. KiReleaseThreadLock(Thread);
  594. return;
  595. }
  596. BOOLEAN
  597. KiHandleNmi (
  598. VOID
  599. );
  600. FORCEINLINE
  601. LOGICAL
  602. KiIsKernelStackSwappable (
  603. IN KPROCESSOR_MODE WaitMode,
  604. IN PKTHREAD Thread
  605. )
  606. /*++
  607. Routine Description:
  608. This function determines whether the kernel stack is swappabel for the
  609. the specified thread in a wait operation.
  610. Arguments:
  611. WaitMode - Supplies the processor mode of the wait operation.
  612. Thread - Supplies a pointer to a dispatcher object of type thread.
  613. Return Value:
  614. If the kernel stack for the specified thread is swappable, then TRUE is
  615. returned. Otherwise, FALSE is returned.
  616. --*/
  617. {
  618. return ((WaitMode != KernelMode) &&
  619. (Thread->EnableStackSwap != FALSE) &&
  620. (Thread->Priority < (LOW_REALTIME_PRIORITY + 9)));
  621. }
  622. VOID
  623. FASTCALL
  624. KiRetireDpcList (
  625. PKPRCB Prcb
  626. );
  627. FORCEINLINE
  628. VOID
  629. FASTCALL
  630. KiUnlockDispatcherDatabase (
  631. IN KIRQL OldIrql
  632. )
  633. /*++
  634. Routine Description:
  635. This function unlocks the dispatcher database and exits the scheduler.
  636. Arguments:
  637. OldIrql - Supplies the previous IRQL.
  638. Return Value:
  639. None.
  640. --*/
  641. {
  642. KiUnlockDispatcherDatabaseFromSynchLevel();
  643. KiExitDispatcher(OldIrql);
  644. return;
  645. }
  646. //
  647. // Private (internal) structure definitions.
  648. //
  649. // APC Parameter structure.
  650. //
  651. typedef struct _KAPC_RECORD {
  652. PKNORMAL_ROUTINE NormalRoutine;
  653. PVOID NormalContext;
  654. PVOID SystemArgument1;
  655. PVOID SystemArgument2;
  656. } KAPC_RECORD, *PKAPC_RECORD;
  657. //
  658. // Executive initialization.
  659. //
  660. VOID
  661. ExpInitializeExecutive (
  662. IN ULONG Number,
  663. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  664. );
  665. //
  666. // Interprocessor interrupt function definitions.
  667. //
  668. // Define immediate interprocessor commands.
  669. //
  670. #define IPI_APC 1 // APC interrupt request
  671. #define IPI_DPC 2 // DPC interrupt request
  672. #define IPI_FREEZE 4 // freeze execution request
  673. #define IPI_PACKET_READY 8 // packet ready request
  674. #define IPI_SYNCH_REQUEST 16 // reverse stall packet request
  675. //
  676. // Define interprocess interrupt types.
  677. //
  678. typedef ULONG KIPI_REQUEST;
  679. #if NT_INST
  680. #define IPI_INSTRUMENT_COUNT(a,b) KiIpiCounts[a].b++;
  681. #else
  682. #define IPI_INSTRUMENT_COUNT(a,b)
  683. #endif
  684. #if defined(_AMD64_) || defined(_IA64_)
  685. ULONG
  686. KiIpiProcessRequests (
  687. VOID
  688. );
  689. #endif // defined(_AMD64_) || defined(_IA64_)
  690. VOID
  691. FASTCALL
  692. KiIpiSend (
  693. IN KAFFINITY TargetProcessors,
  694. IN KIPI_REQUEST Request
  695. );
  696. VOID
  697. KiIpiSendPacket (
  698. IN KAFFINITY TargetProcessors,
  699. IN PKIPI_WORKER WorkerFunction,
  700. IN PVOID Parameter1,
  701. IN PVOID Parameter2,
  702. IN PVOID Parameter3
  703. );
  704. VOID
  705. FASTCALL
  706. KiIpiSignalPacketDone (
  707. IN PKIPI_CONTEXT SignalDone
  708. );
  709. FORCEINLINE
  710. VOID
  711. KiIpiStallOnPacketTargets (
  712. KAFFINITY TargetSet
  713. )
  714. /*++
  715. Routine Description:
  716. This function waits until the specified set of processors have signaled
  717. their completion of a requested function.
  718. N.B. The exact protocol used between the source and the target of an
  719. interprocessor request is not specified. Minimally the source
  720. must construct an appropriate packet and send the packet to a set
  721. of specified targets. Each target receives the address of the packet
  722. address as an argument, and minimally must clear the packet address
  723. when the mutually agreed upon protocol allows. The target has three
  724. options:
  725. 1. Capture necessary information, release the source by clearing
  726. the packet address, execute the request in parallel with the
  727. source, and return from the interrupt.
  728. 2. Execute the request in series with the source, release the
  729. source by clearing the packet address, and return from the
  730. interrupt.
  731. 3. Execute the request in series with the source, release the
  732. source, wait for a reply from the source based on a packet
  733. parameter, and return from the interrupt.
  734. This function is provided to enable the source to synchronize with the
  735. target for cases 2 and 3 above.
  736. N.B. There is no support for method 3 above.
  737. Arguments:
  738. TargetSet - Supplies the the target set of IPI processors.
  739. Return Value:
  740. None.
  741. --*/
  742. {
  743. KAFFINITY volatile *Barrier;
  744. PKPRCB Prcb;
  745. //
  746. // If there is one and only one bit set in the target set, then wait
  747. // on the target set. Otherwise, wait on the packet barrier.
  748. //
  749. Prcb = KeGetCurrentPrcb();
  750. Barrier = &Prcb->TargetSet;
  751. if ((TargetSet & (TargetSet - 1)) != 0) {
  752. Barrier = &Prcb->PacketBarrier;
  753. }
  754. while (*Barrier != 0) {
  755. KeYieldProcessor();
  756. }
  757. return;
  758. }
  759. //
  760. // Private (internal) function definitions.
  761. //
  762. VOID
  763. FASTCALL
  764. KiUnwaitThread (
  765. IN PKTHREAD Thread,
  766. IN LONG_PTR WaitStatus,
  767. IN KPRIORITY Increment
  768. );
  769. FORCEINLINE
  770. VOID
  771. KiActivateWaiterQueue (
  772. IN PRKQUEUE Queue
  773. )
  774. /*++
  775. Routine Description:
  776. This function is called when the current thread is about to enter a
  777. wait state and is currently processing a queue entry. The current
  778. number of threads processign entries for the queue is decrement and
  779. an attempt is made to activate another thread if the current count
  780. is less than the maximum count, there is a waiting thread, and the
  781. queue is not empty.
  782. N.B. It is possible that this function is called on one processor
  783. holding the dispatcher database lock while the state of the
  784. specified queue object is being modified on another processor
  785. while holding only the queue object lock. This does not cause
  786. a problem since holding the queue object lock ensures that
  787. there are no waiting threads.
  788. Arguments:
  789. Queue - Supplies a pointer to a dispatcher object of type event.
  790. Return Value:
  791. None.
  792. --*/
  793. {
  794. PRLIST_ENTRY Entry;
  795. PRKTHREAD Thread;
  796. PRKWAIT_BLOCK WaitBlock;
  797. PRLIST_ENTRY WaitEntry;
  798. //
  799. // Decrement the current count of active threads and check if another
  800. // thread can be activated. If the current number of active threads is
  801. // less than the target maximum number of threads, there is a entry in
  802. // in the queue, and a thread is waiting, then remove the entry from the
  803. // queue, decrement the number of entries in the queue, and unwait the
  804. // respectiive thread.
  805. //
  806. Queue->CurrentCount -= 1;
  807. if (Queue->CurrentCount < Queue->MaximumCount) {
  808. Entry = Queue->EntryListHead.Flink;
  809. WaitEntry = Queue->Header.WaitListHead.Blink;
  810. if ((Entry != &Queue->EntryListHead) &&
  811. (WaitEntry != &Queue->Header.WaitListHead)) {
  812. RemoveEntryList(Entry);
  813. Entry->Flink = NULL;
  814. Queue->Header.SignalState -= 1;
  815. WaitBlock = CONTAINING_RECORD(WaitEntry, KWAIT_BLOCK, WaitListEntry);
  816. Thread = WaitBlock->Thread;
  817. KiUnwaitThread(Thread, (LONG_PTR)Entry, 0);
  818. }
  819. }
  820. return;
  821. }
  822. VOID
  823. KiAllProcessorsStarted (
  824. VOID
  825. );
  826. VOID
  827. KiApcInterrupt (
  828. VOID
  829. );
  830. NTSTATUS
  831. KiCallUserMode (
  832. IN PVOID *OutputBuffer,
  833. IN PULONG OutputLength
  834. );
  835. typedef struct {
  836. ULONGLONG Adjustment;
  837. LARGE_INTEGER NewCount;
  838. volatile LONG KiNumber;
  839. volatile LONG HalNumber;
  840. volatile LONG Barrier;
  841. } ADJUST_INTERRUPT_TIME_CONTEXT, *PADJUST_INTERRUPT_TIME_CONTEXT;
  842. VOID
  843. KiCalibrateTimeAdjustment (
  844. PADJUST_INTERRUPT_TIME_CONTEXT Adjust
  845. );
  846. VOID
  847. KiChainedDispatch (
  848. VOID
  849. );
  850. #if DBG
  851. VOID
  852. KiCheckTimerTable (
  853. IN ULARGE_INTEGER SystemTime
  854. );
  855. #endif
  856. LARGE_INTEGER
  857. KiComputeReciprocal (
  858. IN LONG Divisor,
  859. OUT PCCHAR Shift
  860. );
  861. extern LARGE_INTEGER KiTimeIncrementReciprocal;
  862. extern CCHAR KiTimeIncrementShiftCount;
  863. #if defined(_AMD64_)
  864. __forceinline
  865. ULONG
  866. KiComputeTimerTableIndex (
  867. IN LARGE_INTEGER Interval,
  868. IN LARGE_INTEGER CurrentTime,
  869. IN PKTIMER Timer
  870. )
  871. /*++
  872. Routine Description:
  873. This function computes the timer table index for the specified timer
  874. object and stores the due time in the timer object.
  875. N.B. The interval parameter is guaranteed to be negative since it is
  876. expressed as relative time.
  877. The formula for due time calculation is:
  878. Due Time = Current Time - Interval
  879. The formula for the index calculation is:
  880. Index = (Due Time / Maximum time increment) & (Table Size - 1)
  881. The time increment division is performed using reciprocal multiplication.
  882. N.B. The maximum time increment determines the interval corresponding
  883. to a tick.
  884. Arguments:
  885. Interval - Supplies the relative time at which the timer is to
  886. expire.
  887. CurrentCount - Supplies the current system tick count.
  888. Timer - Supplies a pointer to a dispatch object of type timer.
  889. Return Value:
  890. The time table index is returned as the function value and the due
  891. time is stored in the timer object.
  892. --*/
  893. {
  894. ULONG64 DueTime;
  895. ULONG64 HighTime;
  896. ULONG Index;
  897. //
  898. // Compute the due time of the timer.
  899. //
  900. DueTime = CurrentTime.QuadPart - Interval.QuadPart;
  901. Timer->DueTime.QuadPart = DueTime;
  902. //
  903. // Compute the timer table index.
  904. //
  905. HighTime = UnsignedMultiplyHigh(DueTime,
  906. KiTimeIncrementReciprocal.QuadPart);
  907. Index = (ULONG)(HighTime >> KiTimeIncrementShiftCount);
  908. return (Index & (TIMER_TABLE_SIZE - 1));
  909. }
  910. #else
  911. ULONG
  912. KiComputeTimerTableIndex (
  913. IN LARGE_INTEGER Interval,
  914. IN LARGE_INTEGER CurrentCount,
  915. IN PKTIMER Timer
  916. );
  917. #endif
  918. PLARGE_INTEGER
  919. FASTCALL
  920. KiComputeWaitInterval (
  921. IN PLARGE_INTEGER OriginalTime,
  922. IN PLARGE_INTEGER DueTime,
  923. IN OUT PLARGE_INTEGER NewTime
  924. );
  925. NTSTATUS
  926. KiContinue (
  927. IN PCONTEXT ContextRecord,
  928. IN PKEXCEPTION_FRAME ExceptionFrame,
  929. IN PKTRAP_FRAME TrapFrame
  930. );
  931. VOID
  932. KiDeliverApc (
  933. IN KPROCESSOR_MODE PreviousMode,
  934. IN PKEXCEPTION_FRAME ExceptionFrame,
  935. IN PKTRAP_FRAME TrapFrame
  936. );
  937. VOID
  938. KiDispatchException (
  939. IN PEXCEPTION_RECORD ExceptionRecord,
  940. IN PKEXCEPTION_FRAME ExceptionFrame,
  941. IN PKTRAP_FRAME TrapFrame,
  942. IN KPROCESSOR_MODE PreviousMode,
  943. IN BOOLEAN FirstChance
  944. );
  945. VOID
  946. KiExecuteDpc (
  947. IN PVOID Context
  948. );
  949. KCONTINUE_STATUS
  950. KiSetDebugProcessor (
  951. IN PKTRAP_FRAME TrapFrame,
  952. IN PKEXCEPTION_FRAME ExceptionFrame,
  953. IN KPROCESSOR_MODE PreviousMode
  954. );
  955. ULONG
  956. KiCopyInformation (
  957. IN OUT PEXCEPTION_RECORD ExceptionRecord1,
  958. IN PEXCEPTION_RECORD ExceptionRecord2
  959. );
  960. VOID
  961. KiDispatchInterrupt (
  962. VOID
  963. );
  964. VOID
  965. FASTCALL
  966. KiDeferredReadyThread (
  967. IN PKTHREAD Thread
  968. );
  969. PKTHREAD
  970. FASTCALL
  971. KiFindReadyThread (
  972. IN ULONG Processor,
  973. IN PKPRCB Prcb
  974. );
  975. VOID
  976. KiFloatingDispatch (
  977. VOID
  978. );
  979. FORCEINLINE
  980. VOID
  981. KiSetTbFlushTimeStampBusy (
  982. VOID
  983. )
  984. /*++
  985. Routine Description:
  986. This function sets the TB flush time stamp busy by setting the high
  987. order bit of the TB flush time stamp. All readers of the time stamp
  988. value will spin until the bit is cleared.
  989. Arguments:
  990. None.
  991. Return Value:
  992. None.
  993. --*/
  994. {
  995. LONG Value;
  996. //
  997. // While the TB flush time stamp counter is being updated the high
  998. // order bit of the time stamp value is set. Otherwise, the bit is
  999. // clear.
  1000. //
  1001. do {
  1002. do {
  1003. } while ((Value = KiTbFlushTimeStamp) < 0);
  1004. //
  1005. // Attempt to set the high order bit.
  1006. //
  1007. } while (InterlockedCompareExchange((PLONG)&KiTbFlushTimeStamp,
  1008. Value | 0x80000000,
  1009. Value) != Value);
  1010. return;
  1011. }
  1012. FORCEINLINE
  1013. VOID
  1014. KiClearTbFlushTimeStampBusy (
  1015. VOID
  1016. )
  1017. /*++
  1018. Routine Description:
  1019. This function ckears the TB flush time stamp busy by clearing the high
  1020. order bit of the TB flush time stamp and incrementing the low 32-bit
  1021. value.
  1022. N.B. It is assumed that the high order bit of the time stamp value
  1023. is set on entry to this routine.
  1024. Arguments:
  1025. None.
  1026. Return Value:
  1027. None.
  1028. --*/
  1029. {
  1030. LONG Value;
  1031. //
  1032. // Get the current TB flush time stamp value, compute the next value,
  1033. // and store the result clearing the busy bit.
  1034. //
  1035. Value = (KiTbFlushTimeStamp + 1) & 0x7fffffff;
  1036. InterlockedExchange((PLONG)&KiTbFlushTimeStamp, Value);
  1037. return;
  1038. }
  1039. PULONG
  1040. KiGetUserModeStackAddress (
  1041. VOID
  1042. );
  1043. VOID
  1044. KiInitializeContextThread (
  1045. IN PKTHREAD Thread,
  1046. IN PKSYSTEM_ROUTINE SystemRoutine,
  1047. IN PKSTART_ROUTINE StartRoutine OPTIONAL,
  1048. IN PVOID StartContext OPTIONAL,
  1049. IN PCONTEXT ContextFrame OPTIONAL
  1050. );
  1051. VOID
  1052. KiInitializeKernel (
  1053. IN PKPROCESS Process,
  1054. IN PKTHREAD Thread,
  1055. IN PVOID IdleStack,
  1056. IN PKPRCB Prcb,
  1057. IN CCHAR Number,
  1058. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  1059. );
  1060. VOID
  1061. KiInitSpinLocks (
  1062. PKPRCB Prcb,
  1063. ULONG Number
  1064. );
  1065. VOID
  1066. KiInitSystem (
  1067. VOID
  1068. );
  1069. BOOLEAN
  1070. KiInitMachineDependent (
  1071. VOID
  1072. );
  1073. VOID
  1074. KiInitializeUserApc (
  1075. IN PKEXCEPTION_FRAME ExceptionFrame,
  1076. IN PKTRAP_FRAME TrapFrame,
  1077. IN PKNORMAL_ROUTINE NormalRoutine,
  1078. IN PVOID NormalContext,
  1079. IN PVOID SystemArgument1,
  1080. IN PVOID SystemArgument2
  1081. );
  1082. FORCEINLINE
  1083. VOID
  1084. FASTCALL
  1085. KiInsertDeferredReadyList (
  1086. IN PKTHREAD Thread
  1087. )
  1088. /*++
  1089. Routine Description:
  1090. This function pushes an entry onto the current processor's deferred
  1091. ready list.
  1092. Arguments:
  1093. Thread - Supplies a pointer to a thread object.
  1094. Return Value:
  1095. None.
  1096. --*/
  1097. {
  1098. //
  1099. // On the MP system, insert the specified thread in the deferred ready
  1100. // list. On the UP system, ready the thread immediately.
  1101. //
  1102. #if defined(NT_UP)
  1103. Thread->State = DeferredReady;
  1104. Thread->DeferredProcessor = 0;
  1105. KiDeferredReadyThread(Thread);
  1106. #else
  1107. PKPRCB Prcb;
  1108. Prcb = KeGetCurrentPrcb();
  1109. Thread->State = DeferredReady;
  1110. Thread->DeferredProcessor = Prcb->Number;
  1111. PushEntryList(&Prcb->DeferredReadyListHead,
  1112. &Thread->SwapListEntry);
  1113. #endif
  1114. return;
  1115. }
  1116. LONG
  1117. FASTCALL
  1118. KiInsertQueue (
  1119. IN PKQUEUE Queue,
  1120. IN PLIST_ENTRY Entry,
  1121. IN BOOLEAN Head
  1122. );
  1123. VOID
  1124. FASTCALL
  1125. KiInsertQueueApc (
  1126. IN PKAPC Apc,
  1127. IN KPRIORITY Increment
  1128. );
  1129. LOGICAL
  1130. FASTCALL
  1131. KiInsertTreeTimer (
  1132. IN PKTIMER Timer,
  1133. IN LARGE_INTEGER Interval
  1134. );
  1135. VOID
  1136. KiInterruptDispatch (
  1137. VOID
  1138. );
  1139. VOID
  1140. KiInterruptDispatchRaise (
  1141. IN PKINTERRUPT Interrupt
  1142. );
  1143. VOID
  1144. KiInterruptDispatchSame (
  1145. IN PKINTERRUPT Interrupt
  1146. );
  1147. VOID
  1148. KiPassiveRelease (
  1149. VOID
  1150. );
  1151. VOID
  1152. FASTCALL
  1153. KiProcessDeferredReadyList (
  1154. IN PKPRCB CurrentPrcb
  1155. );
  1156. VOID
  1157. KiQuantumEnd (
  1158. VOID
  1159. );
  1160. NTSTATUS
  1161. KiRaiseException (
  1162. IN PEXCEPTION_RECORD ExceptionRecord,
  1163. IN PCONTEXT ContextRecord,
  1164. IN PKEXCEPTION_FRAME ExceptionFrame,
  1165. IN PKTRAP_FRAME TrapFrame,
  1166. IN BOOLEAN FirstChance
  1167. );
  1168. VOID
  1169. FASTCALL
  1170. KiReadyThread (
  1171. IN PKTHREAD Thread
  1172. );
  1173. FORCEINLINE
  1174. VOID
  1175. KxQueueReadyThread (
  1176. IN PKTHREAD Thread,
  1177. IN PKPRCB Prcb
  1178. )
  1179. /*++
  1180. Routine Description:
  1181. This function inserts the previously current thread in the current
  1182. processor's dispatcher ready queues if the thread can run on the
  1183. curent processor. Otherwise, the specified thread is readied for
  1184. execution.
  1185. N.B. This function is called with the current PRCB lock held and returns
  1186. with the PRCB lock not held.
  1187. Arguments:
  1188. Thread - Supplies a pointer to a thread object.
  1189. Prcb - Supplies a pointer to a the current PRCB.
  1190. Return Value:
  1191. None.
  1192. --*/
  1193. {
  1194. BOOLEAN Preempted;
  1195. KPRIORITY Priority;
  1196. ASSERT(Prcb == KeGetCurrentPrcb());
  1197. ASSERT(Thread->State == Running);
  1198. ASSERT(Thread->NextProcessor == Prcb->Number);
  1199. //
  1200. // If the thread can run on the specified processor, then insert the
  1201. // thread in the appropriate dispatcher ready queue for the specified
  1202. // processor and release the specified PRCB lock. Otherwise, release
  1203. // the specified PRCB lock and ready the thread for execution.
  1204. //
  1205. #if !defined(NT_UP)
  1206. if ((Thread->Affinity & Prcb->SetMember) != 0) {
  1207. #endif
  1208. Thread->State = Ready;
  1209. Preempted = Thread->Preempted;
  1210. Thread->Preempted = FALSE;
  1211. Thread->WaitTime = KiQueryLowTickCount();
  1212. Priority = Thread->Priority;
  1213. ASSERT((Priority >= 0) && (Priority <= HIGH_PRIORITY));
  1214. if (Preempted != FALSE) {
  1215. InsertHeadList(&Prcb->DispatcherReadyListHead[Priority],
  1216. &Thread->WaitListEntry);
  1217. } else {
  1218. InsertTailList(&Prcb->DispatcherReadyListHead[Priority],
  1219. &Thread->WaitListEntry);
  1220. }
  1221. Prcb->ReadySummary |= PRIORITY_MASK(Priority);
  1222. ASSERT(Priority == Thread->Priority);
  1223. KiReleasePrcbLock(Prcb);
  1224. #if !defined(NT_UP)
  1225. } else {
  1226. Thread->State = DeferredReady;
  1227. Thread->DeferredProcessor = Prcb->Number;
  1228. KiReleasePrcbLock(Prcb);
  1229. KiDeferredReadyThread(Thread);
  1230. }
  1231. #endif
  1232. return;
  1233. }
  1234. LOGICAL
  1235. FASTCALL
  1236. KiReinsertTreeTimer (
  1237. IN PKTIMER Timer,
  1238. IN ULARGE_INTEGER DueTime
  1239. );
  1240. #if DBG
  1241. #define KiRemoveTreeTimer(Timer) \
  1242. (Timer)->Header.Inserted = FALSE; \
  1243. RemoveEntryList(&(Timer)->TimerListEntry); \
  1244. (Timer)->TimerListEntry.Flink = NULL; \
  1245. (Timer)->TimerListEntry.Blink = NULL
  1246. #else
  1247. #define KiRemoveTreeTimer(Timer) \
  1248. (Timer)->Header.Inserted = FALSE; \
  1249. RemoveEntryList(&(Timer)->TimerListEntry)
  1250. #endif
  1251. #if defined(NT_UP)
  1252. #define KiRequestApcInterrupt(Processor) KiRequestSoftwareInterrupt(APC_LEVEL)
  1253. #else
  1254. #define KiRequestApcInterrupt(Processor) \
  1255. if (KeGetCurrentProcessorNumber() == Processor) { \
  1256. KiRequestSoftwareInterrupt(APC_LEVEL); \
  1257. } else { \
  1258. KiIpiSend(AFFINITY_MASK(Processor), IPI_APC); \
  1259. }
  1260. #endif
  1261. #if defined(NT_UP)
  1262. #define KiRequestDispatchInterrupt(Processor)
  1263. #else
  1264. #define KiRequestDispatchInterrupt(Processor) \
  1265. if (KeGetCurrentProcessorNumber() != Processor) { \
  1266. KiIpiSend(AFFINITY_MASK(Processor), IPI_DPC); \
  1267. }
  1268. #endif
  1269. PKTHREAD
  1270. FASTCALL
  1271. KiSelectNextThread (
  1272. IN PKPRCB Prcb
  1273. );
  1274. KAFFINITY
  1275. FASTCALL
  1276. KiSetAffinityThread (
  1277. IN PKTHREAD Thread,
  1278. IN KAFFINITY Affinity
  1279. );
  1280. FORCEINLINE
  1281. VOID
  1282. KiSetContextSwapBusy (
  1283. IN PKTHREAD Thread
  1284. )
  1285. /*++
  1286. Routine Description:
  1287. This routine sets context swap busy for the specified thread.
  1288. Arguments:
  1289. Thread - Supplies a pointer to a dispatcher object of type thread.
  1290. Return Value:
  1291. None.
  1292. --*/
  1293. {
  1294. #if !defined(NT_UP)
  1295. ASSERT(Thread->SwapBusy == FALSE);
  1296. Thread->SwapBusy = TRUE;
  1297. #else
  1298. UNREFERENCED_PARAMETER(Thread);
  1299. #endif
  1300. return;
  1301. }
  1302. FORCEINLINE
  1303. VOID
  1304. KiSetContextSwapIdle (
  1305. IN PKTHREAD Thread
  1306. )
  1307. /*++
  1308. Routine Description:
  1309. This routine sets context swap idle for the specified thread.
  1310. Arguments:
  1311. Thread - Supplies a pointer to a dispatcher object of type thread.
  1312. Return Value:
  1313. None.
  1314. --*/
  1315. {
  1316. #if !defined(NT_UP)
  1317. ASSERT(Thread->SwapBusy == TRUE);
  1318. Thread->SwapBusy = FALSE;
  1319. #else
  1320. UNREFERENCED_PARAMETER(Thread);
  1321. #endif
  1322. return;
  1323. }
  1324. VOID
  1325. KiSetSystemTime (
  1326. IN PLARGE_INTEGER NewTime,
  1327. OUT PLARGE_INTEGER OldTime
  1328. );
  1329. VOID
  1330. KiSuspendNop (
  1331. IN struct _KAPC *Apc,
  1332. IN OUT PKNORMAL_ROUTINE *NormalRoutine,
  1333. IN OUT PVOID *NormalContext,
  1334. IN OUT PVOID *SystemArgument1,
  1335. IN OUT PVOID *SystemArgument2
  1336. );
  1337. VOID
  1338. KiSuspendRundown (
  1339. IN PKAPC Apc
  1340. );
  1341. VOID
  1342. KiSuspendThread (
  1343. IN PVOID NormalContext,
  1344. IN PVOID SystemArgument1,
  1345. IN PVOID SystemArgument2
  1346. );
  1347. BOOLEAN
  1348. KiSwapProcess (
  1349. IN PKPROCESS NewProcess,
  1350. IN PKPROCESS OldProcess
  1351. );
  1352. LONG_PTR
  1353. FASTCALL
  1354. KiSwapThread (
  1355. IN PKTHREAD OldThread,
  1356. IN PKPRCB CurrentPrcb
  1357. );
  1358. VOID
  1359. KiThreadStartup (
  1360. IN PVOID StartContext
  1361. );
  1362. VOID
  1363. KiTimerExpiration (
  1364. IN PKDPC Dpc,
  1365. IN PVOID DeferredContext,
  1366. IN PVOID SystemArgument1,
  1367. IN PVOID SystemArgument2
  1368. );
  1369. VOID
  1370. FASTCALL
  1371. KiTimerListExpire (
  1372. IN PLIST_ENTRY ExpiredListHead,
  1373. IN KIRQL OldIrql
  1374. );
  1375. VOID
  1376. KiUnexpectedInterrupt (
  1377. VOID
  1378. );
  1379. FORCEINLINE
  1380. VOID
  1381. FASTCALL
  1382. KiUnlinkThread (
  1383. IN PRKTHREAD Thread,
  1384. IN LONG_PTR WaitStatus
  1385. )
  1386. /*++
  1387. Routine Description:
  1388. This function unlinks a thread from the appropriate wait queues and sets
  1389. the thread's wait completion status.
  1390. Arguments:
  1391. Thread - Supplies a pointer to a dispatcher object of type thread.
  1392. WaitStatus - Supplies the wait completion status.
  1393. Return Value:
  1394. None.
  1395. --*/
  1396. {
  1397. PKQUEUE Queue;
  1398. PKTIMER Timer;
  1399. PRKWAIT_BLOCK WaitBlock;
  1400. //
  1401. // Set wait completion status, remove wait blocks from object wait
  1402. // lists, and remove thread from wait list.
  1403. //
  1404. Thread->WaitStatus |= WaitStatus;
  1405. WaitBlock = Thread->WaitBlockList;
  1406. do {
  1407. RemoveEntryList(&WaitBlock->WaitListEntry);
  1408. WaitBlock = WaitBlock->NextWaitBlock;
  1409. } while (WaitBlock != Thread->WaitBlockList);
  1410. if (Thread->WaitListEntry.Flink != NULL) {
  1411. RemoveEntryList(&Thread->WaitListEntry);
  1412. }
  1413. //
  1414. // If thread timer is still active, then cancel thread timer.
  1415. //
  1416. Timer = &Thread->Timer;
  1417. if (Timer->Header.Inserted != FALSE) {
  1418. KiRemoveTreeTimer(Timer);
  1419. }
  1420. //
  1421. // If the thread is processing a queue entry, then increment the
  1422. // count of currently active threads.
  1423. //
  1424. Queue = Thread->Queue;
  1425. if (Queue != NULL) {
  1426. Queue->CurrentCount += 1;
  1427. }
  1428. return;
  1429. }
  1430. VOID
  1431. KiUserApcDispatcher (
  1432. IN PVOID NormalContext,
  1433. IN PVOID SystemArgument1,
  1434. IN PVOID SystemArgument2,
  1435. IN PKNORMAL_ROUTINE NormalRoutine
  1436. );
  1437. VOID
  1438. KiUserExceptionDispatcher (
  1439. IN PEXCEPTION_RECORD ExceptionRecord,
  1440. IN PCONTEXT ContextFrame
  1441. );
  1442. VOID
  1443. KiVerifyReadySummary (
  1444. PKPRCB Prcb
  1445. );
  1446. BOOLEAN
  1447. FASTCALL
  1448. KiSwapContext (
  1449. IN PKTHREAD OldThread,
  1450. IN PKTHREAD NewThread
  1451. );
  1452. //
  1453. // VOID
  1454. // FASTCALL
  1455. // KiWaitSatisfyAny (
  1456. // IN PKMUTANT Object,
  1457. // IN PKTHREAD Thread
  1458. // )
  1459. //
  1460. //
  1461. // Routine Description:
  1462. //
  1463. // This function satisfies a wait for any type of object and performs
  1464. // any side effects that are necessary.
  1465. //
  1466. // Arguments:
  1467. //
  1468. // Object - Supplies a pointer to a dispatcher object.
  1469. //
  1470. // Thread - Supplies a pointer to a dispatcher object of type thread.
  1471. //
  1472. // Return Value:
  1473. //
  1474. // None.
  1475. //
  1476. #define KiWaitSatisfyAny(_Object_, _Thread_) { \
  1477. if (((_Object_)->Header.Type & DISPATCHER_OBJECT_TYPE_MASK) == EventSynchronizationObject) { \
  1478. (_Object_)->Header.SignalState = 0; \
  1479. \
  1480. } else if ((_Object_)->Header.Type == SemaphoreObject) { \
  1481. (_Object_)->Header.SignalState -= 1; \
  1482. \
  1483. } else if ((_Object_)->Header.Type == MutantObject) { \
  1484. (_Object_)->Header.SignalState -= 1; \
  1485. if ((_Object_)->Header.SignalState == 0) { \
  1486. (_Thread_)->KernelApcDisable = (_Thread_)->KernelApcDisable - (_Object_)->ApcDisable; \
  1487. (_Object_)->OwnerThread = (_Thread_); \
  1488. if ((_Object_)->Abandoned == TRUE) { \
  1489. (_Object_)->Abandoned = FALSE; \
  1490. (_Thread_)->WaitStatus = STATUS_ABANDONED; \
  1491. } \
  1492. \
  1493. InsertHeadList((_Thread_)->MutantListHead.Blink, \
  1494. &(_Object_)->MutantListEntry); \
  1495. } \
  1496. } \
  1497. }
  1498. //
  1499. // VOID
  1500. // FASTCALL
  1501. // KiWaitSatisfyMutant (
  1502. // IN PKMUTANT Object,
  1503. // IN PKTHREAD Thread
  1504. // )
  1505. //
  1506. //
  1507. // Routine Description:
  1508. //
  1509. // This function satisfies a wait for a mutant object.
  1510. //
  1511. // Arguments:
  1512. //
  1513. // Object - Supplies a pointer to a dispatcher object.
  1514. //
  1515. // Thread - Supplies a pointer to a dispatcher object of type thread.
  1516. //
  1517. // Return Value:
  1518. //
  1519. // None.
  1520. //
  1521. #define KiWaitSatisfyMutant(_Object_, _Thread_) { \
  1522. (_Object_)->Header.SignalState -= 1; \
  1523. if ((_Object_)->Header.SignalState == 0) { \
  1524. (_Thread_)->KernelApcDisable = (_Thread_)->KernelApcDisable - (_Object_)->ApcDisable; \
  1525. (_Object_)->OwnerThread = (_Thread_); \
  1526. if ((_Object_)->Abandoned == TRUE) { \
  1527. (_Object_)->Abandoned = FALSE; \
  1528. (_Thread_)->WaitStatus = STATUS_ABANDONED; \
  1529. } \
  1530. \
  1531. InsertHeadList((_Thread_)->MutantListHead.Blink, \
  1532. &(_Object_)->MutantListEntry); \
  1533. } \
  1534. }
  1535. //
  1536. // VOID
  1537. // FASTCALL
  1538. // KiWaitSatisfyOther (
  1539. // IN PKMUTANT Object
  1540. // )
  1541. //
  1542. //
  1543. // Routine Description:
  1544. //
  1545. // This function satisfies a wait for any type of object except a mutant
  1546. // and performs any side effects that are necessary.
  1547. //
  1548. // Arguments:
  1549. //
  1550. // Object - Supplies a pointer to a dispatcher object.
  1551. //
  1552. // Return Value:
  1553. //
  1554. // None.
  1555. //
  1556. #define KiWaitSatisfyOther(_Object_) { \
  1557. if (((_Object_)->Header.Type & DISPATCHER_OBJECT_TYPE_MASK) == EventSynchronizationObject) { \
  1558. (_Object_)->Header.SignalState = 0; \
  1559. \
  1560. } else if ((_Object_)->Header.Type == SemaphoreObject) { \
  1561. (_Object_)->Header.SignalState -= 1; \
  1562. \
  1563. } \
  1564. }
  1565. VOID
  1566. FASTCALL
  1567. KiWaitTest (
  1568. IN PVOID Object,
  1569. IN KPRIORITY Increment
  1570. );
  1571. FORCEINLINE
  1572. VOID
  1573. KiWaitTestSynchronizationObject (
  1574. IN PVOID Object,
  1575. IN KPRIORITY Increment
  1576. )
  1577. /*++
  1578. Routine Description:
  1579. This function tests if a wait can be satisfied when a synchronization
  1580. dispatcher object attains a state of signaled. Synchronization objects
  1581. include synchronization events and synchronization timers.
  1582. Arguments:
  1583. Object - Supplies a pointer to an event object.
  1584. Increment - Supplies the priority increment.
  1585. Return Value:
  1586. None.
  1587. --*/
  1588. {
  1589. PKEVENT Event = Object;
  1590. PLIST_ENTRY ListHead;
  1591. PRKTHREAD Thread;
  1592. PRKWAIT_BLOCK WaitBlock;
  1593. PLIST_ENTRY WaitEntry;
  1594. //
  1595. // As long as the signal state of the specified event is signaled and
  1596. // there are waiters in the event wait list, then try to satisfy a wait.
  1597. //
  1598. ListHead = &Event->Header.WaitListHead;
  1599. ASSERT(IsListEmpty(&Event->Header.WaitListHead) == FALSE);
  1600. WaitEntry = ListHead->Flink;
  1601. do {
  1602. //
  1603. // Get the address of the wait block and the thread doing the wait.
  1604. //
  1605. WaitBlock = CONTAINING_RECORD(WaitEntry, KWAIT_BLOCK, WaitListEntry);
  1606. Thread = WaitBlock->Thread;
  1607. //
  1608. // If the wait type is wait any, then satisfy the wait, unwait the
  1609. // thread with the wait key status, and exit loop. Otherwise, unwait
  1610. // the thread with a kernel APC status and continue the loop.
  1611. //
  1612. if (WaitBlock->WaitType == WaitAny) {
  1613. Event->Header.SignalState = 0;
  1614. KiUnwaitThread(Thread, (NTSTATUS)WaitBlock->WaitKey, Increment);
  1615. break;
  1616. }
  1617. KiUnwaitThread(Thread, STATUS_KERNEL_APC, Increment);
  1618. WaitEntry = ListHead->Flink;
  1619. } while (WaitEntry != ListHead);
  1620. return;
  1621. }
  1622. FORCEINLINE
  1623. VOID
  1624. KiWaitTestWithoutSideEffects (
  1625. IN PVOID Object,
  1626. IN KPRIORITY Increment
  1627. )
  1628. /*++
  1629. Routine Description:
  1630. This function tests if a wait can be satisfied when a dispatcher object
  1631. without side effects attains a state of signaled. Dispatcher objects
  1632. that have no side effects when a wait is satisfied include notification
  1633. events, notification timers, processes, and threads.
  1634. Arguments:
  1635. Object - Supplies a pointer to a dispatcher object that has no side
  1636. effects when a wait is satisfied.
  1637. Increment - Supplies the priority increment.
  1638. Return Value:
  1639. None.
  1640. --*/
  1641. {
  1642. PKEVENT Event = Object;
  1643. PLIST_ENTRY ListHead;
  1644. PRKTHREAD Thread;
  1645. PRKWAIT_BLOCK WaitBlock;
  1646. PLIST_ENTRY WaitEntry;
  1647. //
  1648. // Empty the entire list of waiters since the specified object has
  1649. // no side effects when a wait is satisfied.
  1650. //
  1651. ListHead = &Event->Header.WaitListHead;
  1652. ASSERT(IsListEmpty(&Event->Header.WaitListHead) == FALSE);
  1653. WaitEntry = ListHead->Flink;
  1654. do {
  1655. //
  1656. // Get the address of the wait block and the thread doing the wait.
  1657. //
  1658. WaitBlock = CONTAINING_RECORD(WaitEntry, KWAIT_BLOCK, WaitListEntry);
  1659. Thread = WaitBlock->Thread;
  1660. //
  1661. // If the wait type is wait any, then unwait the thread with the
  1662. // wait key status. Otherwise, unwait the thread with a kernel APC
  1663. // status.
  1664. //
  1665. if (WaitBlock->WaitType == WaitAny) {
  1666. KiUnwaitThread(Thread, (NTSTATUS)WaitBlock->WaitKey, Increment);
  1667. } else {
  1668. KiUnwaitThread(Thread, STATUS_KERNEL_APC, Increment);
  1669. }
  1670. WaitEntry = ListHead->Flink;
  1671. } while (WaitEntry != ListHead);
  1672. return;
  1673. }
  1674. VOID
  1675. KiFreezeTargetExecution (
  1676. IN PKTRAP_FRAME TrapFrame,
  1677. IN PKEXCEPTION_FRAME ExceptionFrame
  1678. );
  1679. VOID
  1680. KiPollFreezeExecution (
  1681. VOID
  1682. );
  1683. VOID
  1684. KiSaveProcessorState (
  1685. IN PKTRAP_FRAME TrapFrame,
  1686. IN PKEXCEPTION_FRAME ExceptionFrame
  1687. );
  1688. VOID
  1689. KiSaveProcessorControlState (
  1690. IN PKPROCESSOR_STATE ProcessorState
  1691. );
  1692. VOID
  1693. KiRestoreProcessorState (
  1694. IN PKTRAP_FRAME TrapFrame,
  1695. IN PKEXCEPTION_FRAME ExceptionFrame
  1696. );
  1697. VOID
  1698. KiRestoreProcessorControlState (
  1699. IN PKPROCESSOR_STATE ProcessorState
  1700. );
  1701. #define KiEnableAlignmentExceptions()
  1702. #define KiDisableAlignmentExceptions()
  1703. BOOLEAN
  1704. KiHandleAlignmentFault(
  1705. IN PEXCEPTION_RECORD ExceptionRecord,
  1706. IN PKEXCEPTION_FRAME ExceptionFrame,
  1707. IN PKTRAP_FRAME TrapFrame,
  1708. IN KPROCESSOR_MODE PreviousMode,
  1709. IN BOOLEAN FirstChance,
  1710. OUT BOOLEAN *ExceptionForwarded
  1711. );
  1712. //
  1713. // External references to private kernel data structures
  1714. //
  1715. extern PMESSAGE_RESOURCE_DATA KiBugCodeMessages;
  1716. extern FAST_MUTEX KiGenericCallDpcMutex;
  1717. extern ULONG KiDmaIoCoherency;
  1718. extern ULONG KiMaximumDpcQueueDepth;
  1719. extern ULONG KiMinimumDpcRate;
  1720. extern ULONG KiAdjustDpcThreshold;
  1721. extern PKDEBUG_ROUTINE KiDebugRoutine;
  1722. extern PKDEBUG_SWITCH_ROUTINE KiDebugSwitchRoutine;
  1723. extern const CCHAR KiFindFirstSetLeft[256];
  1724. extern CALL_PERFORMANCE_DATA KiFlushSingleCallData;
  1725. extern ULONG_PTR KiHardwareTrigger;
  1726. extern KEVENT KiSwapEvent;
  1727. extern PKTHREAD KiSwappingThread;
  1728. extern KNODE KiNode0;
  1729. extern KNODE KiNodeInit[];
  1730. extern SINGLE_LIST_ENTRY KiProcessInSwapListHead;
  1731. extern SINGLE_LIST_ENTRY KiProcessOutSwapListHead;
  1732. extern SINGLE_LIST_ENTRY KiStackInSwapListHead;
  1733. extern const ULONG KiPriorityMask[];
  1734. extern LIST_ENTRY KiProfileSourceListHead;
  1735. extern BOOLEAN KiProfileAlignmentFixup;
  1736. extern ULONG KiProfileAlignmentFixupInterval;
  1737. extern ULONG KiProfileAlignmentFixupCount;
  1738. extern KSPIN_LOCK KiReverseStallIpiLock;
  1739. #if defined(_X86_)
  1740. extern ULONG KiLog2MaximumIncrement;
  1741. extern ULONG KiMaximumIncrementReciprocal;
  1742. extern ULONG KeTimerReductionModulus;
  1743. extern ULONG KiUpperModMul;
  1744. #endif
  1745. #if defined(_IA64_)
  1746. extern ULONG KiMaxIntervalPerTimerInterrupt;
  1747. // KiProfileInterval value should be replaced by a call:
  1748. // HalQuerySystemInformation(HalProfileSourceInformation)
  1749. #else // _IA64_
  1750. extern ULONG KiProfileInterval;
  1751. #endif // _IA64_
  1752. extern LIST_ENTRY KiProfileListHead;
  1753. extern KSPIN_LOCK KiProfileLock;
  1754. extern UCHAR KiArgumentTable[];
  1755. extern ULONG KiServiceLimit;
  1756. extern ULONG_PTR KiServiceTable[];
  1757. extern CALL_PERFORMANCE_DATA KiSetEventCallData;
  1758. extern ULONG KiTickOffset;
  1759. extern LIST_ENTRY KiTimerTableListHead[TIMER_TABLE_SIZE];
  1760. extern KAFFINITY KiTimeProcessor;
  1761. extern KDPC KiTimerExpireDpc;
  1762. extern KSPIN_LOCK KiFreezeExecutionLock;
  1763. extern BOOLEAN KiSlavesStartExecution;
  1764. extern CALL_PERFORMANCE_DATA KiWaitSingleCallData;
  1765. extern ULONG KiEnableTimerWatchdog;
  1766. #if defined(_IA64_)
  1767. extern ULONG KiMasterRid;
  1768. extern ULONGLONG KiMasterSequence;
  1769. extern ULONG KiIdealDpcRate;
  1770. extern KSPIN_LOCK KiRegionSwapLock;
  1771. #if !defined(UP_NT)
  1772. extern KSPIN_LOCK KiMasterRidLock;
  1773. #endif
  1774. VOID
  1775. KiSaveEmDebugContext (
  1776. IN OUT PCONTEXT Context
  1777. );
  1778. VOID
  1779. KiLoadEmDebugContext (
  1780. IN PCONTEXT Context
  1781. );
  1782. VOID
  1783. KiFlushRse (
  1784. VOID
  1785. );
  1786. VOID
  1787. KiInvalidateStackedRegisters (
  1788. VOID
  1789. );
  1790. NTSTATUS
  1791. Ki386CheckDivideByZeroTrap(
  1792. IN PKTRAP_FRAME Frame
  1793. );
  1794. #endif // defined(_IA64_)
  1795. #if defined(_IA64_)
  1796. extern KINTERRUPT KxUnexpectedInterrupt;
  1797. #endif
  1798. #if NT_INST
  1799. extern KIPI_COUNTS KiIpiCounts[MAXIMUM_PROCESSORS];
  1800. #endif
  1801. extern KSPIN_LOCK KiFreezeLockBackup;
  1802. extern ULONG KiFreezeFlag;
  1803. extern volatile ULONG KiSuspendState;
  1804. #if DBG
  1805. extern ULONG KiMaximumSearchCount;
  1806. #endif
  1807. //
  1808. // Define context switch data collection macro.
  1809. //
  1810. //#define _COLLECT_SWITCH_DATA_ 1
  1811. #if defined(_COLLECT_SWITCH_DATA_)
  1812. #define KiIncrementSwitchCounter(Member) KeThreadSwitchCounters.Member += 1
  1813. #else
  1814. #define KiIncrementSwitchCounter(Member)
  1815. #endif
  1816. FORCEINLINE
  1817. PKTHREAD
  1818. KiSelectReadyThread (
  1819. IN KPRIORITY LowPriority,
  1820. IN PKPRCB Prcb
  1821. )
  1822. /*++
  1823. Routine Description:
  1824. This function searches the dispatcher ready queues from the specified
  1825. low priority to the highest priority in an attempt to find a thread
  1826. that can execute on the specified processor.
  1827. Arguments:
  1828. LowPriority - Supplies the lowest priority dispatcher ready queue to
  1829. examine.
  1830. Prcb - Supplies a pointer to a processor control block.
  1831. Return Value:
  1832. If a thread is located that can execute on the specified processor, then
  1833. the address of the thread object is returned. Otherwise a null pointer
  1834. is returned.
  1835. --*/
  1836. {
  1837. ULONG HighPriority;
  1838. PRLIST_ENTRY ListEntry;
  1839. ULONG PrioritySet;
  1840. PKTHREAD Thread;
  1841. //
  1842. // Compute the set of priority levels that should be scanned in an attempt
  1843. // to find a thread that can run on the current processor.
  1844. //
  1845. PrioritySet = KiPriorityMask[LowPriority] & Prcb->ReadySummary;
  1846. Thread = NULL;
  1847. if (PrioritySet != 0) {
  1848. KeFindFirstSetLeftMember(PrioritySet, &HighPriority);
  1849. ASSERT((PrioritySet & PRIORITY_MASK(HighPriority)) != 0);
  1850. ASSERT(IsListEmpty(&Prcb->DispatcherReadyListHead[HighPriority]) == FALSE);
  1851. ListEntry = Prcb->DispatcherReadyListHead[HighPriority].Flink;
  1852. Thread = CONTAINING_RECORD(ListEntry, KTHREAD, WaitListEntry);
  1853. ASSERT((KPRIORITY)HighPriority == Thread->Priority);
  1854. ASSERT((Thread->Affinity & AFFINITY_MASK(Prcb->Number)) != 0);
  1855. ASSERT(Thread->NextProcessor == Prcb->Number);
  1856. if (RemoveEntryList(&Thread->WaitListEntry) != FALSE) {
  1857. Prcb->ReadySummary ^= PRIORITY_MASK(HighPriority);
  1858. }
  1859. }
  1860. //
  1861. // Return thread address if one could be found.
  1862. //
  1863. return Thread;
  1864. }
  1865. VOID
  1866. KiSetInternalEvent (
  1867. IN PKEVENT Event,
  1868. IN PKTHREAD Thread
  1869. );
  1870. //
  1871. // Include platform specific internal kernel header file.
  1872. //
  1873. #if defined(_AMD64_)
  1874. #include "amd64\kiamd64.h"
  1875. #elif defined(_X86_)
  1876. #include "i386\kix86.h"
  1877. #endif // defined(_AMD64_)
  1878. #endif // defined(_KI_)