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.

1485 lines
42 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. addrsup.c
  5. Abstract:
  6. This module contains the routine to manipulate the virtual address
  7. descriptor tree.
  8. Author:
  9. Lou Perazzoli (loup) 19-May-1989
  10. Landy Wang (landyw) 02-June-1997
  11. Ripped off and modified from timersup.c
  12. The support for siblings was removed and a routine to locate
  13. the corresponding virtual address descriptor for a given address
  14. was added.
  15. Environment:
  16. Kernel mode only, working set mutex held, APCs disabled.
  17. Revision History:
  18. --*/
  19. #include "mi.h"
  20. #if (_MSC_VER >= 800)
  21. #pragma warning(disable:4010) // Allow pretty pictures without the noise
  22. #endif
  23. VOID
  24. MiReorderTree (
  25. IN PMMADDRESS_NODE Node,
  26. IN OUT PMMADDRESS_NODE *Root
  27. );
  28. #ifdef ALLOC_PRAGMA
  29. #pragma alloc_text(PAGE,MiGetFirstNode)
  30. #pragma alloc_text(PAGE,MiInsertNode)
  31. #pragma alloc_text(PAGE,MiGetNextNode)
  32. #pragma alloc_text(PAGE,MiGetPreviousNode)
  33. #pragma alloc_text(PAGE,MiCheckForConflictingNode)
  34. #pragma alloc_text(PAGE,MiFindEmptyAddressRangeInTree)
  35. #pragma alloc_text(PAGE,MiFindEmptyAddressRangeDownTree)
  36. #pragma alloc_text(PAGE,MiReorderTree)
  37. #pragma alloc_text(PAGE,NodeTreeWalk)
  38. #endif
  39. VOID
  40. MiReorderTree (
  41. IN PMMADDRESS_NODE Node,
  42. IN OUT PMMADDRESS_NODE *Root
  43. )
  44. /*++
  45. Routine Description:
  46. This function reorders the Node tree by applying various splay functions
  47. to the tree. This is a local function that is called by the insert Node
  48. routine.
  49. Arguments:
  50. Node - Supplies a pointer to a virtual address descriptor.
  51. Return Value:
  52. None.
  53. --*/
  54. {
  55. PMMADDRESS_NODE GrandParent;
  56. PMMADDRESS_NODE Parent;
  57. PMMADDRESS_NODE SplayNode;
  58. //
  59. // Reorder Node tree to make it as balanced as possible with as little
  60. // work as possible.
  61. //
  62. SplayNode = Node;
  63. while (SplayNode != *Root) {
  64. Parent = SplayNode->Parent;
  65. if (Parent == *Root) {
  66. //
  67. // Splay node's parent is the root of the tree. Rotate the tree
  68. // left or right depending on whether the splay node is the left
  69. // of right child of its parent.
  70. //
  71. // Pictorially:
  72. //
  73. // Right Left
  74. //
  75. // P X P X
  76. // / \ / \ / \ / \
  77. // X C -> A P C X -> P A
  78. // / \ / \ / \ / \
  79. // A B B C B A C B
  80. //
  81. *Root = SplayNode;
  82. SplayNode->Parent = (PMMADDRESS_NODE)NULL;
  83. Parent->Parent = SplayNode;
  84. if (SplayNode == Parent->LeftChild) {
  85. //
  86. // Splay node is the left child of its parent. Rotate tree
  87. // right.
  88. //
  89. Parent->LeftChild = SplayNode->RightChild;
  90. if (SplayNode->RightChild) {
  91. SplayNode->RightChild->Parent = Parent;
  92. }
  93. SplayNode->RightChild = Parent;
  94. } else {
  95. //
  96. // Splay node is the right child of its parent. Rotate tree
  97. // left.
  98. //
  99. Parent->RightChild = SplayNode->LeftChild;
  100. if (SplayNode->LeftChild) {
  101. SplayNode->LeftChild->Parent = Parent;
  102. }
  103. SplayNode->LeftChild = Parent;
  104. }
  105. break;
  106. } else {
  107. GrandParent = Parent->Parent;
  108. if ((SplayNode == Parent->LeftChild) &&
  109. (Parent == GrandParent->LeftChild)) {
  110. //
  111. // Both the splay node and the parent node are left children
  112. // of their parents. Rotate tree right and make the parent
  113. // the root of the new subtree.
  114. //
  115. // Pictorially:
  116. //
  117. // G P
  118. // / \ / \
  119. // P D X G
  120. // / \ -> / \ / \
  121. // X C A B C D
  122. // / \
  123. // A B
  124. //
  125. if (GrandParent == *Root) {
  126. *Root = Parent;
  127. Parent->Parent = (PMMADDRESS_NODE)NULL;
  128. } else {
  129. Parent->Parent = GrandParent->Parent;
  130. if (GrandParent == GrandParent->Parent->LeftChild) {
  131. GrandParent->Parent->LeftChild = Parent;
  132. } else {
  133. GrandParent->Parent->RightChild = Parent;
  134. }
  135. }
  136. GrandParent->LeftChild = Parent->RightChild;
  137. if (Parent->RightChild) {
  138. Parent->RightChild->Parent = GrandParent;
  139. }
  140. GrandParent->Parent = Parent;
  141. Parent->RightChild = GrandParent;
  142. SplayNode = Parent;
  143. } else if ((SplayNode == Parent->RightChild) &&
  144. (Parent == GrandParent->RightChild)) {
  145. //
  146. // Both the splay node and the parent node are right children
  147. // of their parents. Rotate tree left and make the parent
  148. // the root of the new subtree.
  149. //
  150. // Pictorially:
  151. //
  152. // G P
  153. // / \ / \
  154. // D P G X
  155. // / \ -> / \ / \
  156. // C X D C B A
  157. // / \
  158. // A B
  159. //
  160. if (GrandParent == *Root) {
  161. *Root = Parent;
  162. Parent->Parent = (PMMADDRESS_NODE)NULL;
  163. } else {
  164. Parent->Parent = GrandParent->Parent;
  165. if (GrandParent == GrandParent->Parent->LeftChild) {
  166. GrandParent->Parent->LeftChild = Parent;
  167. } else {
  168. GrandParent->Parent->RightChild = Parent;
  169. }
  170. }
  171. GrandParent->RightChild = Parent->LeftChild;
  172. if (Parent->LeftChild) {
  173. Parent->LeftChild->Parent = GrandParent;
  174. }
  175. GrandParent->Parent = Parent;
  176. Parent->LeftChild = GrandParent;
  177. SplayNode = Parent;
  178. } else if ((SplayNode == Parent->LeftChild) &&
  179. (Parent == GrandParent->RightChild)) {
  180. //
  181. // Splay node is the left child of its parent and parent is
  182. // the right child of its parent. Rotate tree left and make
  183. // splay node the root of the new subtree.
  184. //
  185. // Pictorially:
  186. //
  187. // G X
  188. // / \ / \
  189. // A P G P
  190. // / \ -> / \ / \
  191. // X D A B C D
  192. // / \
  193. // B C
  194. //
  195. if (GrandParent == *Root) {
  196. *Root = SplayNode;
  197. SplayNode->Parent = (PMMADDRESS_NODE)NULL;
  198. } else {
  199. SplayNode->Parent = GrandParent->Parent;
  200. if (GrandParent == GrandParent->Parent->LeftChild) {
  201. GrandParent->Parent->LeftChild = SplayNode;
  202. } else {
  203. GrandParent->Parent->RightChild = SplayNode;
  204. }
  205. }
  206. Parent->LeftChild = SplayNode->RightChild;
  207. if (SplayNode->RightChild) {
  208. SplayNode->RightChild->Parent = Parent;
  209. }
  210. GrandParent->RightChild = SplayNode->LeftChild;
  211. if (SplayNode->LeftChild) {
  212. SplayNode->LeftChild->Parent = GrandParent;
  213. }
  214. Parent->Parent = SplayNode;
  215. GrandParent->Parent = SplayNode;
  216. SplayNode->LeftChild = GrandParent;
  217. SplayNode->RightChild = Parent;
  218. } else {
  219. //
  220. // Splay node is the right child of its parent and parent is
  221. // the left child of its parent. Rotate tree right and make
  222. // splay node the root of the new subtree.
  223. //
  224. // Pictorially:
  225. //
  226. // G X
  227. // / \ / \
  228. // P A P G
  229. // / \ -> / \ / \
  230. // D X D C B A
  231. // / \
  232. // C B
  233. //
  234. if (GrandParent == *Root) {
  235. *Root = SplayNode;
  236. SplayNode->Parent = (PMMADDRESS_NODE)NULL;
  237. } else {
  238. SplayNode->Parent = GrandParent->Parent;
  239. if (GrandParent == GrandParent->Parent->LeftChild) {
  240. GrandParent->Parent->LeftChild = SplayNode;
  241. } else {
  242. GrandParent->Parent->RightChild = SplayNode;
  243. }
  244. }
  245. Parent->RightChild = SplayNode->LeftChild;
  246. if (SplayNode->LeftChild) {
  247. SplayNode->LeftChild->Parent = Parent;
  248. }
  249. GrandParent->LeftChild = SplayNode->RightChild;
  250. if (SplayNode->RightChild) {
  251. SplayNode->RightChild->Parent = GrandParent;
  252. }
  253. Parent->Parent = SplayNode;
  254. GrandParent->Parent = SplayNode;
  255. SplayNode->LeftChild = Parent;
  256. SplayNode->RightChild = GrandParent;
  257. }
  258. }
  259. }
  260. return;
  261. }
  262. PMMADDRESS_NODE
  263. FASTCALL
  264. MiGetNextNode (
  265. IN PMMADDRESS_NODE Node
  266. )
  267. /*++
  268. Routine Description:
  269. This function locates the virtual address descriptor which contains
  270. the address range which logically follows the specified address range.
  271. Arguments:
  272. Node - Supplies a pointer to a virtual address descriptor.
  273. Return Value:
  274. Returns a pointer to the virtual address descriptor containing the
  275. next address range, NULL if none.
  276. --*/
  277. {
  278. PMMADDRESS_NODE Next;
  279. PMMADDRESS_NODE Parent;
  280. PMMADDRESS_NODE Left;
  281. Next = Node;
  282. if (Next->RightChild == (PMMADDRESS_NODE)NULL) {
  283. while ((Parent = Next->Parent) != (PMMADDRESS_NODE)NULL) {
  284. //
  285. // Locate the first ancestor of this node of which this
  286. // node is the left child of and return that node as the
  287. // next element.
  288. //
  289. if (Parent->LeftChild == Next) {
  290. return Parent;
  291. }
  292. Next = Parent;
  293. }
  294. return (PMMADDRESS_NODE)NULL;
  295. }
  296. //
  297. // A right child exists, locate the left most child of that right child.
  298. //
  299. Next = Next->RightChild;
  300. while ((Left = Next->LeftChild) != (PMMADDRESS_NODE)NULL) {
  301. Next = Left;
  302. }
  303. return Next;
  304. }
  305. PMMADDRESS_NODE
  306. FASTCALL
  307. MiGetPreviousNode (
  308. IN PMMADDRESS_NODE Node
  309. )
  310. /*++
  311. Routine Description:
  312. This function locates the virtual address descriptor which contains
  313. the address range which logically precedes the specified virtual
  314. address descriptor.
  315. Arguments:
  316. Node - Supplies a pointer to a virtual address descriptor.
  317. Return Value:
  318. Returns a pointer to the virtual address descriptor containing the
  319. next address range, NULL if none.
  320. --*/
  321. {
  322. PMMADDRESS_NODE Previous;
  323. Previous = Node;
  324. if (Previous->LeftChild == (PMMADDRESS_NODE)NULL) {
  325. while (Previous->Parent != (PMMADDRESS_NODE)NULL) {
  326. //
  327. // Locate the first ancestor of this node of which this
  328. // node is the right child of and return that node as the
  329. // Previous element.
  330. //
  331. if (Previous->Parent->RightChild == Previous) {
  332. return Previous->Parent;
  333. }
  334. Previous = Previous->Parent;
  335. }
  336. return (PMMADDRESS_NODE)NULL;
  337. }
  338. //
  339. // A left child exists, locate the right most child of that left child.
  340. //
  341. Previous = Previous->LeftChild;
  342. while (Previous->RightChild != (PMMADDRESS_NODE)NULL) {
  343. Previous = Previous->RightChild;
  344. }
  345. return Previous;
  346. }
  347. PMMADDRESS_NODE
  348. FASTCALL
  349. MiGetFirstNode (
  350. IN PMMADDRESS_NODE Root
  351. )
  352. /*++
  353. Routine Description:
  354. This function locates the virtual address descriptor which contains
  355. the address range which logically is first within the address space.
  356. Arguments:
  357. None.
  358. Return Value:
  359. Returns a pointer to the virtual address descriptor containing the
  360. first address range, NULL if none.
  361. --*/
  362. {
  363. PMMADDRESS_NODE First;
  364. First = Root;
  365. if (First == (PMMADDRESS_NODE)NULL) {
  366. return (PMMADDRESS_NODE)NULL;
  367. }
  368. while (First->LeftChild != (PMMADDRESS_NODE)NULL) {
  369. First = First->LeftChild;
  370. }
  371. return First;
  372. }
  373. VOID
  374. FASTCALL
  375. MiInsertNode (
  376. IN PMMADDRESS_NODE Node,
  377. IN OUT PMMADDRESS_NODE *Root
  378. )
  379. /*++
  380. Routine Description:
  381. This function inserts a virtual address descriptor into the tree and
  382. reorders the splay tree as appropriate.
  383. Arguments:
  384. Node - Supplies a pointer to a virtual address descriptor
  385. Return Value:
  386. None.
  387. --*/
  388. {
  389. ULONG Level = 0;
  390. PMMADDRESS_NODE Parent;
  391. //
  392. // Initialize virtual address descriptor child links.
  393. //
  394. Node->LeftChild = (PMMADDRESS_NODE)NULL;
  395. Node->RightChild = (PMMADDRESS_NODE)NULL;
  396. //
  397. // If the tree is empty, then establish this virtual address descriptor
  398. // as the root of the tree.
  399. // Otherwise descend the tree to find the correct place to
  400. // insert the descriptor.
  401. //
  402. Parent = *Root;
  403. if (!Parent) {
  404. *Root = Node;
  405. Node->Parent = (PMMADDRESS_NODE)NULL;
  406. } else {
  407. for (;;) {
  408. Level += 1;
  409. if (Level == 15) {
  410. MiReorderTree(Parent, Root);
  411. }
  412. //
  413. // If the starting address for this virtual address descriptor
  414. // is less than the parent starting address, then
  415. // follow the left child link. Else follow the right child link.
  416. //
  417. if (Node->StartingVpn < Parent->StartingVpn) {
  418. //
  419. // Starting address of the virtual address descriptor is less
  420. // than the parent starting virtual address.
  421. // Follow left child link if not null. Otherwise
  422. // insert the descriptor as the left child of the parent and
  423. // reorder the tree.
  424. //
  425. if (Parent->LeftChild) {
  426. Parent = Parent->LeftChild;
  427. } else {
  428. Parent->LeftChild = Node;
  429. Node->Parent = Parent;
  430. // MiReorderTree(Node, Root);
  431. break;
  432. }
  433. } else {
  434. //
  435. // Starting address of the virtual address descriptor is greater
  436. // than the parent starting virtual address.
  437. // Follow right child link if not null. Otherwise
  438. // insert the descriptor as the right child of the parent and
  439. // reorder the tree.
  440. //
  441. if (Parent->RightChild) {
  442. Parent = Parent->RightChild;
  443. } else {
  444. Parent->RightChild = Node;
  445. Node->Parent = Parent;
  446. // MiReorderTree(Node, Root);
  447. break;
  448. }
  449. }
  450. }
  451. }
  452. return;
  453. }
  454. VOID
  455. FASTCALL
  456. MiRemoveNode (
  457. IN PMMADDRESS_NODE Node,
  458. IN OUT PMMADDRESS_NODE *Root
  459. )
  460. /*++
  461. Routine Description:
  462. This function removes a virtual address descriptor from the tree and
  463. reorders the splay tree as appropriate.
  464. Arguments:
  465. Node - Supplies a pointer to a virtual address descriptor.
  466. Return Value:
  467. None.
  468. --*/
  469. {
  470. PMMADDRESS_NODE LeftChild;
  471. PMMADDRESS_NODE RightChild;
  472. PMMADDRESS_NODE SplayNode;
  473. LeftChild = Node->LeftChild;
  474. RightChild = Node->RightChild;
  475. //
  476. // If the Node is the root of the tree, then establish new root. Else
  477. // isolate splay case and perform splay tree transformation.
  478. //
  479. if (Node == *Root) {
  480. //
  481. // This Node is the root of the tree. There are four cases to
  482. // handle:
  483. //
  484. // 1. the descriptor has no children
  485. // 2. the descriptor has a left child but no right child
  486. // 3. the descriptor has a right child but no left child
  487. // 4. the descriptor has both a right child and a left child
  488. //
  489. if (LeftChild) {
  490. if (RightChild) {
  491. //
  492. // The descriptor has both a left child and a right child.
  493. //
  494. if (LeftChild->RightChild) {
  495. //
  496. // The left child has a right child. Make the right most
  497. // descendent of the right child of the left child the
  498. // new root of the tree.
  499. //
  500. // Pictorially:
  501. //
  502. // R R
  503. // | |
  504. // X Z
  505. // / \ / \
  506. // A B -> A B
  507. // \ \
  508. // . .
  509. // \
  510. // Z
  511. //
  512. SplayNode = LeftChild->RightChild;
  513. while (SplayNode->RightChild) {
  514. SplayNode = SplayNode->RightChild;
  515. }
  516. *Root = SplayNode;
  517. SplayNode->Parent->RightChild = SplayNode->LeftChild;
  518. if (SplayNode->LeftChild) {
  519. SplayNode->LeftChild->Parent = SplayNode->Parent;
  520. }
  521. SplayNode->Parent = (PMMADDRESS_NODE)NULL;
  522. LeftChild->Parent = SplayNode;
  523. RightChild->Parent = SplayNode;
  524. SplayNode->LeftChild = LeftChild;
  525. SplayNode->RightChild = RightChild;
  526. } else if (RightChild->LeftChild) {
  527. //
  528. // The right child has a left child. Make the left most
  529. // descendent of the left child of the right child the
  530. // new root of the tree.
  531. //
  532. // Pictorially:
  533. //
  534. // R R
  535. // | |
  536. // X Z
  537. // / \ / \
  538. // A B -> A B
  539. // / /
  540. // . .
  541. // /
  542. // Z
  543. //
  544. SplayNode = RightChild->LeftChild;
  545. while (SplayNode->LeftChild) {
  546. SplayNode = SplayNode->LeftChild;
  547. }
  548. *Root = SplayNode;
  549. SplayNode->Parent->LeftChild = SplayNode->RightChild;
  550. if (SplayNode->RightChild) {
  551. SplayNode->RightChild->Parent = SplayNode->Parent;
  552. }
  553. SplayNode->Parent = (PMMADDRESS_NODE)NULL;
  554. LeftChild->Parent = SplayNode;
  555. RightChild->Parent = SplayNode;
  556. SplayNode->LeftChild = LeftChild;
  557. SplayNode->RightChild = RightChild;
  558. } else {
  559. //
  560. // The left child of the descriptor does not have a right child,
  561. // and the right child of the descriptor does not have a left
  562. // child. Make the left child of the descriptor the new root of
  563. // the tree.
  564. //
  565. // Pictorially:
  566. //
  567. // R R
  568. // | |
  569. // X A
  570. // / \ / \
  571. // A B -> . B
  572. // / /
  573. // .
  574. //
  575. *Root = LeftChild;
  576. LeftChild->Parent = (PMMADDRESS_NODE)NULL;
  577. LeftChild->RightChild = RightChild;
  578. LeftChild->RightChild->Parent = LeftChild;
  579. }
  580. } else {
  581. //
  582. // The descriptor has a left child, but does not have a right child.
  583. // Make the left child the new root of the tree.
  584. //
  585. // Pictorially:
  586. //
  587. // R R
  588. // | |
  589. // X -> A
  590. // /
  591. // A
  592. //
  593. *Root = LeftChild;
  594. LeftChild->Parent = (PMMADDRESS_NODE)NULL;
  595. }
  596. } else if (RightChild) {
  597. //
  598. // The descriptor has a right child, but does not have a left child.
  599. // Make the right child the new root of the tree.
  600. //
  601. // Pictorially:
  602. //
  603. // R R
  604. // | |
  605. // X -> A
  606. // \
  607. // A
  608. //
  609. *Root = RightChild;
  610. RightChild->Parent = (PMMADDRESS_NODE)NULL;
  611. while (RightChild->LeftChild) {
  612. RightChild = RightChild->LeftChild;
  613. }
  614. } else {
  615. //
  616. // The descriptor has neither a left child nor a right child. The
  617. // tree will be empty after removing the descriptor.
  618. //
  619. // Pictorially:
  620. //
  621. // R R
  622. // | ->
  623. // X
  624. //
  625. *Root = NULL;
  626. }
  627. } else if (LeftChild) {
  628. if (RightChild) {
  629. //
  630. // The descriptor has both a left child and a right child.
  631. //
  632. if (LeftChild->RightChild) {
  633. //
  634. // The left child has a right child. Make the right most
  635. // descendent of the right child of the left child the new
  636. // root of the subtree.
  637. //
  638. // Pictorially:
  639. //
  640. // P P
  641. // / \
  642. // X X
  643. // / \ / \
  644. // A B or A B
  645. // \ \
  646. // . .
  647. // \ \
  648. // Z Z
  649. //
  650. // |
  651. // v
  652. //
  653. // P P
  654. // / \
  655. // Z Z
  656. // / \ / \
  657. // A B or A B
  658. // \ \
  659. // . .
  660. //
  661. SplayNode = LeftChild->RightChild;
  662. while (SplayNode->RightChild) {
  663. SplayNode = SplayNode->RightChild;
  664. }
  665. SplayNode->Parent->RightChild = SplayNode->LeftChild;
  666. if (SplayNode->LeftChild) {
  667. SplayNode->LeftChild->Parent = SplayNode->Parent;
  668. }
  669. SplayNode->Parent = Node->Parent;
  670. if (Node == Node->Parent->LeftChild) {
  671. Node->Parent->LeftChild = SplayNode;
  672. } else {
  673. Node->Parent->RightChild = SplayNode;
  674. }
  675. LeftChild->Parent = SplayNode;
  676. RightChild->Parent = SplayNode;
  677. SplayNode->LeftChild = LeftChild;
  678. SplayNode->RightChild = RightChild;
  679. } else if (RightChild->LeftChild) {
  680. //
  681. // The right child has a left child. Make the left most
  682. // descendent of the left child of the right child the
  683. // new root of the subtree.
  684. //
  685. // Pictorially:
  686. //
  687. // P P
  688. // / \
  689. // X X
  690. // / \ / \
  691. // A B or A B
  692. // / /
  693. // . .
  694. // / /
  695. // Z Z
  696. //
  697. // |
  698. // v
  699. //
  700. // P P
  701. // / \
  702. // Z Z
  703. // / \ / \
  704. // A B or A B
  705. // / /
  706. // . .
  707. //
  708. SplayNode = RightChild->LeftChild;
  709. while (SplayNode->LeftChild) {
  710. SplayNode = SplayNode->LeftChild;
  711. }
  712. SplayNode->Parent->LeftChild = SplayNode->RightChild;
  713. if (SplayNode->RightChild) {
  714. SplayNode->RightChild->Parent = SplayNode->Parent;
  715. }
  716. SplayNode->Parent = Node->Parent;
  717. if (Node == Node->Parent->LeftChild) {
  718. Node->Parent->LeftChild = SplayNode;
  719. } else {
  720. Node->Parent->RightChild = SplayNode;
  721. }
  722. LeftChild->Parent = SplayNode;
  723. RightChild->Parent = SplayNode;
  724. SplayNode->LeftChild = LeftChild;
  725. SplayNode->RightChild = RightChild;
  726. } else {
  727. //
  728. // The left child of the descriptor does not have a right child,
  729. // and the right child of the descriptor does node have a left
  730. // child. Make the left child of the descriptor the new root of
  731. // the subtree.
  732. //
  733. // Pictorially:
  734. //
  735. // P P
  736. // / \
  737. // X X
  738. // / \ / \
  739. // A B or A B
  740. // / /
  741. // . .
  742. //
  743. // |
  744. // v
  745. //
  746. // P P
  747. // / \
  748. // A A
  749. // / \ / \
  750. // . B or . B
  751. // / /
  752. //
  753. SplayNode = LeftChild;
  754. SplayNode->Parent = Node->Parent;
  755. if (Node == Node->Parent->LeftChild) {
  756. Node->Parent->LeftChild = SplayNode;
  757. } else {
  758. Node->Parent->RightChild = SplayNode;
  759. }
  760. SplayNode->RightChild = RightChild;
  761. RightChild->Parent = SplayNode;
  762. }
  763. } else {
  764. //
  765. // The descriptor has a left child, but does not have a right child.
  766. // Make the left child the new root of the subtree.
  767. //
  768. // Pictorially:
  769. //
  770. // P P
  771. // / \
  772. // X or X
  773. // / /
  774. // A A
  775. //
  776. // |
  777. // v
  778. //
  779. // P P
  780. // / \
  781. // A A
  782. //
  783. LeftChild->Parent = Node->Parent;
  784. if (Node == Node->Parent->LeftChild) {
  785. Node->Parent->LeftChild = LeftChild;
  786. } else {
  787. Node->Parent->RightChild = LeftChild;
  788. }
  789. }
  790. } else if (RightChild) {
  791. //
  792. // descriptor has a right child, but does not have a left child. Make
  793. // the right child the new root of the subtree.
  794. //
  795. // Pictorially:
  796. //
  797. // P P
  798. // / \
  799. // X or X
  800. // \ \
  801. // A A
  802. //
  803. // |
  804. // v
  805. //
  806. // P P
  807. // / \
  808. // A A
  809. //
  810. RightChild->Parent = Node->Parent;
  811. if (Node == Node->Parent->LeftChild) {
  812. Node->Parent->LeftChild = RightChild;
  813. } else {
  814. Node->Parent->RightChild = RightChild;
  815. }
  816. } else {
  817. //
  818. // The descriptor has neither a left child nor a right child. Delete
  819. // the descriptor from the tree and adjust its parent right or left
  820. // link.
  821. //
  822. // Pictorially:
  823. //
  824. // P P
  825. // / \
  826. // X or X
  827. //
  828. // |
  829. // v
  830. //
  831. // P P
  832. //
  833. if (Node == Node->Parent->LeftChild) {
  834. Node->Parent->LeftChild = (PMMADDRESS_NODE)NULL;
  835. } else {
  836. Node->Parent->RightChild = (PMMADDRESS_NODE)NULL;
  837. }
  838. }
  839. return;
  840. }
  841. PMMADDRESS_NODE
  842. FASTCALL
  843. MiLocateAddressInTree (
  844. IN ULONG_PTR Vpn,
  845. IN PMMADDRESS_NODE *Root
  846. )
  847. /*++
  848. Routine Description:
  849. The function locates the virtual address descriptor which describes
  850. a given address.
  851. Arguments:
  852. Vpn - Supplies the virtual page number to locate a descriptor for.
  853. Return Value:
  854. Returns a pointer to the virtual address descriptor which contains
  855. the supplied virtual address or NULL if none was located.
  856. --*/
  857. {
  858. PMMADDRESS_NODE Parent;
  859. ULONG Level = 0;
  860. Parent = *Root;
  861. for (;;) {
  862. if (Parent == (PMMADDRESS_NODE)NULL) {
  863. return (PMMADDRESS_NODE)NULL;
  864. }
  865. if (Level == 20) {
  866. //
  867. // There are 20 nodes above this point, reorder the
  868. // tree with this node as the root. Note this reorder
  869. // cannot be done unless the address creation mutex is held,
  870. // and it is not held on faults.
  871. #if 0
  872. MiReorderTree(Parent, Root);
  873. #endif
  874. }
  875. if (Vpn < Parent->StartingVpn) {
  876. Parent = Parent->LeftChild;
  877. Level += 1;
  878. } else if (Vpn > Parent->EndingVpn) {
  879. Parent = Parent->RightChild;
  880. Level += 1;
  881. } else {
  882. //
  883. // The address is within the start and end range.
  884. //
  885. return Parent;
  886. }
  887. }
  888. }
  889. PMMADDRESS_NODE
  890. MiCheckForConflictingNode (
  891. IN ULONG_PTR StartVpn,
  892. IN ULONG_PTR EndVpn,
  893. IN PMMADDRESS_NODE Root
  894. )
  895. /*++
  896. Routine Description:
  897. The function determines if any addresses between a given starting and
  898. ending address is contained within a virtual address descriptor.
  899. Arguments:
  900. StartVpn - Supplies the virtual address to locate a containing
  901. descriptor.
  902. EndVpn - Supplies the virtual address to locate a containing
  903. descriptor.
  904. Return Value:
  905. Returns a pointer to the first conflicting virtual address descriptor
  906. if one is found, otherwise a NULL value is returned.
  907. --*/
  908. {
  909. PMMADDRESS_NODE Node;
  910. Node = Root;
  911. for (;;) {
  912. if (Node == (PMMADDRESS_NODE)NULL) {
  913. return (PMMADDRESS_NODE)NULL;
  914. }
  915. if (StartVpn > Node->EndingVpn) {
  916. Node = Node->RightChild;
  917. } else if (EndVpn < Node->StartingVpn) {
  918. Node = Node->LeftChild;
  919. } else {
  920. //
  921. // The starting address is less than or equal to the end VA
  922. // and the ending address is greater than or equal to the
  923. // start va. Return this node.
  924. //
  925. return Node;
  926. }
  927. }
  928. }
  929. NTSTATUS
  930. MiFindEmptyAddressRangeInTree (
  931. IN SIZE_T SizeOfRange,
  932. IN ULONG_PTR Alignment,
  933. IN PMMADDRESS_NODE Root,
  934. OUT PMMADDRESS_NODE *PreviousVad,
  935. OUT PVOID *Base
  936. )
  937. /*++
  938. Routine Description:
  939. The function examines the virtual address descriptors to locate
  940. an unused range of the specified size and returns the starting
  941. address of the range.
  942. Arguments:
  943. SizeOfRange - Supplies the size in bytes of the range to locate.
  944. Alignment - Supplies the alignment for the address. Must be
  945. a power of 2 and greater than the page_size.
  946. Root - Supplies the root of the tree to search through.
  947. PreviousVad - Supplies the Vad which is before this the found
  948. address range.
  949. Base - Receives the starting address of a suitable range on success.
  950. Return Value:
  951. NTSTATUS.
  952. --*/
  953. {
  954. PMMADDRESS_NODE Node;
  955. PMMADDRESS_NODE NextNode;
  956. ULONG_PTR AlignmentVpn;
  957. ULONG_PTR SizeOfRangeVpn;
  958. AlignmentVpn = Alignment >> PAGE_SHIFT;
  959. //
  960. // Locate the Node with the lowest starting address.
  961. //
  962. ASSERT (SizeOfRange != 0);
  963. SizeOfRangeVpn = (SizeOfRange + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
  964. ASSERT (SizeOfRangeVpn != 0);
  965. Node = Root;
  966. if (Node == (PMMADDRESS_NODE)NULL) {
  967. *Base = MM_LOWEST_USER_ADDRESS;
  968. return STATUS_SUCCESS;
  969. }
  970. while (Node->LeftChild != (PMMADDRESS_NODE)NULL) {
  971. Node = Node->LeftChild;
  972. }
  973. //
  974. // Check to see if a range exists between the lowest address VAD
  975. // and lowest user address.
  976. //
  977. if (Node->StartingVpn > MI_VA_TO_VPN (MM_LOWEST_USER_ADDRESS)) {
  978. if ( SizeOfRangeVpn <
  979. (Node->StartingVpn - MI_VA_TO_VPN (MM_LOWEST_USER_ADDRESS))) {
  980. *PreviousVad = NULL;
  981. *Base = MM_LOWEST_USER_ADDRESS;
  982. return STATUS_SUCCESS;
  983. }
  984. }
  985. for (;;) {
  986. NextNode = MiGetNextNode (Node);
  987. if (NextNode != (PMMADDRESS_NODE)NULL) {
  988. if (SizeOfRangeVpn <=
  989. ((ULONG_PTR)NextNode->StartingVpn -
  990. MI_ROUND_TO_SIZE(1 + Node->EndingVpn,
  991. AlignmentVpn))) {
  992. //
  993. // Check to ensure that the ending address aligned upwards
  994. // is not greater than the starting address.
  995. //
  996. if ((ULONG_PTR)NextNode->StartingVpn >
  997. MI_ROUND_TO_SIZE(1 + Node->EndingVpn,
  998. AlignmentVpn)) {
  999. *PreviousVad = Node;
  1000. *Base = (PVOID) MI_ROUND_TO_SIZE(
  1001. (ULONG_PTR)MI_VPN_TO_VA_ENDING(Node->EndingVpn),
  1002. Alignment);
  1003. return STATUS_SUCCESS;
  1004. }
  1005. }
  1006. } else {
  1007. //
  1008. // No more descriptors, check to see if this fits into the remainder
  1009. // of the address space.
  1010. //
  1011. if ((((ULONG_PTR)Node->EndingVpn + MI_VA_TO_VPN(X64K)) <
  1012. MI_VA_TO_VPN (MM_HIGHEST_VAD_ADDRESS))
  1013. &&
  1014. (SizeOfRange <=
  1015. ((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS -
  1016. (ULONG_PTR)MI_ROUND_TO_SIZE(
  1017. (ULONG_PTR)MI_VPN_TO_VA(Node->EndingVpn), Alignment)))) {
  1018. *PreviousVad = Node;
  1019. *Base = (PVOID) MI_ROUND_TO_SIZE(
  1020. (ULONG_PTR)MI_VPN_TO_VA_ENDING(Node->EndingVpn),
  1021. Alignment);
  1022. return STATUS_SUCCESS;
  1023. }
  1024. return STATUS_NO_MEMORY;
  1025. }
  1026. Node = NextNode;
  1027. }
  1028. }
  1029. NTSTATUS
  1030. MiFindEmptyAddressRangeDownTree (
  1031. IN SIZE_T SizeOfRange,
  1032. IN PVOID HighestAddressToEndAt,
  1033. IN ULONG_PTR Alignment,
  1034. IN PMMADDRESS_NODE Root,
  1035. OUT PVOID *Base
  1036. )
  1037. /*++
  1038. Routine Description:
  1039. The function examines the virtual address descriptors to locate
  1040. an unused range of the specified size and returns the starting
  1041. address of the range. The function examines from the high
  1042. addresses down and ensures that starting address is less than
  1043. the specified address.
  1044. Arguments:
  1045. SizeOfRange - Supplies the size in bytes of the range to locate.
  1046. HighestAddressToEndAt - Supplies the virtual address that limits
  1047. the value of the ending address. The ending
  1048. address of the located range must be less
  1049. than this address.
  1050. Alignment - Supplies the alignment for the address. Must be
  1051. a power of 2 and greater than the page_size.
  1052. Root - Supplies the root of the tree to search through.
  1053. Base - Receives the starting address of a suitable range on success.
  1054. Return Value:
  1055. NTSTATUS.
  1056. --*/
  1057. {
  1058. PMMADDRESS_NODE Node;
  1059. PMMADDRESS_NODE PreviousNode;
  1060. ULONG_PTR AlignedEndingVa;
  1061. PVOID OptimalStart;
  1062. ULONG_PTR OptimalStartVpn;
  1063. ULONG_PTR HighestVpn;
  1064. ULONG_PTR AlignmentVpn;
  1065. SizeOfRange = MI_ROUND_TO_SIZE (SizeOfRange, PAGE_SIZE);
  1066. if (((ULONG_PTR)HighestAddressToEndAt + 1) < SizeOfRange) {
  1067. return STATUS_NO_MEMORY;
  1068. }
  1069. ASSERT (HighestAddressToEndAt != NULL);
  1070. ASSERT (HighestAddressToEndAt <= (PVOID)((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1));
  1071. HighestVpn = MI_VA_TO_VPN (HighestAddressToEndAt);
  1072. //
  1073. // Locate the Node with the highest starting address.
  1074. //
  1075. OptimalStart = (PVOID)(MI_ALIGN_TO_SIZE(
  1076. (((ULONG_PTR)HighestAddressToEndAt + 1) - SizeOfRange),
  1077. Alignment));
  1078. Node = Root;
  1079. if (Node == (PMMADDRESS_NODE)NULL) {
  1080. //
  1081. // The tree is empty, any range is okay.
  1082. //
  1083. *Base = OptimalStart;
  1084. return STATUS_SUCCESS;
  1085. }
  1086. //
  1087. // See if an empty slot exists to hold this range, locate the largest
  1088. // element in the tree.
  1089. //
  1090. while (Node->RightChild != (PMMADDRESS_NODE)NULL) {
  1091. Node = Node->RightChild;
  1092. }
  1093. //
  1094. // Check to see if a range exists between the highest address VAD
  1095. // and the highest address to end at.
  1096. //
  1097. AlignedEndingVa = (ULONG_PTR)MI_ROUND_TO_SIZE ((ULONG_PTR)MI_VPN_TO_VA_ENDING (Node->EndingVpn),
  1098. Alignment);
  1099. if (AlignedEndingVa < (ULONG_PTR)HighestAddressToEndAt) {
  1100. if ( SizeOfRange < ((ULONG_PTR)HighestAddressToEndAt - AlignedEndingVa)) {
  1101. *Base = MI_ALIGN_TO_SIZE(
  1102. ((ULONG_PTR)HighestAddressToEndAt - SizeOfRange),
  1103. Alignment);
  1104. return STATUS_SUCCESS;
  1105. }
  1106. }
  1107. //
  1108. // Walk the tree backwards looking for a fit.
  1109. //
  1110. OptimalStartVpn = MI_VA_TO_VPN (OptimalStart);
  1111. AlignmentVpn = MI_VA_TO_VPN (Alignment);
  1112. for (;;) {
  1113. PreviousNode = MiGetPreviousNode (Node);
  1114. if (PreviousNode != (PMMADDRESS_NODE)NULL) {
  1115. //
  1116. // Is the ending Va below the top of the address to end at.
  1117. //
  1118. if (PreviousNode->EndingVpn < OptimalStartVpn) {
  1119. if ((SizeOfRange >> PAGE_SHIFT) <=
  1120. ((ULONG_PTR)Node->StartingVpn -
  1121. (ULONG_PTR)MI_ROUND_TO_SIZE(1 + PreviousNode->EndingVpn,
  1122. AlignmentVpn))) {
  1123. //
  1124. // See if the optimal start will fit between these
  1125. // two VADs.
  1126. //
  1127. if ((OptimalStartVpn > PreviousNode->EndingVpn) &&
  1128. (HighestVpn < Node->StartingVpn)) {
  1129. *Base = OptimalStart;
  1130. return STATUS_SUCCESS;
  1131. }
  1132. //
  1133. // Check to ensure that the ending address aligned upwards
  1134. // is not greater than the starting address.
  1135. //
  1136. if ((ULONG_PTR)Node->StartingVpn >
  1137. (ULONG_PTR)MI_ROUND_TO_SIZE(1 + PreviousNode->EndingVpn,
  1138. AlignmentVpn)) {
  1139. *Base = MI_ALIGN_TO_SIZE(
  1140. (ULONG_PTR)MI_VPN_TO_VA (Node->StartingVpn) - SizeOfRange,
  1141. Alignment);
  1142. return STATUS_SUCCESS;
  1143. }
  1144. }
  1145. }
  1146. } else {
  1147. //
  1148. // No more descriptors, check to see if this fits into the remainder
  1149. // of the address space.
  1150. //
  1151. if (Node->StartingVpn > MI_VA_TO_VPN (MM_LOWEST_USER_ADDRESS)) {
  1152. if ((SizeOfRange >> PAGE_SHIFT) <=
  1153. ((ULONG_PTR)Node->StartingVpn - MI_VA_TO_VPN (MM_LOWEST_USER_ADDRESS))) {
  1154. //
  1155. // See if the optimal start will fit between these
  1156. // two VADs.
  1157. //
  1158. if (HighestVpn < Node->StartingVpn) {
  1159. *Base = OptimalStart;
  1160. return STATUS_SUCCESS;
  1161. }
  1162. *Base = MI_ALIGN_TO_SIZE(
  1163. (ULONG_PTR)MI_VPN_TO_VA (Node->StartingVpn) - SizeOfRange,
  1164. Alignment);
  1165. return STATUS_SUCCESS;
  1166. }
  1167. }
  1168. return STATUS_NO_MEMORY;
  1169. }
  1170. Node = PreviousNode;
  1171. }
  1172. }
  1173. #if DBG
  1174. VOID
  1175. NodeTreeWalk (
  1176. PMMADDRESS_NODE Start
  1177. )
  1178. {
  1179. if (Start == (PMMADDRESS_NODE)NULL) {
  1180. return;
  1181. }
  1182. NodeTreeWalk(Start->LeftChild);
  1183. DbgPrint("Node at 0x%p start 0x%p end 0x%p \n",
  1184. (ULONG_PTR)Start,
  1185. MI_VPN_TO_VA(Start->StartingVpn),
  1186. (ULONG_PTR)MI_VPN_TO_VA (Start->EndingVpn) | (PAGE_SIZE - 1));
  1187. NodeTreeWalk(Start->RightChild);
  1188. return;
  1189. }
  1190. #endif //DBG