Aligning virtual address to immediate next page boundary
Asked Answered
L

3

11

I came across following algorithm that aligns virtual address to immediate next page bounday.

VirtualAddr = (VirtualAddr & ~(PageSize-1));

Also, given a length of bytes aligns length (rounds it) to be on the page boundary

len = ((PageSize-1)&len) ? ((len+PageSize) & ~(PageSize-1)):len;

I am finding it hard to decipher how this works. Can someone help me out to break it down?

Linchpin answered 9/4, 2014 at 18:8 Comment(5)
That aligns a virtual address to the immediate previous page boundryForebode
...and the second one doesn't work at all, unless there's other assumptions you haven't mentioned. (Oh wait, if (len<=PageSize) then it's len, otherwise it's len rounded up to the next page boundary. That's quite different than what you described.Forebode
Yes you are correct. 1. For first statement to align to immediate next boundary should be((VirtualAddr+PageSize) & ~(PageSize-1)) 2. And the second statement of the second line rounds to page size.Linchpin
Your correction to the first problem is also incorrect (ish), as it adds unneeded padding to those already aligned; use ((VirtualAddr+PageSize-1) & ~(PageSize-1)) instead.Forebode
lang-py >>> hex(0x00053000 & ~(4095)) '0x53000' >>> hex(0x00053FFF & ~(4095)) '0x53000' >>> hex(0x00052FFF & ~(4095)) '0x52000' Footsie
T
14

Those calculations assume that the page size is a power of 2 (which is the case for all systems that I know of), for example

PageSize = 4096 = 2^12 = 1000000000000 (binary)

Then (written as binary numbers)

PageSize-1    = 00...00111111111111
~(PageSize-1) = 11...11000000000000

which means that

(VirtualAddr & ~(PageSize-1))

is VirtualAddr with the lower 12 bits set to zero or, in other words, VirtualAddr rounded down to the next multiple of 2^12 = PageSize.

Now you can (hopefully) see that in

len = ((PageSize-1)&len) ? ((len+PageSize) & ~(PageSize-1)):len;

the first expression

 ((PageSize-1)&len)

is zero exactly if len is a multiple of PageSize. In that case, len is left unchanged. Otherwise (len + PageSize) is rounded down to the next multiple of PageSize.

So in any case, len is rounded up to the next multiple of PageSize.

Those answered 9/4, 2014 at 18:49 Comment(1)
Selecting this answer. Detailed, descriptive and exactly what I was looking for. Thanks everyone for helping me out :).Linchpin
E
3

I think the first one should be

VirtualAddr = (VirtualAddr & ~(PageSize-1)) + PageSize; 
Euchre answered 9/4, 2014 at 18:27 Comment(3)
Actually, even this is not quite correct. This works unless VirtualAddr is already aligned. In this case, it will be advanced to the next page boundary.Karaganda
You are right, maybe an if statement could check this.Euchre
this should do it I believe. ((VirtualAddr+PageSize) & ~(PageSize-1))Linchpin
B
0

This one-liner will do it - if it is already aligned aligned it will not skip to the next page boundary:

aligned = ((unsigned long) a & (getpagesize()-1)) ? (void *) (((unsigned long) a+getpagesize()) & ~(getpagesize()-1)) : a;

This one-liner will do it - if it is already aligned aligned it will not skip to the next page boundary:

if you really do want to skip to the next page boundary even if it's already aligned - just do:

aligned = (void *) (((unsigned long) a+getpagesize()) & ~(getpagesize()-1))

This should avoid all compiler warnings, too.

getpagesize() is a POSIX thing. #include <unistd.h> to avoid warnings.

Bindman answered 6/4, 2018 at 13:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.