From: jeffreycameron on
Hello all,

I'm trying to implement AWE in my application. So far I have done this
:

1. Enabled the Lock Pages in Memory privilege for my account
2. Used the AWE example code function to enable and disable this
privilege for my app.
3. Set up a memory allocation wrapper function that makes calls to:
a. Determine the number of pages I need
b. Set up a PFN array
c. Call AllocateUserPhysicalPages and pass in the PFN array
d. Call VirtualAlloc (I also tried VirtualAllocEx) to reserve the
memory
e. Call MapUserPhysicalPages to map the memory.

I'm not concerned about deallocating the stuff just yet, that will come
later. Right now I believe the memory is freed when the process dies
anyway so it isn't a big concern for me.

The server I am running this on has 32GB of RAM and is running Windows
Advanced Server 2003. The /PAE switch is in the boot.ini file and
enabled. During usual running the server is using about 310MB of RAM
for the processes and such that are on it already. Much less than the
32GB available.

My problem is when I try to allocate large memory chunks. I can
allocate up to 500MB with AWE no problem, then I have a single huge
allocation of close to 800MB after this. When I try to make this single
huge allocation the program fails!! I was under the impression that
with PAE X86 and AWE my 32-bit pointers could/would point to physical
memory up to 64GB in range ... so why the hell is it not working??

I do mix regular heap allocation (using calloc) with the AWE stuff. I
try to localise the usage of AWE to the really large arrays of data I
need. Could this be a cause?

Can someone please help and tell me what the devil is going on?

Thanks in advance!

p.s. YES I really do need this much memory!! Working with caches and
memory-mapped files would be too slow for the application I want to use.

From: jeffreycameron on
Sorry, I should have added earlier, that when I said the allocation
failed it failed on a call to VirtualAlloc with GetLastError reporting
there wasn't enough memory to handle the request.

From: Carl Daniel [VC++ MVP] on
jeffreycameron(a)gmail.com wrote:
> Sorry, I should have added earlier, that when I said the allocation
> failed it failed on a call to VirtualAlloc with GetLastError reporting
> there wasn't enough memory to handle the request.

Are you actually allocating any AWE memory? Unless you're calling
AllocateUserPhysicalPages and MapUserPhysicalPages, you're not using AWE
memory.

See
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/memory/base/address_windowing_extensions.asp
for details.

-cd


From: Jeffrey on
Hi Carl,

Yes, i'm calling AllocateUserPhysicalPages (which is successful) and
then calling VirtualAlloc (which fails). After VirtualAlloc I would then
call MapUserPhysicalPages. So my cycles goes (see code below):

