test: memory.c File Reference

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# memory.c File Reference

`#include "precomp.h"`

Go to the source code of this file.

## Classes

struct | _SEGMENT_HEADER
struct | _FREE_HEADER
struct | _BUSY_HEADER
struct | _HEAP_HEADER

## Defines

#define | FLAGS_FREE 0x00000000
#define | FLAGS_BUSY 0x00000001
#define | FLAGS_MASK 0x00000003
#define | ALLOCATION_GRANULARITY 16
#define | HEAP_ZERO_EXTRA_MEMORY 0x00000008

## Typedefs

typedef _SEGMENT_HEADER | SEGMENT_HEADER
typedef _SEGMENT_HEADER * | PSEGMENT_HEADER
typedef _FREE_HEADER | FREE_HEADER
typedef _FREE_HEADER * | PFREE_HEADER
typedef _BUSY_HEADER | BUSY_HEADER
typedef _BUSY_HEADER * | PBUSY_HEADER
typedef _HEAP_HEADER | HEAP_HEADER
typedef _HEAP_HEADER * | PHEAP_HEADER

## Functions

PVOID | AlRtCreateHeap (IN ULONG Flags, IN PVOID HeapBase, IN ULONG Size)
BOOLEAN | AlRtValidateHeap (IN PVOID HeapHandle, IN BOOLEAN DumpHeap)
PVOID | AlRtAllocateHeap (IN PVOID HeapHandle, IN ULONG Size)
PVOID | AlRtFreeHeap (IN PVOID HeapHandle, IN PVOID BaseAddress)
PVOID | AlRtReAllocateHeap (IN PVOID HeapHandle, IN PVOID BaseAddress, IN ULONG Size)
ARC_STATUS | AlMemoryInitialize (ULONG StackPages, ULONG HeapPages)
PVOID | AlAllocateHeap (IN ULONG Size)
PVOID | AlDeallocateHeap (IN PVOID HeapAddress)
PVOID | AlReallocateHeap (IN PVOID HeapAddress, IN ULONG NewSize)
BOOLEAN | AlValidateHeap (IN BOOLEAN DumpHeap)

## Variables

ULONG | AlHeapFree
ULONG | AlHeapLimit
PVOID | HeapHandle

## Define Documentation

#define ALLOCATION_GRANULARITY 16

| Definition at line 61 of file memory.c. Referenced by AlRtAllocateHeap(), AlRtCreateHeap(), AlRtFreeHeap(), and AlRtReAllocateHeap().

#define FLAGS_BUSY 0x00000001

| Definition at line 52 of file memory.c. Referenced by AlRtAllocateHeap(), AlRtFreeHeap(), and AlRtReAllocateHeap().

#define FLAGS_FREE 0x00000000

| Definition at line 51 of file memory.c.

#define FLAGS_MASK 0x00000003

| Definition at line 53 of file memory.c. Referenced by AlRtFreeHeap(), and AlRtReAllocateHeap().

#define HEAP_ZERO_EXTRA_MEMORY 0x00000008

| Definition at line 107 of file memory.c. Referenced by AlMemoryInitialize(), and AlRtCreateHeap().

## Typedef Documentation

typedef struct _BUSY_HEADER BUSY_HEADER

typedef struct _FREE_HEADER FREE_HEADER

typedef struct _HEAP_HEADER HEAP_HEADER

typedef struct _BUSY_HEADER * PBUSY_HEADER

| Referenced by AlRtAllocateHeap(), AlRtFreeHeap(), and AlRtReAllocateHeap().

typedef struct _FREE_HEADER * PFREE_HEADER

| Referenced by AlRtAllocateHeap(), AlRtCreateHeap(), and AlRtFreeHeap().

typedef struct _HEAP_HEADER * PHEAP_HEADER

| Referenced by AlRtAllocateHeap(), AlRtCreateHeap(), AlRtFreeHeap(), and AlRtReAllocateHeap().

typedef struct _SEGMENT_HEADER * PSEGMENT_HEADER

| Referenced by AlRtAllocateHeap(), AlRtFreeHeap(), and AlRtReAllocateHeap().

typedef struct _SEGMENT_HEADER SEGMENT_HEADER

## Function Documentation

PVOID AlAllocateHeap | ( | IN ULONG | Size | ) |

Definition at line 1113 of file memory.c.

References AlRtAllocateHeap(), HeapHandle, and Size.

Referenced by AlAddMenuItem(), AlCombinePaths(), AlGetEnvVarComponents(), AlNewMenu(), AlStrDup(), LowGetDiskLayout(), and LowSetDiskLayout().

    01116 {
    01117     return (AlRtAllocateHeap
    01118          (
    01119          HeapHandle,
    01120          Size
    01121          ));
    01122
    01123 }

PVOID AlDeallocateHeap | ( | IN PVOID | HeapAddress | ) |

Definition at line 1134 of file memory.c.

References AlRtFreeHeap(), and HeapHandle.

Referenced by AlFreeArray(), AlFreeEnvVarComponents(), AlFreeMenu(), AlGetBase(), AlpFreeComponents(), LowGetDiskLayout(), and LowSetDiskLayout().

    01137 {
    01138     return (AlRtFreeHeap
    01139         (
    01140         HeapHandle,
    01141         HeapAddress
    01142         ));
    01143 }

ARC_STATUS AlMemoryInitialize | ( | ULONG | StackPages,
|  | ULONG | HeapPages
| ) |

