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.

931 lines
23 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. suballoc.c
  5. Abstract:
  6. This module contains code for managing a paritially commited address
  7. space. It handles allocation of chunks of memory smaller than the
  8. commit granularity. It commits and decommits memory as needed using
  9. the supplied function for committing and decommitting memory. The
  10. structures used for tracking the address space are allocated outside
  11. of the specified addresss space.
  12. Author:
  13. Dave Hastings (daveh) creation-date 21-Jan-1994
  14. Notes:
  15. Since this package does not actually access memory in the address space
  16. it is managing, it will work as well with real linear addresses or
  17. "Intel Addresses" such as would be encountered with the Insignia Emulator
  18. on risc.
  19. Revision History:
  20. --*/
  21. #include "suballcp.h"
  22. PVOID
  23. SAInitialize(
  24. ULONG BaseAddress,
  25. ULONG Size,
  26. PSACOMMITROUTINE CommitRoutine,
  27. PSACOMMITROUTINE DecommitRoutine,
  28. PSAMEMORYMOVEROUTINE MemoryMoveRoutine
  29. )
  30. /*++
  31. Routine Description:
  32. This function performs initialization of the sub allocation package
  33. for the specified addresss range. It allocates the data structures
  34. necessary to track the allocations
  35. Arguments:
  36. BaseAddress -- Supplies the base address of the address space to
  37. sub allocate.
  38. Size -- Supplies the size in bytes of the address space to sub allocate.
  39. CommitRoutine -- Supplies a pointer to the routine used to commit regions
  40. of the address space.
  41. Return Value:
  42. If the function was successful it returns a pointer to the sub-allocation
  43. data structures. Otherwise it returns NULL.
  44. --*/
  45. {
  46. PSUBALLOCATIONDATA SubAlloc;
  47. ULONG SASize;
  48. ASSERT_STEPTHROUGH;
  49. //
  50. // Asserts to insure that everything is as we expect it to be
  51. //
  52. ASSERT(((COMMIT_GRANULARITY % SUBALLOC_GRANULARITY) == 0));
  53. //
  54. // Allocate the tracking structure
  55. //
  56. // SUBALLOCATIONDATA is declared with 1 uchar for the bitmap.
  57. // this is the reason for subtracting one from the total size
  58. // calculation.
  59. //
  60. SASize = sizeof(SUBALLOCATIONDATA)
  61. + (Size / SUBALLOC_GRANULARITY) / sizeof(UCHAR) - 1;
  62. SubAlloc = malloc(SASize);
  63. if (SubAlloc == NULL) {
  64. return NULL;
  65. }
  66. //
  67. // Initialize the structure
  68. //
  69. RtlZeroMemory(SubAlloc, SASize);
  70. INIT_SUBALLOC_SIGNATURE(SubAlloc);
  71. SubAlloc->BaseAddress = BaseAddress;
  72. SubAlloc->Size = Size / SUBALLOC_GRANULARITY;
  73. SubAlloc->CommitRoutine = CommitRoutine;
  74. SubAlloc->DecommitRoutine = DecommitRoutine;
  75. SubAlloc->MoveMemRoutine = MemoryMoveRoutine;
  76. return SubAlloc;
  77. }
  78. BOOL
  79. SAQueryFree(
  80. PVOID SubAllocation,
  81. PULONG FreeBytes,
  82. PULONG LargestFreeBlock
  83. )
  84. /*++
  85. Routine Description:
  86. This routine returns the number of free bytes in the
  87. sub allocated address space.
  88. Arguments:
  89. SubAllocation -- Supplies the pointer returned by SAInitialize
  90. FreeBytes -- Returns the number of free bytes
  91. Return Value:
  92. TRUE -- if successful, and FreeBytes contains the number of free bytes.
  93. FALSE otherwise
  94. --*/
  95. {
  96. ULONG i, FreeCount;
  97. PSUBALLOCATIONDATA SubAlloc;
  98. ULONG TempLargest, LargestBlock;
  99. ASSERT_STEPTHROUGH;
  100. //
  101. // Get a typed pointer
  102. //
  103. SubAlloc = SubAllocation;
  104. //
  105. // Make sure that we have what we think we do
  106. //
  107. ASSERT_SUBALLOC(SubAlloc);
  108. //
  109. // Count the free chunks and find largest block
  110. //
  111. FreeCount = 0;
  112. LargestBlock = 0;
  113. i = 0;
  114. while (i < SubAlloc->Size) {
  115. TempLargest = 0;
  116. while (
  117. (i < SubAlloc->Size) &&
  118. (GET_BIT_FROM_CHAR_ARRAY(SubAlloc->Allocated, i) == 0)
  119. ){
  120. FreeCount++;
  121. TempLargest++;
  122. i++;
  123. }
  124. if (TempLargest > LargestBlock) {
  125. LargestBlock = TempLargest;
  126. }
  127. //
  128. // Skip allocated blocks
  129. //
  130. while (
  131. (i < SubAlloc->Size) &&
  132. (GET_BIT_FROM_CHAR_ARRAY(SubAlloc->Allocated, i) == 1)
  133. ) {
  134. i++;
  135. }
  136. }
  137. *FreeBytes = FreeCount * SUBALLOC_GRANULARITY;
  138. *LargestFreeBlock = LargestBlock * SUBALLOC_GRANULARITY;
  139. return TRUE;
  140. }
  141. BOOL
  142. SAAllocate(
  143. PVOID SubAllocation,
  144. ULONG Size,
  145. PULONG Address
  146. )
  147. /*++
  148. Routine Description:
  149. This function allocates a portion of the address space described by
  150. SubAllocation. If necessary, it will commit additional blocks.
  151. Size is rounded up to the next higher multiple of SUBALLOC_GRANULARITY.
  152. Arguments:
  153. SubAllocation -- Supplies the pointer returned by SAInitialize.
  154. Size -- Supplies the size in bytes of the region to allocate.
  155. Address -- Returns the address of the region allocated.
  156. Return Value:
  157. TRUE if successful. If false is returned, no address is returned.
  158. Notes:
  159. Zero is a valid value for the returned address.
  160. --*/
  161. {
  162. ULONG AllocateSize, i, CurrentChunk;
  163. BOOL Done = FALSE;
  164. PSUBALLOCATIONDATA SubAlloc;
  165. BOOL Success;
  166. ASSERT_STEPTHROUGH;
  167. //
  168. // Get a typed pointer. This allows us to avoid
  169. // casting every time we access the pointer.
  170. //
  171. SubAlloc = SubAllocation;
  172. ASSERT_SUBALLOC(SubAlloc);
  173. //
  174. // Round size and make into number of blocks
  175. //
  176. AllocateSize = ALLOC_ROUND(Size);
  177. //
  178. // Find a chunk that is free
  179. //
  180. // We need this loop in spite of the fact that we
  181. // are keeping an index to the first free block.
  182. // We update this pointer somewhat heuristically.
  183. // If we allocate the first free block, we update
  184. // the index to point past the block we allocated.
  185. // We don't repeat the free scan however, so the
  186. // index may actually point to an allocated block.
  187. //
  188. CurrentChunk = SubAlloc->FirstFree;
  189. while (CurrentChunk < SubAlloc->Size) {
  190. if (GET_BIT_FROM_CHAR_ARRAY(SubAlloc->Allocated, CurrentChunk) == 0) {
  191. SubAlloc->FirstFree = CurrentChunk;
  192. break;
  193. }
  194. CurrentChunk++;
  195. }
  196. //
  197. // Find a block that is big enough
  198. //
  199. while (!Done && (CurrentChunk < SubAlloc->Size)){
  200. //
  201. // Search for a contiguous block large enough
  202. //
  203. for (i = 0; i < AllocateSize; i++){
  204. //
  205. // Insure we don't walk off the end of the data structure
  206. //
  207. if ((i + CurrentChunk) >= SubAlloc->Size){
  208. CurrentChunk += i; // Satisfy termination condition
  209. break;
  210. }
  211. //
  212. // Check to see if this chunk is free
  213. //
  214. if (
  215. GET_BIT_FROM_CHAR_ARRAY(
  216. SubAlloc->Allocated,
  217. i + CurrentChunk
  218. )
  219. == 0
  220. ){
  221. continue;
  222. } else {
  223. //
  224. // Chunk is not free, so advance the search
  225. //
  226. CurrentChunk += i + 1;
  227. break;
  228. }
  229. }
  230. //
  231. // Check to see if we found a chunk
  232. //
  233. if (i == AllocateSize) {
  234. Done = TRUE;
  235. }
  236. }
  237. //
  238. // If we found the chunk, commit it (if necessary) and mark it allocated
  239. //
  240. // N.B. It is important to commit it first, and mark it allocated last,
  241. // because we use the allocated bits to determine if the chunk is
  242. // committed. If all of the allocated bits are clear, the chunk
  243. // is not commited yet.
  244. //
  245. if (Done) {
  246. //
  247. // Allocate and commit the memory
  248. //
  249. Success = AllocateChunkAt(
  250. SubAlloc,
  251. AllocateSize,
  252. CurrentChunk,
  253. FALSE
  254. );
  255. if (!Success) {
  256. return FALSE;
  257. }
  258. *Address = BLOCK_INDEX_TO_ADDRESS(SubAlloc, CurrentChunk);
  259. ASSERT((SubAlloc->BaseAddress <= *Address) &&
  260. ((SubAlloc->BaseAddress + SubAlloc->Size * SUBALLOC_GRANULARITY)
  261. > *Address));
  262. #if 0
  263. {
  264. char Buffer[80];
  265. sprintf(Buffer, "SAAllocate: Allocating at address %lx\n", *Address);
  266. OutputDebugString(Buffer);
  267. }
  268. #endif
  269. return TRUE;
  270. } else {
  271. return FALSE;
  272. }
  273. }
  274. BOOL
  275. SAFree(
  276. PVOID SubAllocation,
  277. ULONG Size,
  278. ULONG Address
  279. )
  280. /*++
  281. Routine Description:
  282. This routine frees a sub-allocated chunk of memory. If the
  283. entire commited block (or blocks) that the specified chunk
  284. belongs to are free, the chunks are decommitted. Address is
  285. rounded down to the next lower SUBALLOC_GRANULARITY boundary.
  286. size is rounded up to the next higher multiple of SUBALLOC_GRANULARITY.
  287. Arguments:
  288. SubAllocation -- Supplies the pointer returned by SAInitialize.
  289. Size -- Supplies the size in bytes of the region to free.
  290. Address -- Supplies the address of the region to free.
  291. Return Value:
  292. TRUE if successful.
  293. Notes:
  294. It is possible to free a different size at a particular
  295. address than was allocated. This will not cause the
  296. SubAllocation package any problems.
  297. BUGBUG decommit error handling?
  298. --*/
  299. {
  300. PSUBALLOCATIONDATA SubAlloc;
  301. ULONG AllocatedSize, BaseBlock;
  302. SubAlloc = SubAllocation;
  303. ASSERT_SUBALLOC(SubAlloc);
  304. //
  305. // Make sure that the space to free is really ours
  306. // (Entire block within range, and correctly aligned)
  307. if (
  308. (Address < SubAlloc->BaseAddress) ||
  309. (Address >= (SubAlloc->BaseAddress + SubAlloc->Size * SUBALLOC_GRANULARITY)) ||
  310. ((Address + Size) > (SubAlloc->BaseAddress + SubAlloc->Size * SUBALLOC_GRANULARITY)) ||
  311. (Address % SUBALLOC_GRANULARITY)
  312. ) {
  313. return FALSE;
  314. }
  315. //
  316. // Turn Address into Block #
  317. //
  318. BaseBlock = ADDRESS_TO_BLOCK_INDEX(SubAlloc, Address);
  319. //
  320. // Round up the size
  321. //
  322. AllocatedSize = ALLOC_ROUND(Size);
  323. return FreeChunk(
  324. SubAlloc,
  325. AllocatedSize,
  326. BaseBlock
  327. );
  328. }
  329. BOOL
  330. SAReallocate(
  331. PVOID SubAllocation,
  332. ULONG OriginalSize,
  333. ULONG OriginalAddress,
  334. ULONG NewSize,
  335. PULONG NewAddress
  336. )
  337. /*++
  338. Routine Description:
  339. This routine reallocates a sub allocated block of memory.
  340. The sizes are rounded up to the next SUBALLOC_GRANULARITY.
  341. The Original address is rounded down to the next SUBALLOC_GRANULARITY
  342. boundary. Only min(OriginalSize, NewSize) bytes of data are copied to
  343. the new block. The block changed in place if possible.
  344. The following is an enumation of the possible successful reallocs.
  345. 1. NewSize < OriginalSize
  346. free block tail
  347. 2. NewSize > OriginalSize
  348. a.) Sufficient freespace at OriginalAddress + OriginalSize
  349. Allocate the space at the tail of the block
  350. b.) Sufficient free space at OriginalAddress - size delta
  351. Allocate the space at the beginning of the block, and
  352. copy the data.
  353. c.) Sufficient space elsewhere in the address space
  354. Allocate the space, and copy the block.
  355. If none of the above is true, the realloc fails. The above are
  356. in order of preference.
  357. Arguments:
  358. SubAllocation -- Supplies the pointer returned by SAInitialize.
  359. OriginalSize -- Supplies the old size in bytes of the block.
  360. OriginalAddress -- Supplies the old address of the block.
  361. NewSize -- Supplies the new size in bytes of the block.
  362. NewAddress -- Returns the new address of the block.
  363. Return Value:
  364. True if successful. If unsucessful, no allocation is changed.
  365. Notes:
  366. If the caller does not supply the correct original size for the block,
  367. some memory may be lost, and the block may be moved unnecessarily.
  368. --*/
  369. {
  370. ULONG OriginalSizeBlock, NewSizeBlock, OriginalIndex;
  371. ULONG AdditionalBlocks, Address;
  372. BOOL Success;
  373. PSUBALLOCATIONDATA SubAlloc;
  374. SubAlloc = SubAllocation;
  375. ASSERT_SUBALLOC(SubAlloc);
  376. //
  377. // Convert Sizes and address to blocks
  378. //
  379. OriginalSizeBlock = ALLOC_ROUND(OriginalSize);
  380. NewSizeBlock = ALLOC_ROUND(NewSize);
  381. OriginalIndex = ADDRESS_TO_BLOCK_INDEX(SubAlloc, OriginalAddress);
  382. //
  383. // Check to see if we are changing the size of the block
  384. //
  385. // N.B. Because we have rounded the numbers to an allocation
  386. // boundary, the following test may succeed (correctly)
  387. // even though OriginalSize != NewSize
  388. //
  389. if (OriginalSizeBlock == NewSizeBlock) {
  390. *NewAddress = OriginalAddress;
  391. return TRUE;
  392. }
  393. //
  394. // Check to see if the block is getting smaller
  395. //
  396. if (OriginalSizeBlock > NewSizeBlock) {
  397. //
  398. // Free the tail of the block
  399. //
  400. Success = FreeChunk(
  401. SubAlloc,
  402. OriginalSizeBlock - NewSizeBlock,
  403. OriginalIndex + NewSizeBlock
  404. );
  405. if (Success) {
  406. *NewAddress = OriginalAddress;
  407. return TRUE;
  408. } else {
  409. return FALSE;
  410. }
  411. }
  412. //
  413. // Try to allocate the space at the end of the block
  414. //
  415. AdditionalBlocks = NewSizeBlock - OriginalSizeBlock;
  416. Success = AllocateChunkAt(
  417. SubAlloc,
  418. AdditionalBlocks,
  419. OriginalIndex + OriginalSizeBlock,
  420. TRUE
  421. );
  422. //
  423. // If there was space, return success
  424. //
  425. if (Success) {
  426. *NewAddress = OriginalAddress;
  427. return TRUE;
  428. }
  429. //
  430. // Try to allocate space at the beginning of the block
  431. //
  432. Success = AllocateChunkAt(
  433. SubAlloc,
  434. AdditionalBlocks,
  435. OriginalIndex - AdditionalBlocks,
  436. TRUE
  437. );
  438. if (Success) {
  439. //
  440. // Move the data
  441. //
  442. // N.B. We can't just call RtlMoveMemory,
  443. // because we don't know the correspondence
  444. // between the address space we manage, and
  445. // real linear addresses. In addition, for
  446. // risc NTVDM, some additional work may have
  447. // to be done (such as flushing caches).
  448. //
  449. SubAlloc->MoveMemRoutine(
  450. BLOCK_INDEX_TO_ADDRESS(
  451. SubAlloc,
  452. (OriginalIndex - AdditionalBlocks)
  453. ),
  454. OriginalAddress,
  455. OriginalSize
  456. );
  457. *NewAddress = BLOCK_INDEX_TO_ADDRESS(
  458. SubAlloc,
  459. (OriginalIndex - AdditionalBlocks)
  460. );
  461. return TRUE;
  462. }
  463. //
  464. // Attempt to allocate a new block
  465. //
  466. Success = SAAllocate(
  467. SubAlloc,
  468. NewSize,
  469. &Address
  470. );
  471. if (Success) {
  472. //
  473. // Move the data
  474. //
  475. // N.B. We could copy the data, but it would
  476. // require one more function pointer.
  477. //
  478. SubAlloc->MoveMemRoutine(
  479. Address,
  480. OriginalAddress,
  481. OriginalSize
  482. );
  483. SAFree(
  484. SubAlloc,
  485. OriginalSize,
  486. OriginalAddress
  487. );
  488. //
  489. // Indicate success
  490. //
  491. *NewAddress = Address;
  492. return TRUE;
  493. }
  494. //
  495. // All reallocation strategies failed.
  496. //
  497. return FALSE;
  498. }
  499. BOOL
  500. AllocateChunkAt(
  501. PSUBALLOCATIONDATA SubAlloc,
  502. ULONG Size,
  503. ULONG BlockIndex,
  504. BOOLEAN CheckFree
  505. )
  506. /*++
  507. Routine Description:
  508. This routine attempts to allocate the specified chunk
  509. of memory. It first checks to make sure that it is
  510. free.
  511. Arguments:
  512. SubAlloc -- Supplies a pointer to the suballocation data
  513. Size -- Supplies the size of the chunk to allocate
  514. BlockIndex -- Supplies the index of the beginning of the block
  515. to allocate
  516. CheckFree -- Supplies an indication of whether to check and see
  517. if the memory is free. If this routine is called from
  518. SAAllocate, we know the memory is free.
  519. Return Value:
  520. True if successful
  521. --*/
  522. {
  523. ULONG i;
  524. if (CheckFree) {
  525. //
  526. // Verify that the memory is free
  527. //
  528. for (i = 0; i < Size; i++){
  529. //
  530. // Insure we don't walk off the end of the data structure
  531. //
  532. if ((i + BlockIndex) >= SubAlloc->Size){
  533. break;
  534. }
  535. //
  536. // Check to see if this chunk is free
  537. //
  538. if (
  539. GET_BIT_FROM_CHAR_ARRAY(
  540. SubAlloc->Allocated,
  541. i + BlockIndex
  542. )
  543. == 0
  544. ){
  545. continue;
  546. } else {
  547. //
  548. // Chunk is not free
  549. //
  550. break;
  551. }
  552. }
  553. //
  554. // If the chunk is not free
  555. //
  556. if (i != Size) {
  557. return FALSE;
  558. }
  559. }
  560. //
  561. // Commit the chunk
  562. //
  563. if (!CommitChunk(SubAlloc, BlockIndex, Size, SACommit)) {
  564. return FALSE;
  565. }
  566. //
  567. // Mark it as allocated
  568. //
  569. for (i = BlockIndex; i < BlockIndex + Size; i++) {
  570. SET_BIT_IN_CHAR_ARRAY(SubAlloc->Allocated, i);
  571. }
  572. //
  573. // Update the pointer to the first free block
  574. //
  575. if (BlockIndex == SubAlloc->FirstFree) {
  576. SubAlloc->FirstFree += Size;
  577. }
  578. return TRUE;
  579. }
  580. BOOL
  581. FreeChunk(
  582. PSUBALLOCATIONDATA SubAlloc,
  583. ULONG Size,
  584. ULONG BlockIndex
  585. )
  586. /*++
  587. Routine Description:
  588. This routine actually marks the memory as free
  589. and decommits it as necessary.
  590. Arguments:
  591. SubAlloc -- Supplies a pointer to the suballocation data
  592. Size -- Supplies the size (in SUBALLOC_GRANULARITY) of the
  593. region to free
  594. BlockIndex -- Supplies the index of the begining of the region
  595. (in SUBALLOC_GRANULARITY)
  596. Return Value:
  597. TRUE if successful.
  598. --*/
  599. {
  600. SUBALLOCATIONDATA LocalSubAlloc;
  601. ULONG CurrentBlock;
  602. BOOL Success;
  603. //
  604. // Save a copy of the suballoc data
  605. //
  606. LocalSubAlloc = *SubAlloc;
  607. //
  608. // reset free pointer
  609. //
  610. if (BlockIndex < SubAlloc->FirstFree) {
  611. SubAlloc->FirstFree = BlockIndex;
  612. }
  613. //
  614. // Mark the region as free
  615. //
  616. // N.B. We mark the block as free before decommitting it, because
  617. // the decommit code will use the allocated bits to determine which
  618. // parts can be decommitted.
  619. //
  620. for (CurrentBlock = BlockIndex;
  621. CurrentBlock < BlockIndex + Size;
  622. CurrentBlock++
  623. ) {
  624. CLEAR_BIT_IN_CHAR_ARRAY(SubAlloc->Allocated, CurrentBlock);
  625. }
  626. //
  627. // Decommit the memory
  628. //
  629. Success = CommitChunk(SubAlloc, BlockIndex, Size, SADecommit);
  630. if (!Success) {
  631. *SubAlloc = LocalSubAlloc;
  632. }
  633. return Success;
  634. }
  635. BOOL
  636. CommitChunk(
  637. PSUBALLOCATIONDATA SubAlloc,
  638. ULONG StartChunk,
  639. ULONG Size,
  640. COMMIT_ACTION Action
  641. )
  642. /*++
  643. Routine Description:
  644. This routine commits a chunk of memory. Part or all
  645. of the specified chunk may already be commited.
  646. Arguments:
  647. SubAllocation -- Supplies a pointer to the suballocation data
  648. StartChunk -- Supplies the relative start of the region to be
  649. committed (in SUBALLOCATION_GRANULARITY)
  650. Size -- Supplies the size of the chunk to be commited
  651. (in SUBALLOCATION_GRANULARITY)
  652. Return Value:
  653. TRUE -- If the block was successfully committed (or already committed)
  654. FALSE -- Otherwise
  655. Notes:
  656. This routine depends on the allocated bits in SubAlloc to determine
  657. whether memory is committed. When memory is to be committed, CommitBlock
  658. must be called before the Allocated bits are modified. When memory is
  659. decommitted, the Allocated bits must be modified before CommitBlock is
  660. called.
  661. --*/
  662. {
  663. ULONG FirstBlock, LastBlock, CurrentBlock;
  664. NTSTATUS Status;
  665. ASSERT_STEPTHROUGH;
  666. ASSERT_SUBALLOC(SubAlloc);
  667. //
  668. // Round Start down to next COMMIT_GRANULARITY and convert to block #
  669. //
  670. FirstBlock = (StartChunk * SUBALLOC_GRANULARITY) / COMMIT_GRANULARITY;
  671. //
  672. // Round StartChunk + size up to next COMMIT_GRANULARITY
  673. //
  674. LastBlock = ((StartChunk + Size) * SUBALLOC_GRANULARITY +
  675. (COMMIT_GRANULARITY - 1)) / COMMIT_GRANULARITY;
  676. for (
  677. CurrentBlock = FirstBlock;
  678. CurrentBlock < LastBlock;
  679. CurrentBlock++
  680. ) {
  681. //
  682. // If the block is not committed, either commit it or decommit it,
  683. // depending on the value of Action.
  684. //
  685. if (!IsBlockCommitted(SubAlloc, CurrentBlock)) {
  686. if (Action == SACommit) {
  687. Status = (SubAlloc->CommitRoutine)(
  688. CurrentBlock * COMMIT_GRANULARITY + SubAlloc->BaseAddress,
  689. COMMIT_GRANULARITY
  690. );
  691. } else if (Action == SADecommit) {
  692. Status = (SubAlloc->DecommitRoutine)(
  693. CurrentBlock * COMMIT_GRANULARITY + SubAlloc->BaseAddress,
  694. COMMIT_GRANULARITY
  695. );
  696. }
  697. if (Status != STATUS_SUCCESS) {
  698. //
  699. // Bugbug -- decommit any blocks committed here
  700. //
  701. return FALSE;
  702. }
  703. }
  704. }
  705. return TRUE;
  706. }
  707. BOOL
  708. IsBlockCommitted(
  709. PSUBALLOCATIONDATA SubAlloc,
  710. ULONG Block
  711. )
  712. /*++
  713. Routine Description:
  714. This routine checks to see if a particular block of the
  715. suballocation is committed.
  716. Arguments:
  717. SubAlloc -- Supplies a pointer to the suballocation data
  718. Block -- Supplies the number of the block to check
  719. Return Value:
  720. TRUE -- if the block is committed
  721. FALSE -- if the block is not committed
  722. Notes:
  723. The return value is based on the state of the bits in the
  724. suballocation data, not on information from the NT memory
  725. manager.
  726. --*/
  727. {
  728. BOOL Committed = FALSE;
  729. ULONG i;
  730. ASSERT_STEPTHROUGH;
  731. ASSERT_SUBALLOC(SubAlloc);
  732. //
  733. // Check the bits for each of the suballoc blocks in the
  734. // commit block
  735. //
  736. for (i = 0; i < COMMIT_GRANULARITY / SUBALLOC_GRANULARITY; i++) {
  737. //
  738. // Check to see if this suballoc block is allocated
  739. //
  740. if (
  741. GET_BIT_FROM_CHAR_ARRAY(
  742. SubAlloc->Allocated,
  743. i + Block * COMMIT_GRANULARITY / SUBALLOC_GRANULARITY
  744. )
  745. ) {
  746. Committed = TRUE;
  747. break;
  748. }
  749. }
  750. return Committed;
  751. }