Formula for memory alignment

Looking through the kernel code, I found a formula for memory alignment:

aligned = ((operand + (alignment - 1)) & ~ (alignment - 1))

So, I even write a program to do this:

#include <stdio.h>

int main(int argc, char** argv) {
    long long operand;
    long long alignment;
    if(argv[1]) {
        operand = atol(argv[1]);
    } else {
        printf("Enter value to be aligned!\n");
        return -1;
    }
    if(argv[2]) {
        alignment = strtol(argv[2],NULL,16);
    } else {
        printf("\nDefaulting to 1MB alignment\n");
        alignment = 0x100000;
    }
    long long aligned = ((operand + (alignment - 1)) & ~(alignment - 1));
    printf("Aligned memory is: 0x%.8llx [Hex] <--> %lld\n",aligned,aligned);
    return 0;
}

      

But I don't understand this logic at all. How it works?

+3


source to share


1 answer


Basically, the formula increments an integer operand

(address) to the next address aligned with alignment

.

Expression

aligned = ((operand + (alignment - 1)) & ~(alignment - 1))

      

basically the same as the formula is a little easier to understand:

aligned = int((operand + (alignment - 1)) / alignment) * alignment

      

For example, given operand (address) 102 and alignment 10, we get:

aligned = int((102 + 9) / 10) * 10
aligned = int(111 / 10) * 10
aligned = 11 * 10
aligned = 110

      

First, let's add the address 9

and get it 111

. Then, since our alignment is 10, we basically zero out the last digit, i.e.111 / 10 * 10 = 110



Note that for every 10 power equalization (i.e. 10, 100, 1000, etc.) we basically zero out the last digits.

On most processors, division and multiplication take much longer than bitwise operations, so let's go back to the original formula:

aligned = ((operand + (alignment - 1)) & ~(alignment - 1))

      

The second part of the formula only makes sense when the alignment is a power of 2. For example:

... & ~(2 - 1) will zero last bit of address.
... & ~(64 - 1) will zero last 5 bits of address.
etc

      

As with zeroing the last few digits of the address for cardinality 10 alignments, we zero out the last few bits for cardinality 2 alignments.

Hope this makes sense to you now.

+1


source







All Articles