Definition at line 991 of file memory.c.

References AlHeapFree, AlHeapLimit, AlRtCreateHeap(), ArcGetMemoryDescriptor, _MEMORY_DESCRIPTOR::BasePage, ENOMEM, ESUCCESS, HEAP_ZERO_EXTRA_MEMORY, HeapHandle, KSEG0_BASE, MemoryFree, MemoryLoadedProgram, _MEMORY_DESCRIPTOR::MemoryType, NULL, PAGE_SHIFT, _MEMORY_DESCRIPTOR::PageCount, and PMEMORY_DESCRIPTOR.

Referenced by main().

    00998                    :
    00999
    01000     This routine allocates stack space for the OS loader, initializes
    01001     heap storage, and initializes the memory allocation list.
    01002
    01003 Arguments:
    01004
    01005     None.
    01006
    01007 Return Value:
    01008
    01009     ESUCCESS is returned if the initialization is successful. Otherwise,
    01010     ENOMEM is returned.
    01011
    01012 --*/
    01013
    01014 {
    01015
    01016     PMEMORY_DESCRIPTOR FreeDescriptor;
    01017     PMEMORY_DESCRIPTOR ProgramDescriptor;
    01018
    01019     //
    01020     // Find the memory descriptor that describes the allocation for the OS
    01021     // loader itself.
    01022     //
    01023
    01024     ProgramDescriptor = NULL;
    01025     while ((ProgramDescriptor = ArcGetMemoryDescriptor(ProgramDescriptor)) != NULL) {
    01026         if (ProgramDescriptor->MemoryType == MemoryLoadedProgram) {
    01027             break;
    01028         }
    01029     }
    01030
    01031     //
    01032     // If a loaded program memory descriptor was found, then it must be
    01033     // for the OS loader since that is the only program that can be loaded.
    01034     // If a loaded program memory descriptor was not found, then firmware
    01035     // is not functioning properly and an unsuccessful status is returned.
    01036     //
    01037
    01038     if (ProgramDescriptor == NULL) {
    01039         return ENOMEM;
    01040     }
    01041
    01042     //
    01043     // Find the free memory descriptor that is just below the loaded
    01044     // program in memory. There should be several megabytes of free
    01045     // memory just preceeding the OS loader.
    01046     //
    01047
    01048     FreeDescriptor = NULL;
    01049     while ((FreeDescriptor = ArcGetMemoryDescriptor(FreeDescriptor)) != NULL) {
    01050         if ((FreeDescriptor->MemoryType == MemoryFree) &&
    01051             (FreeDescriptor->PageCount >= (StackPages+HeapPages))) {
    01052             break;
    01053         }
    01054     }
    01055
    01056     //
    01057     // If a free memory descriptor was not found that describes the free
    01058     // memory just below the OS loader, then firmware is not functioning
    01059     // properly and an unsuccessful status is returned.
    01060     //
    01061
    01062     if (FreeDescriptor == NULL) {
    01063         return ENOMEM;
    01064     }
    01065
    01066     //
    01067     // Check to determine if enough free memory is available for the OS
    01068     // loader stack and the heap area. If enough memory is not available,
    01069     // then return an unsuccessful status.
    01070     //
    01071
    01072     if (FreeDescriptor->PageCount < (StackPages + HeapPages)) {
    01073         return ENOMEM;
    01074     }
    01075
    01076     //
    01077     // Compute the address of the loader heap, initialize the heap
    01078     // allocation variables, and zero the heap memory.
    01079     //
    01080
    01081     AlHeapFree = KSEG0_BASE | ((ProgramDescriptor->BasePage -
    01082                 (StackPages + HeapPages)) << PAGE_SHIFT);
    01083
    01084     AlHeapLimit = AlHeapFree + (HeapPages << PAGE_SHIFT);
    01085
    01086     memset((PVOID)AlHeapFree, 0,HeapPages << PAGE_SHIFT);
    01087
    01088
    01089     //
    01090     // Changed to new heap allocater
    01091     //
    01092
    01093     if ((HeapHandle = AlRtCreateHeap
    01094             (
    01095             HEAP_ZERO_EXTRA_MEMORY,
    01096             (PVOID)AlHeapFree,
    01097             HeapPages << PAGE_SHIFT
    01098             ))
    01099             == NULL)
    01100        return ENOMEM;
    01101     else
    01102        return ESUCCESS;
    01103
    01104 }

PVOID AlReallocateHeap | ( | IN PVOID | HeapAddress,
|  | IN ULONG | NewSize
| ) |

Definition at line 1153 of file memory.c.

References AlRtReAllocateHeap(), and HeapHandle.

Referenced by AlAddMenuItem(), and LowGetDiskLayout().

    01157 {
    01158     return (AlRtReAllocateHeap
    01159         (
    01160         HeapHandle,
    01161         HeapAddress,
    01162         NewSize
    01163         ));
    01164 }

PVOID AlRtAllocateHeap | ( | IN PVOID | HeapHandle,
|  | IN ULONG | Size
| ) |

Definition at line 365 of file memory.c.

References ALLOCATION_GRANULARITY, AlPrint(), AlRtValidateHeap(), FALSE, FLAGS_BUSY, _HEAP_HEADER::FreeList, _BUSY_HEADER::HandleValue, HeapHandle, _HEAP_HEADER::Length, _FREE_HEADER::Next, NULL, PBUSY_HEADER, PFREE_HEADER, PHEAP_HEADER, PSEGMENT_HEADER, _BUSY_HEADER::Segment, _FREE_HEADER::Segment, _BUSY_HEADER::Size, _FREE_HEADER::Size, Size, _BUSY_HEADER::Spare, TRUE, and _HEAP_HEADER::ZeroExtraMemory.

