|
|
/*++
Copyright (c) 1995-1998 Microsoft Corporation
Module Name:
epalloc.c
Abstract: This module allocates memory for the entry point structures Author:
21-Aug-1995 Ori Gershony (t-orig)
Revision History:
24-Aug-1999 [askhalid] copied from 32-bit wx86 directory and make work for 64bit.
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include "wx86.h"
#include "cpuassrt.h"
#include "config.h"
#include "entrypt.h"
ASSERTNAME;
PVOID allocBase; // Base of the allocation unit
PVOID commitLimit; // Top of commited memory
PVOID allocLimit; // Top of memory allocated to the user
#if DBG
#define EPTRASHVALUE 0x0b
#endif
INT initEPAlloc( VOID ) /*++
Routine Description:
Initializes the entry point memory allocator
Arguments:
none
Return Value:
return-value - non-zero for success, 0 for failure
--*/ { NTSTATUS Status; ULONGLONG ReserveSize = CpuEntryPointReserve;
Status = NtAllocateVirtualMemory(NtCurrentProcess(), &allocBase, 0, &ReserveSize, MEM_RESERVE, PAGE_READWRITE ); if (!NT_SUCCESS(Status)) { return 0; }
// No memory is commited yet, nor is any allocated to the user
allocLimit = commitLimit = allocBase;
return (INT)(LONGLONG)allocBase; }
VOID termEPAlloc( VOID ) /*++
Routine Description:
Frees the memory used the the allocator. This should only be called before the process is terminated.
Arguments:
none
Return Value:
return-value - none
--*/ { ULONGLONG ReserveSize = CpuEntryPointReserve;
NtFreeVirtualMemory(NtCurrentProcess(), &allocBase, &ReserveSize, MEM_RELEASE ); }
BOOLEAN commitMemory( LONG CommitDiff ) /*++
Routine Description:
This routine tries to commit memory for use by the allocator. If there is no more memory left, is fails and returns with zero. Else it returns 1 for success. This is an internal function for use by the allocator only.
Arguments:
none
Return Value:
return-value - TRUE for success, FALSE for failure
--*/ { LONG CommitSize; DWORD i; LONGLONG TempCommitDiff = CommitDiff;
for (i=0; i<CpuMaxAllocRetries; ++i) { NTSTATUS Status; LARGE_INTEGER Timeout;
//
// Try to allocate more memory
//
if ((LONG)(ULONGLONG)commitLimit + CommitDiff -(LONG)(ULONGLONG)allocBase > (LONG)(ULONGLONG)CpuEntryPointReserve) { //
// The commit would extend pase the reserve. Fail the
// alloc, which will cause a cache/entrypoint flush.
//
return FALSE; } Status = NtAllocateVirtualMemory(NtCurrentProcess(), &commitLimit, 0, &TempCommitDiff, MEM_COMMIT, PAGE_READWRITE ); if (NT_SUCCESS(Status)) { //
// Allocation succeeded. Move commitLimit up and return success
//
#if DBG
RtlFillMemory(commitLimit, TempCommitDiff, EPTRASHVALUE); #endif
commitLimit = (PVOID) ((ULONG)(ULONGLONG)commitLimit + TempCommitDiff); return TRUE; }
//
// No pages available. Sleep a bit and hope another thread frees a
// page.
//
Timeout.QuadPart = (LONGLONG)CpuWaitForMemoryTime * -10000i64; NtDelayExecution(FALSE, &Timeout); }
//
// No pages available. Return failure. Caller will attempt to free
// some pages and retry the EPAlloc call.
return FALSE; }
PVOID EPAlloc( DWORD cb ) /*++
Routine Description:
This routine allocated memory for use by the entry point module.
Arguments:
cb - count of bytes to allocate from the entrypoint memory.
Return Value:
return-value - The memory allocated if succeeded, NULL otherwise
--*/ { PVOID newAllocLimit, oldAllocLimit; LONG CommitDiff;
CPUASSERTMSG(allocLimit == commitLimit || *(PBYTE)allocLimit == EPTRASHVALUE, "Entrypoint memory overrun");
// Calculate new allocation limit
oldAllocLimit = allocLimit; newAllocLimit = (PVOID) ((ULONG)(ULONGLONG)oldAllocLimit + cb);
// See if we need to commit more memory
CommitDiff = (LONG)(ULONGLONG)newAllocLimit - (LONG)(ULONGLONG)commitLimit; if (CommitDiff > 0){ // Yes we do, so try to commit more memory
if (!commitMemory(CommitDiff)){ // Cannot commit more memory, so return failure
return NULL; } }
allocLimit = newAllocLimit; return oldAllocLimit; }
VOID EPFree( VOID ) /*++
Routine Description:
This routine frees all entry point memory allocated so far
Arguments:
none
Return Value:
none
--*/ { #if DBG
//
// Fill the committed space with a known value to make
// debugging easier
//
RtlFillMemory(allocBase, (ULONG)(ULONGLONG)allocLimit-(ULONG)(ULONGLONG)allocBase, EPTRASHVALUE); #endif
allocLimit = allocBase; }
|