First invocation:
1. Call AllocateUserPhysicalPages (#pages for 500MB RAM) [Success]
2. Call VirtualAlloc (500MB RAM) [Success]
3. Call MapUserPhysicalPages (#pages for 500MB RAM) [Success]

Second invocation:
1. Call AllocateUserPhysicalPages (#pages for 800MB RAM) [Success]
2. Call VirtualAlloc (800MB of RAM) [Failure]
3. GetLastError reports not enough memory to fulfill request.

Sorry for little specifics, but i'm at home typing this. There is no
internet access at my workstation for security reasons.

So the first time I call my function it succeeds, the second time it
fails. The total of memory between them is app. 1.3GB. My server has
32GB of RAM and PAE enabled. 4GT is turned off.

[CODE SNIPPET]

AWERegionDescriptor *region;
SYSTEM_INFO info;
ULONG_PTR pages_requested;
BOOL rAWEesult;
PVOID ptr;
int ret_code;
int page_size = 0;

/* determine the page size of this computer */

GetSystemInfo(&info);
page_size = info.dwPageSize;
pages_requested = ((nb_elem * elem_size) / page_size) + 1;

/* allocate the space for the region descriptor */

region = (AWERegionDescriptor*) ccalloc(1,
sizeof(AWERegionDescriptor));
region->nb_pages = pages_requested;
region->pfn_array = (ULONG_PTR*) HeapAlloc(GetProcessHeap(), 0,
region->nb_pages * sizeof(ULONG_PTR));

/* reserve the physical pages in memory */

result = AllocateUserPhysicalPages(GetCurrentProcess(),
&(region->nb_pages), region->pfn_array);

if (result == FALSE)
{
/* print error */
}

if (pages_requested != region->nb_pages)
{
/* print error */
}

/* allocate the pointer */

ptr = VirtualAlloc(NULL, nb_elem * elem_size, MEM_RESERVE |
MEM_PHYSICAL, PAGE_READWRITE);

/* ensure memory was available */

if (ptr == NULL)
{
/* print an error */
}
else
{
/* map the physical memory into the AWE region */

result = MapUserPhysicalPages(ptr, region->nb_pages,
region->pfn_array);

if (result == FALSE)
{
/* print error */
}
}

return ptr;

[END CODE SNIPPET]

Carl Daniel [VC++ MVP] wrote:
> jeffreycameron(a)gmail.com wrote:
>
>>Sorry, I should have added earlier, that when I said the allocation
>>failed it failed on a call to VirtualAlloc with GetLastError reporting
>>there wasn't enough memory to handle the request.
>
>
> Are you actually allocating any AWE memory? Unless you're calling
> AllocateUserPhysicalPages and MapUserPhysicalPages, you're not using AWE
> memory.
>
> See
> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/memory/base/address_windowing_extensions.asp
> for details.
>
> -cd
>
>
From: Ivan Brugiolo [MSFT] on
Form the description of the problem,
it seems that the address space of the process does not
have a large enought contiguous address range to map
the view of the physical memory.
Virtual address space of a process is still limited to 2/3/4 Gig,
depending if the application is running
on a regular, /3G and LargeAddressAware,
Wow64 and LargeAddressAware.
Virtual address space is being used by heap segments, threads's stacks,
module mapping, user mapping, etc, etc.

I would recoment running the `!address -summary` command
in any recent cdb/ntsd/windbg debugger, and see what is the
largest contigious range of addressed onto which you can create a map
(and, at the same time, you would see what else the address space
is being used for).

To give you the idea, in a regular process with just "int main(int,char
**){}",
you can expect to have 1.9Gig of contiguous address range, that
would allou you to map about 1/17th of the 32Gig of physical
memory you have at any given time.
More complex process would allow you less.

--
--
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of any included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm


"Jeffrey" <jeffreycameron(a)gmail.com> wrote in message
news:ejNl3GCMGHA.4064(a)TK2MSFTNGP10.phx.gbl...
> Hi Carl,
>
> Yes, i'm calling AllocateUserPhysicalPages (which is successful) and then
> calling VirtualAlloc (which fails). After VirtualAlloc I would then call
> MapUserPhysicalPages. So my cycles goes (see code below):
>
> First invocation:
> 1. Call AllocateUserPhysicalPages (#pages for 500MB RAM) [Success]
> 2. Call VirtualAlloc (500MB RAM) [Success]
> 3. Call MapUserPhysicalPages (#pages for 500MB RAM) [Success]
>
> Second invocation:
> 1. Call AllocateUserPhysicalPages (#pages for 800MB RAM) [Success]
> 2. Call VirtualAlloc (800MB of RAM) [Failure]
> 3. GetLastError reports not enough memory to fulfill request.
>
> Sorry for little specifics, but i'm at home typing this. There is no
> internet access at my workstation for security reasons.
>
> So the first time I call my function it succeeds, the second time it
> fails. The total of memory between them is app. 1.3GB. My server has 32GB
> of RAM and PAE enabled. 4GT is turned off.
>
> [CODE SNIPPET]
>
> AWERegionDescriptor *region;
> SYSTEM_INFO info;
> ULONG_PTR pages_requested;
> BOOL rAWEesult;
> PVOID ptr;
> int ret_code;
> int page_size = 0;
>
> /* determine the page size of this computer */
>
> GetSystemInfo(&info);
> page_size = info.dwPageSize;
> pages_requested = ((nb_elem * elem_size) / page_size) + 1;
>
> /* allocate the space for the region descriptor */
>
> region = (AWERegionDescriptor*) ccalloc(1,
> sizeof(AWERegionDescriptor));
> region->nb_pages = pages_requested;
> region->pfn_array = (ULONG_PTR*) HeapAlloc(GetProcessHeap(), 0,
> region->nb_pages * sizeof(ULONG_PTR));
>
> /* reserve the physical pages in memory */
>
> result = AllocateUserPhysicalPages(GetCurrentProcess(),
> &(region->nb_pages), region->pfn_array);
>
> if (result == FALSE)
> {
> /* print error */
> }
>
> if (pages_requested != region->nb_pages)
> {
> /* print error */
> }
>
> /* allocate the pointer */
>
> ptr = VirtualAlloc(NULL, nb_elem * elem_size, MEM_RESERVE |
> MEM_PHYSICAL, PAGE_READWRITE);
>
> /* ensure memory was available */
>
> if (ptr == NULL)
> {
> /* print an error */
> }
> else
> {
> /* map the physical memory into the AWE region */
>
> result = MapUserPhysicalPages(ptr, region->nb_pages,
> region->pfn_array);
>
> if (result == FALSE)
> {
> /* print error */
> }
> }
>
> return ptr;
>
> [END CODE SNIPPET]
>
> Carl Daniel [VC++ MVP] wrote:
>> jeffreycameron(a)gmail.com wrote:
>>
>>>Sorry, I should have added earlier, that when I said the allocation
>>>failed it failed on a call to VirtualAlloc with GetLastError reporting
>>>there wasn't enough memory to handle the request.
>>
>>
>> Are you actually allocating any AWE memory? Unless you're calling
>> AllocateUserPhysicalPages and MapUserPhysicalPages, you're not using AWE
>> memory.
>>
>> See
>> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/memory/base/address_windowing_extensions.asp
>> for details.
>>
>> -cd
>>