Referenced by AlAllocateHeap(), and AlRtReAllocateHeap().

    00369 {
    00370     PHEAP_HEADER Heap = (PHEAP_HEADER)HeapHandle;
    00371     ULONG allocationSize;
    00372 //    PSEGMENT_HEADER Segment;
    00373     PFREE_HEADER FreeBlock;
    00374     PFREE_HEADER PreviousFreeBlock;
    00375     PFREE_HEADER NewFreeBlock;
    00376     PBUSY_HEADER BusyBlock;
    00377
    00378
    00379     //
    00380     // Validate that HeapAddress points to a HEAP_HEADER structure.
    00381     //
    00382
    00383     if (Heap->Length != sizeof( HEAP_HEADER )) {
    00384 #if DBG
    00385     AlPrint( "ALHEAP: Invalid heap header- %lx\n", Heap );
    00386 #endif // DBG
    00387         return( NULL );
    00388         }
    00389
    00390     //
    00391     // Additional check, see if the heap is valid, call the heap validation
    00392     // code, requesting it to not dump stuff.
    00393     //
    00394     if(!AlRtValidateHeap( HeapHandle, FALSE)) {
    00395
    00396 #if DBG
    00397         AlPrint("Heap validation failed\n");
    00398 #endif
    00399         return ( NULL );
    00400     }
    00401
    00402
    00403     //
    00404     // Round the requested size up to the allocation granularity.  Note
    00405     // that if the request is for 0 bytes, we still allocate memory.
    00406     //
    00407
    00408     allocationSize = ((Size ? Size : ALLOCATION_GRANULARITY) +
    00409                       sizeof( BUSY_HEADER ) +
    00410                       ALLOCATION_GRANULARITY -
    00411                       1
    00412                      ) & ~(ALLOCATION_GRANULARITY - 1);
    00413     if (allocationSize < Size) {
    00414 #if DBG
    00415     AlPrint( "ALHEAP: Invalid heap size - %lx\n", Size );
    00416 //   RtlpBreakPointHeap();
    00417 #endif // DBG
    00418         return( NULL );
    00419     }
    00420
    00421     //
    00422     // Point to the free list header.
    00423     //
    00424
    00425     FreeBlock = &Heap->FreeList;
    00426 #if DBG
    00427     if (FreeBlock->Size != 0) {
    00428     AlPrint( "ALHEAP: Heap free list HEAD hosed at %lx\n", FreeBlock );
    00429 //   RtlpBreakPointHeap();
    00430
    00431     return( NULL );
    00432         }
    00433 #endif // DBG
    00434
    00435     //
    00436     // Continuous loop.  We'll break out of the loop when we've found
    00437     // (or created) some free memory.
    00438     //
    00439
    00440     while (TRUE) {
    00441         //
    00442         // Have we reached the end of the free list?
    00443         //
    00444
    00445     if (FreeBlock->Next == NULL)
    00446         return( NULL );
    00447         else {
    00448             //
    00449             // Point to the next free block, saving a pointer to the
    00450             // previous one.
    00451             //
    00452
    00453             PreviousFreeBlock = FreeBlock;
    00454             FreeBlock = PreviousFreeBlock->Next;
    00455             }
    00456
    00457 #if DBG
    00458         if (FreeBlock->Size == 0) {
    00459         AlPrint( "ALHEAP: Heap free list ENTRY hosed at %lx\n",
    00460                       FreeBlock
    00461                     );
    00462 //       RtlpBreakPointHeap();
    00463         return( NULL );
    00464             }
    00465 #endif // DBG
    00466
    00467         //
    00468         // We haven't exhausted the free list yet.  If this block is
    00469         // large enough for what we need, break out of the while loop.
    00470         //
    00471
    00472         if (FreeBlock->Size >= allocationSize) {
    00473             break;
    00474             }
    00475
    00476         } // while ( TRUE )
    00477
    00478     //
    00479     // We have found a free block that is large enough to hold what the
    00480     // user requested.  If it's exactly the right size, simply point the
    00481     // previous free block to the successor of this free block.  If it's
    00482     // larger than what we want, we allocate from the front of the block,
    00483     // leaving the trailing part free.  Exactly the right size is fuzzy,
    00484     // as if we decide to split we need at least enough extra space for
    00485     // a free header plus some space to statisfy an allocation.
    00486     //
    00487
    00488     if ((FreeBlock->Size - allocationSize) < (2 * sizeof( FREE_HEADER ))) {
    00489         //
    00490         // If the amount of extra space is less than twice the size of
    00491         // a free header, just give the caller all the space, as the
    00492         // extra amount is too small to waste a free block on.
    00493         //
    00494
    00495         allocationSize = FreeBlock->Size;
    00496
    00497         //
    00498         // Exactly the right size.  Point previous free block to the
    00499         // next free block.
    00500         //
    00501
    00502         PreviousFreeBlock->Next = FreeBlock->Next;
    00503
    00504         }
    00505     else {
    00506
    00507         //
    00508         // More memory than we need.  Make the trailing part of the block
    00509         // into a free block.  Point the previous block to the new block
    00510         // and the new block to the next block.
    00511         //
    00512
    00513         NewFreeBlock = (PFREE_HEADER)((PCH)FreeBlock + allocationSize);
    00514         PreviousFreeBlock->Next = NewFreeBlock;
    00515         NewFreeBlock->Next = FreeBlock->Next;
    00516         NewFreeBlock->Size = FreeBlock->Size - allocationSize;
    00517         NewFreeBlock->Segment = FreeBlock->Segment;
    00518         }
    00519
    00520     //
    00521     // Set up the header for the allocated block.
    00522     //
    00523
    00524     BusyBlock = (PBUSY_HEADER)FreeBlock;
    00525     BusyBlock->Segment = (PSEGMENT_HEADER)((ULONG)FreeBlock->Segment |
    00526                                            FLAGS_BUSY
    00527                                           );
    00528     BusyBlock->Size = allocationSize;
    00529     BusyBlock->HandleValue = NULL;
    00530
    00531     if (Heap->ZeroExtraMemory) {
    00532      ULONG extraSize;
    00533
    00534      extraSize = allocationSize - Size - sizeof( BUSY_HEADER );
    00535      memset( (PCHAR)BusyBlock + (allocationSize - extraSize),
    00536             0,
    00537             extraSize
    00538               );
    00539      }
    00540
    00541 #if DBG
    00542     BusyBlock->Spare = 0;
    00543 #endif
    00544
    00545     //
    00546     // Return the address of the user portion of the allocated block.
    00547     // This is the byte following the header.
    00548     //
    00549
    00550     return( (PVOID)(BusyBlock + 1) );
    00551 } // AlRtAllocateHeap

