align macro kernel

Say you have a number: 0x1006

For some reasons you want to align it to a 4 bytes boundary.

With a 4-byte boundary, you know aligned values are 0x1000, 0x1004, 0x1008, etc. You then also know the aligned value of 0x1006 is 0x1008.

How would you get 0x1008? The alignment mask for alignment value 4 is (4 - 1) = 0x03

Now 0x1006 + 0x03 = 0x1009 and 0x1009 & ~0x03 = 0x1008

This operation is the __ALIGN_MASK macro.

If you want to pass the value 4 (the alignment) instead of directly 0x03 (the alignment mask), you have the ALIGN macro


#define ALIGN(x,a)              __ALIGN_MASK(x,(typeof(x))(a)-1)

the alignment, a, is cast to x's type, and then one is subtracted. The alignment should be a power of 2, so that results in a number of the bit-pattern 00..011..11 of x's type, the mask (k 1s if a = 2^k).

Then

#define __ALIGN_MASK(x,mask)    (((x)+(mask))&~(mask))

adds the value of the mask to x, so that (x)+ (mask) is at least as large as the smallest multiple of the alignment that is not smaller than x and smaller than the next larger multiple. Then the bitwise and with the complement of the mask reduces that number to that multiple of the alignment.

For masks of the form 2^k - 1, the computation

(x + mask) & ~mask

is the same as

(x + 2^k - 1) - ((x + 2^k - 1) % (2^k))

or

((x + 2^k - 1)/(2^k)) * (2^k)