I am analyzing the effect of allocation across virtual pages while creating a 2-D array of dimension PageSize x PageSize. My machine's page size is 4096. I have an array of 4096 integer pointers(columns), pointing to 4096 integers(rows).
I want to begin the allocation for the first integer pointer at a new virtual page. How can I identify if the current memory location is a new page or not? Once, I have identified that, I believe I can write some garbage values and move the pointer to a new virtual page. This is how I allocate the array.
array = malloc(ncolumns * sizeof(int *));
for(j = 0; j < ncolumns; j++)
{
array[j] = malloc(nrows * sizeof(int));
if(array[j] == NULL)
{ reportError(8);}
}
malloc() allocates the virtual memory, owned by the process. During execution the process can be reloaded to the physical memory several times by the operating system. The operating system maps virtual addresses of each process to the physical memory. A process doesn't know the mapping.
In the C Programming Language, the realloc function is used to resize a block of memory that was previously allocated. The realloc function allocates a block of memory (which be can make it larger or smaller in size than the original) and copies the contents of the old block to the new block of memory, if necessary.
If you know your page size, you can allocate a sufficiently sized portion of memory that will guarantee that some portion of the newly allocated memory is aligned on a page boundary. You will need to allocate at least 8192 bytes of memory to guarantee that you will have 4096 bytes aligned on a 4096 byte boundary.
For example, if you call malloc
and it returns to you an offset aligned to 0xDEAD1001
(4097), you will need to go to the next page at memory address 0xDEAD2000
to get to a 4096 byte alignment. Then, you'll need at least 4096 bytes of contiguous space. Hence, the need to allocate 8192 bytes.
To get a 4k byte aligned memory location, you can add 4095 to the address returned by malloc
and mask the last 3 bytes.
void *mem = malloc(8192);
void *ptr = ((void *)mem+0x0FFF) & ~ (void *)0x0FFF;
Edit: Make sure to keep a pointer to the original memory allocated, so you can later turn around and use it to call free()
.
Suppose this time, malloc returned 0xDEAD000F
.
0xDEAD000F + 0x0000FFF = 0xDEAD100E
0xDEAD100E & ~0x0000FFF = 0xDEAD1000
If you don't want to do all this messy pointer arithmetic, I think you could just use posix_memalign
. Check it out here. If you are on a different platform, I'm sure there are similar memory alignment services available.
Using just the features of the C language you cannot align your allocations (i.e. something that was returned from malloc) on the page boundary. Your sample code is just allocating array of pointers to arrays. Their location can be anywhere in the virtual address space. Exact location depends on the compiler/library/OS/etc.
Operating sytems typically have functions that allow doing such things. On Windows you can use VirtualAlloc
function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With