PVOID AlRtCreateHeap | ( | IN ULONG | Flags,
|  | IN PVOID | HeapBase,
|  | IN ULONG | Size
| ) |

Definition at line 119 of file memory.c.

References ALLOCATION_GRANULARITY, _HEAP_HEADER::EndAddress, FALSE, _HEAP_HEADER::FreeList, HEAP_ZERO_EXTRA_MEMORY, _HEAP_HEADER::Length, _FREE_HEADER::Next, NULL, PFREE_HEADER, PHEAP_HEADER, _FREE_HEADER::Segment, _FREE_HEADER::Size, Size, TRUE, _HEAP_HEADER::ValidAddress, and _HEAP_HEADER::ZeroExtraMemory.

Referenced by AlMemoryInitialize().

    00127                    :
    00128
    00129     This routine initializes a heap.
    00130
    00131 Arguments:
    00132
    00133     Flags - Specifies optional attributes of the heap.
    00134
    00135         Valid Flags Values:
    00136         HEAP_ZERO_EXTRA_MEMORY. to make sure that extra memory passed
    00137                     in is zeroed out.
    00138
    00139     HeapBase - if not NULL, this specifies the base address for memory
    00140     to use as the heap.  If NULL, memory is allocated by these routines.
    00141
    00142     Size - Size of the block of memory passed in to be used as a heap
    00143
    00144 Return Value:
    00145
    00146     PVOID - a pointer to be used in accessing the created heap.
    00147
    00148 --*/
    00149
    00150 {
    00151     PHEAP_HEADER Heap = NULL;
    00152     PFREE_HEADER FreeBlock;
    00153
    00154
    00155     Heap          = (PHEAP_HEADER)HeapBase;
    00156     Heap->Length      = sizeof( HEAP_HEADER );
    00157     Heap->ZeroExtraMemory = (BOOLEAN)((Flags & HEAP_ZERO_EXTRA_MEMORY) ? TRUE : FALSE);
    00158     Heap->ValidAddress    = (PCH)Heap + ((sizeof(*Heap) + (ALLOCATION_GRANULARITY-1)) & ~(ALLOCATION_GRANULARITY-1));
    00159     Heap->EndAddress      = (PCH)Heap + Size;
    00160
    00161     //
    00162     // Initialize the free list to be a single block that starts immediately
    00163     // after the heap header.
    00164     //
    00165
    00166     FreeBlock = (PFREE_HEADER)Heap->ValidAddress;
    00167     FreeBlock->Next = NULL;
    00168     FreeBlock->Size = (ULONG)Heap->EndAddress -
    00169                       (ULONG)FreeBlock;
    00170     FreeBlock->Segment = NULL;
    00171
    00172     Heap->FreeList.Next = FreeBlock;
    00173     Heap->FreeList.Size = 0;
    00174     Heap->FreeList.Segment = NULL;
    00175
    00176     return( (PVOID)Heap );
    00177 } // AlRtCreateHeap

PVOID AlRtFreeHeap | ( | IN PVOID | HeapHandle,
|  | IN PVOID | BaseAddress
| ) |

Definition at line 555 of file memory.c.

References ALLOCATION_GRANULARITY, AlPrint(), AlRtValidateHeap(), _HEAP_HEADER::EndAddress, FALSE, FLAGS_BUSY, FLAGS_MASK, _HEAP_HEADER::FreeList, HeapHandle, _HEAP_HEADER::Length, _FREE_HEADER::Next, NULL, PBUSY_HEADER, PFREE_HEADER, PHEAP_HEADER, PSEGMENT_HEADER, _FREE_HEADER::Segment, _BUSY_HEADER::Segment, _FREE_HEADER::Size, _SEGMENT_HEADER::Size, _BUSY_HEADER::Size, TRUE, and _HEAP_HEADER::ValidAddress.

Referenced by AlDeallocateHeap(), and AlRtReAllocateHeap().

    00559 {
    00560     PHEAP_HEADER Heap = (PHEAP_HEADER)HeapHandle;
    00561     PFREE_HEADER FreeBlock;
    00562     PFREE_HEADER PreviousFreeBlock;
    00563     PFREE_HEADER SecondPrevFreeBlock;
    00564     PBUSY_HEADER BusyBlock;
    00565     PSEGMENT_HEADER BusySegment;
    00566     ULONG BusyFlags;
    00567     ULONG BusySize;
    00568
    00569     if (BaseAddress == NULL) {
    00570         return( NULL );
    00571         }
    00572
    00573     //
    00574     // Validate that HeapAddress points to a HEAP_HEADER structure.
    00575     //
    00576
    00577     if (Heap->Length != sizeof( HEAP_HEADER )) {
    00578 #if DBG
    00579     AlPrint( "ALHEAP: Invalid heap header- %lx\n", Heap );
    00580 //   RtlpBreakPointHeap();
    00581 #endif // DBG
    00582         return( BaseAddress );
    00583         }
    00584
    00585     //
    00586     // Additional check, see if the heap is valid, call the heap validation
    00587     // code, requesting it to not dump stuff.
    00588     //
    00589     if(!AlRtValidateHeap( HeapHandle, FALSE)) {
    00590
    00591 #if DBG
    00592         AlPrint("Heap validation failed\n");
    00593 #endif
    00594         return ( BaseAddress );
    00595     }
    00596
    00597
    00598     //
    00599     // Get the 'real' address of the allocation unit.  (That is, the
    00600     // address of the allocation header.)  Make sure the address lies
    00601     // within the bounds of the valid portion of the heap.
    00602     //
    00603
    00604     BusyBlock = (PBUSY_HEADER)BaseAddress - 1;
    00605     BusyFlags = (ULONG)BusyBlock->Segment & FLAGS_MASK;
    00606     BusySegment = (PSEGMENT_HEADER)((ULONG)BusyBlock->Segment & ~FLAGS_MASK);
    00607     BusySize = BusyBlock->Size;
    00608
    00609     if (BusyFlags != FLAGS_BUSY
    00610 #if DBG
    00611         || (BusySegment == NULL &&
    00612             ((PCHAR)BusyBlock < (PCHAR)Heap->ValidAddress ||
    00613          (PCHAR)BusyBlock >= (PCHAR)Heap->EndAddress
    00614             )
    00615         ) ||
    00616         (BusySegment != NULL &&
    00617             (BusyBlock < (PBUSY_HEADER)(BusySegment+1) ||
    00618              BusyBlock >= (PBUSY_HEADER)((ULONG)BusySegment + BusySegment->Size)
    00619             )
    00620         ) ||
    00621         (BusySize < ALLOCATION_GRANULARITY
    00622         ) ||
    00623         (BusySize & (ALLOCATION_GRANULARITY-1) != 0
    00624         )
    00625 #endif // DBG
    00626        ) {
    00627 #if DBG
    00628     AlPrint( "ALHEAP: Invalid Address specified to AlRtFreeHeap( %lx, %lx )\n",
    00629                   Heap,
    00630                   BaseAddress
    00631                 );
    00632 //   RtlpBreakPointHeap();
    00633 #endif // DBG
    00634         return( BaseAddress );
    00635         }
    00636
    00637
    00638     //
    00639     // Free blocks are stored in the free list in ascending order by
    00640     // base address.  As we search the free list to find the place for
    00641     // this block, we remember the previous two free blocks that we
    00642     // passed through.  These are used during combining of adjacent
    00643     // free blocks.
    00644     //
    00645
    00646     SecondPrevFreeBlock = NULL;
    00647     PreviousFreeBlock = &Heap->FreeList;
    00648 #if DBG
    00649     if (PreviousFreeBlock->Size != 0) {
    00650     AlPrint( "ALHEAP: Heap free list HEAD hosed at %lx\n",
    00651                   PreviousFreeBlock
    00652                 );
    00653 //   RtlpBreakPointHeap();
    00654
    00655         return( BaseAddress );
    00656         }
    00657 #endif // DBG
    00658
    00659     //
    00660     // Continuous loop.  We'll break out of the loop when we've found
    00661     // the first block of free memory whose address is larger than the
    00662     // address of the block being freed.  (Or the end of the free list.)
    00663     //
    00664
    00665     while (TRUE) {
    00666
    00667         //
    00668         // Get the address of the next free block.  If we've exhausted
    00669         // the free list, break out of the loop -- the block we're
    00670         // freeing goes at the end of the list.
    00671         //
    00672
    00673         FreeBlock = PreviousFreeBlock->Next;
    00674
    00675         if (FreeBlock == NULL) {
    00676             break;
    00677             }
    00678
    00679 #if DBG
    00680         if (FreeBlock->Size == 0) {
    00681         AlPrint( "ALHEAP: Heap free list ENTRY hosed at %lx\n",
    00682                       FreeBlock
    00683                     );
    00684 //       RtlpBreakPointHeap();
    00685
    00686             return( BaseAddress );
    00687             }
    00688 #endif // DBG
    00689
    00690         //
    00691         // If the address of the current block is higher than the
    00692         // address of the block we're freeing, break out of the loop.
    00693         // The freed block goes immediately before the current block.
    00694         //
    00695
    00696         if (FreeBlock > (PFREE_HEADER)BusyBlock) {
    00697             break;
    00698             }
    00699
    00700         //
    00701         // We haven't found the spot yet.  Remember the last two blocks.
    00702         //
    00703
    00704         SecondPrevFreeBlock = PreviousFreeBlock;
    00705         PreviousFreeBlock = FreeBlock;
    00706
    00707         } // while ( TRUE )
    00708
    00709
    00710     //
    00711     // We've found the place for the block we're freeing.  If the previous
    00712     // block is adjacent to this one, merge the two by summing their sizes,
    00713     // adjusting the address of the block being freed, and making the second
    00714     // previous block the first previous block.  (Note that the previous
    00715     // block may actually be the listhead.  In this case, the if condition
    00716     // will never be true, because the Size of the listhead is 0.)
    00717     //
    00718
    00719     if (((PCH)PreviousFreeBlock + PreviousFreeBlock->Size) == (PCH)BusyBlock &&
    00720         PreviousFreeBlock->Segment == BusySegment
    00721        ) {
    00722         BusySize += PreviousFreeBlock->Size;
    00723         BusyBlock = (PBUSY_HEADER)PreviousFreeBlock;
    00724         PreviousFreeBlock = SecondPrevFreeBlock;
    00725 #if DBG
    00726         }
    00727     else
    00728     if ((PreviousFreeBlock != &Heap->FreeList) &&
    00729         ((PCH)PreviousFreeBlock + PreviousFreeBlock->Size) > (PCH)BusyBlock
    00730        ) {
    00731     AlPrint( "ALHEAP: Heap free list overlaps freed block at %lx\n",
    00732                   BusyBlock
    00733                 );
    00734 //   RtlpBreakPointHeap();
    00735
    00736     return( BaseAddress );
    00737 #endif // DBG
    00738         }
    00739
    00740     //
    00741     // If the block being freed is adjacent to the current block, merge
    00742     // the two by summing their sizes and making the next block the
    00743     // current block.  (Note that the current block may not exist, in
    00744     // which case FreeBlock == NULL, and the if condition will not be
    00745     // true.)
    00746     //*** There is an assumption here that we'll never EVER use the
    00747     //*** very highest part of the address space for user mode allocatable
    00748     //*** memory!
    00749     //
    00750
    00751     if (((PCH)BusyBlock + BusySize) == (PCH)FreeBlock &&
    00752         FreeBlock->Segment == BusySegment
    00753        ) {
    00754         BusySize += FreeBlock->Size;
    00755         FreeBlock = FreeBlock->Next;
    00756 #if DBG
    00757         if (FreeBlock != NULL) {
    00758             if (FreeBlock->Size == 0) {
    00759         AlPrint( "ALHEAP: Heap free list ENTRY hosed at %lx\n",
    00760                           FreeBlock
    00761                         );
    00762 //       RtlpBreakPointHeap();
    00763
    00764         return( BaseAddress );
    00765                 }
    00766             }
    00767         }
    00768     else
    00769     if ((FreeBlock != NULL) &&
    00770         ((PCH)BusyBlock + BusySize) > (PCH)FreeBlock
    00771        ) {
    00772     AlPrint( "ALHEAP: Freed block overlaps heap free list at %lx\n",
    00773                   BusyBlock
    00774                 );
    00775 //   RtlpBreakPointHeap();
    00776
    00777     return( BaseAddress );
    00778 #endif // DBG
    00779         }
    00780
    00781     //
    00782     // Done merging.  Update the free list and the free block header.
    00783     //*** May want to reclaim (i.e., release) pages sometime.  That is,
    00784     //*** if we find ourselves with oodles of contiguous pages on the
    00785     //*** free list, we could delete them from our address space.  On
    00786     //*** the other hand, it probably doesn't cost very much to keep
    00787     //*** them around, and if the process needed that much memory once,
    00788     //*** it's likely to need it again.
    00789     //
    00790
    00791     PreviousFreeBlock->Next = (PFREE_HEADER)BusyBlock;
    00792     ((PFREE_HEADER)BusyBlock)->Next = FreeBlock;
    00793     ((PFREE_HEADER)BusyBlock)->Size = BusySize;
    00794     ((PFREE_HEADER)BusyBlock)->Segment = BusySegment;
    00795
    00796     //
    00797     // Release the free list lock and return to the caller.
    00798     //
    00799
    00800
    00801     return( NULL );
    00802 } // AlRtFreeHeap

PVOID AlRtReAllocateHeap | ( | IN PVOID | HeapHandle,
|  | IN PVOID | BaseAddress,
|  | IN ULONG | Size
| ) |

Definition at line 807 of file memory.c.

References ALLOCATION_GRANULARITY, AlPrint(), AlRtAllocateHeap(), AlRtFreeHeap(), AlRtValidateHeap(), _HEAP_HEADER::EndAddress, FALSE, FLAGS_BUSY, FLAGS_MASK, HeapHandle, _HEAP_HEADER::Length, NULL, PBUSY_HEADER, PHEAP_HEADER, PSEGMENT_HEADER, _BUSY_HEADER::Segment, _SEGMENT_HEADER::Size, _BUSY_HEADER::Size, Size, _BUSY_HEADER::Spare, _HEAP_HEADER::ValidAddress, and _HEAP_HEADER::ZeroExtraMemory.

Referenced by AlReallocateHeap().

    00812 {
    00813     PHEAP_HEADER Heap = (PHEAP_HEADER)HeapHandle;
    00814     PVOID NewBaseAddress;
    00815     ULONG allocationSize;
    00816     PBUSY_HEADER BusyBlock;
    00817     PBUSY_HEADER ExtraBusyBlock;
    00818     PSEGMENT_HEADER BusySegment;
    00819     ULONG BusyFlags;
    00820     ULONG BusySize;
    00821     LONG DeltaSize;
    00822
    00823     //
    00824     // Validate that HeapAddress points to a HEAP_HEADER structure.
    00825     //
    00826
    00827     if (Heap->Length != sizeof( HEAP_HEADER )) {
    00828 #if DBG
    00829     AlPrint( "ALHEAP: Invalid heap header- %lx\n", Heap );
    00830 //   RtlpBreakPointHeap();
    00831 #endif // DBG
    00832         return( NULL );
    00833         }
    00834
    00835     //
    00836     // Additional check, see if the heap is valid, call the heap validation
    00837     // code, requesting it to not dump stuff.
    00838     //
    00839     if(!AlRtValidateHeap( HeapHandle, FALSE)) {
    00840
    00841 #if DBG
    00842         AlPrint("Heap validation failed\n");
    00843 #endif
    00844         return ( NULL );
    00845     }
    00846
    00847
    00848     //
    00849     // Round the requested size up to the allocation granularity.  Note
    00850     // that if the request is for 0 bytes, we still allocate memory.
    00851     //
    00852
    00853     allocationSize = ((Size ? Size : ALLOCATION_GRANULARITY) +
    00854                       sizeof( BUSY_HEADER ) +
    00855                       ALLOCATION_GRANULARITY -
    00856                       1
    00857                      ) & ~(ALLOCATION_GRANULARITY - 1);
    00858
    00859     if (allocationSize < Size) {
    00860 #if DBG
    00861     AlPrint( "ALHEAP: Invalid heap size - %lx\n", Size );
    00862 //   RtlpBreakPointHeap();
    00863 #endif // DBG
    00864         return( NULL );
    00865         }
    00866
    00867     if (BaseAddress == NULL) {
    00868 #if DBG
    00869     AlPrint( "ALHEAP: Invalid heap address - %lx\n", BaseAddress );
    00870 //   RtlpBreakPointHeap();
    00871 #endif // DBG
    00872         return( NULL );
    00873         }
    00874
    00875     //
    00876     // Get the 'real' address of the allocation unit.  (That is, the
    00877     // address of the allocation header.)  Make sure the address lies
    00878     // within the bounds of the valid portion of the heap.
    00879     //
    00880
    00881     BusyBlock = (PBUSY_HEADER)BaseAddress - 1;
    00882     BusySize = BusyBlock->Size;
    00883     BusySegment = (PSEGMENT_HEADER)((ULONG)BusyBlock->Segment & ~FLAGS_MASK);
    00884     BusyFlags = (ULONG)BusyBlock->Segment & FLAGS_MASK;
    00885
    00886     if (BusyFlags != FLAGS_BUSY
    00887 #if DBG
    00888         || (BusySegment == NULL &&
    00889             ((PCHAR)BusyBlock < (PCHAR)Heap->ValidAddress ||
    00890          (PCHAR)BusyBlock >= (PCHAR)Heap->EndAddress
    00891             )
    00892         ) ||
    00893         (BusySegment != NULL &&
    00894             (BusyBlock < (PBUSY_HEADER)(BusySegment+1) ||
    00895              BusyBlock >= (PBUSY_HEADER)((ULONG)BusySegment + BusySegment->Size)
    00896             )
    00897         ) ||
    00898         (BusySize < ALLOCATION_GRANULARITY
    00899         ) ||
    00900         (BusySize & (ALLOCATION_GRANULARITY-1) != 0
    00901         )
    00902 #endif // DBG
    00903        ) {
    00904 #if DBG
    00905     AlPrint( "ALHEAP: Invalid Address specified to AlRtFreeHeap( %lx, %lx )\n",
    00906                   Heap,
    00907                   BaseAddress
    00908                 );
    00909 //   RtlpBreakPointHeap();
    00910 #endif // DBG
    00911         return( NULL );
    00912         }
    00913
    00914
    00915     //
    00916     // See if new size less than or equal to the current size.
    00917     //
    00918
    00919     DeltaSize = (LONG)(BusySize - allocationSize);
    00920     if (DeltaSize >= 0) {
    00921         //
    00922         // Then shrinking block.  If amount of shrinkage is less than
    00923         // the size of a free block, then nothing to do.
    00924         //
    00925
    00926         if (DeltaSize < sizeof( FREE_HEADER )) {
    00927             if (Heap->ZeroExtraMemory) {
    00928         memset( (PCHAR)BusyBlock + (allocationSize - DeltaSize),0,
    00929                                DeltaSize
    00930                              );
    00931                 }
    00932
    00933             return( BaseAddress );
    00934             }
    00935
    00936         //
    00937         // Otherwise, shrink size of this block to new size, and make extra
    00938     // space at end look like another busy block and call AlRtFreeHeap
    00939         // to free it.
    00940         //
    00941
    00942         BusyBlock->Size = allocationSize;
    00943         ExtraBusyBlock = (PBUSY_HEADER)((PCH)BusyBlock + allocationSize);
    00944         ExtraBusyBlock->Segment = BusyBlock->Segment;
    00945         ExtraBusyBlock->Size = (ULONG)(DeltaSize);
    00946 #if DBG
    00947     ExtraBusyBlock->Spare = 0;
    00948 #endif
    00949
    00950     AlRtFreeHeap( HeapHandle, (PVOID)(ExtraBusyBlock+1) );
    00951
    00952         if (Heap->ZeroExtraMemory) {
    00953             ULONG extraSize;
    00954
    00955             extraSize = allocationSize - Size - sizeof( BUSY_HEADER );
    00956         memset( (PCHAR)BusyBlock + (allocationSize - extraSize),0,
    00957                            extraSize
    00958                          );
    00959             }
    00960
    00961         return( BaseAddress );
    00962         }
    00963
    00964     //
    00965     // Otherwise growing block, so allocate a new block with the bigger
    00966     // size, copy the contents of the old block to the new block and then
    00967     // free the old block.  Return the address of the new block.
    00968     //
    00969
    00970     NewBaseAddress = AlRtAllocateHeap( HeapHandle, Size );
    00971     if (NewBaseAddress != NULL) {
    00972 #if DBG
    00973         ExtraBusyBlock = (PBUSY_HEADER)NewBaseAddress - 1;
    00974     ExtraBusyBlock->Spare = 0;
    00975 #endif
    00976     memmove( NewBaseAddress,
    00977                        BaseAddress,
    00978                        BusySize - sizeof( BUSY_HEADER )
    00979                      );
    00980
    00981     AlRtFreeHeap( HeapHandle, BaseAddress );
    00982         }
    00983
    00984     return( NewBaseAddress );
    00985 }

BOOLEAN AlRtValidateHeap | ( | IN PVOID | HeapHandle,
|  | IN BOOLEAN | DumpHeap
| ) |

Definition at line 352 of file memory.c.

References TRUE.

Referenced by AlRtAllocateHeap(), AlRtFreeHeap(), AlRtReAllocateHeap(), and AlValidateHeap().

    00356 {
    00357     return( TRUE );
    00358 }

BOOLEAN AlValidateHeap | ( | IN BOOLEAN | DumpHeap | ) |

Definition at line 1174 of file memory.c.

References AlRtValidateHeap(), and HeapHandle.

    01177 {
    01178     return (AlRtValidateHeap
    01179                 (
    01180                 HeapHandle,
    01181                 DumpHeap
    01182                 ));
    01183 }

## Variable Documentation

ULONG AlHeapFree

| Definition at line 112 of file memory.c. Referenced by AlMemoryInitialize().

ULONG AlHeapLimit

| Definition at line 113 of file memory.c. Referenced by AlMemoryInitialize().

PVOID HeapHandle

| Definition at line 115 of file memory.c. Referenced by AlAllocateHeap(), AlDeallocateHeap(), AlMemoryInitialize(), AlReallocateHeap(), AlRtAllocateHeap(), AlRtFreeHeap(), AlRtReAllocateHeap(), AlValidateHeap(), LdrpTagAllocateHeap(), RtlAllocateHeap(), RtlAllocateHeapSlowly(), RtlCompactHeap(), RtlCreateAndSetSD(), RtlCreateTagHeap(), RtlCreateUserSecurityObject(), RtlDebugAllocateHeap(), RtlDebugCompactHeap(), RtlDebugCreateTagHeap(), RtlDebugDestroyHeap(), RtlDebugFreeHeap(), RtlDebugGetUserInfoHeap(), RtlDebugQueryTagHeap(), RtlDebugReAllocateHeap(), RtlDebugSetUserFlagsHeap(), RtlDebugSetUserValueHeap(), RtlDebugSizeHeap(), RtlDebugUsageHeap(), RtlDebugWalkHeap(), RtlDebugZeroHeap(), RtlDestroyHeap(), RtlExtendHeap(), RtlFreeHeap(), RtlFreeHeapSlowly(), RtlGetUserInfoHeap(), RtlLockHeap(), RtlpComputeMergedAcl(), RtlpConvertAclToAutoInherit(), RtlpConvertToAutoInheritSecurityObject(), RtlpDebugPageHeapAllocate(), RtlpDebugPageHeapCompact(), RtlpDebugPageHeapCreate(), RtlpDebugPageHeapDestroy(), RtlpDebugPageHeapFree(), RtlpDebugPageHeapGetUserInfo(), RtlpDebugPageHeapIsLocked(), RtlpDebugPageHeapLock(), RtlpDebugPageHeapPointerFromHandle(), RtlpDebugPageHeapReAllocate(), RtlpDebugPageHeapSerialize(), RtlpDebugPageHeapSetUserFlags(), RtlpDebugPageHeapSetUserValue(), RtlpDebugPageHeapSize(), RtlpDebugPageHeapUnlock(), RtlpDebugPageHeapUsage(), RtlpDebugPageHeapValidate(), RtlpDphDllHeapAlloc(), RtlpDphDllHeapFree(), RtlpDphDllHeapReAlloc(), RtlpGetDefaultsSubjectContext(), RtlpHeapIsLocked(), RtlpInheritAcl(), RtlpNewSecurityObject(), RtlpQueryProcessEnumHeapsRoutine(), RtlProtectHeap(), RtlpSerializeHeap(), RtlpSetSecurityObject(), RtlpValidOwnerSubjectContext(), RtlQueryTagHeap(), RtlReAllocateHeap(), RtlSetUserFlagsHeap(), RtlSetUserValueHeap(), RtlSizeHeap(), RtlUnlockHeap(), RtlUsageHeap(), RtlValidateHeap(), RtlWalkHeap(), and RtlZeroHeap().