Memory alignment of arrays

Snps picture Snps · Apr 29, 2014 · Viewed 18.2k times · Source

I am having trouble aligning memory for DMA transfer on the Cell processor. I need the last 4 bits of an address to be 0.

I have 4 arrays of unsigned int where each element must be aligned in memory so that its (hex) adress ends with a zero.

E.g.

int main()
{
    size_t i;

    static unsigned int a[2] __attribute__ ((aligned (16)));
    static unsigned int b[2] __attribute__ ((aligned (16)));
    static unsigned int c[2] __attribute__ ((aligned (16)));
    static unsigned int d[2] __attribute__ ((aligned (16)));

    for (i = 0; i < 2; ++i) {
        printf("a[%u] = %p\n", &a[i]);
        printf("b[%u] = %p\n", &b[i]);
        printf("c[%u] = %p\n", &c[i]);
        printf("d[%u] = %p\n", &d[i]);
    }

    return 0;
}

Output:

a[0] = 0x10010b60
b[0] = 0x10010b50
c[0] = 0x10010b40
d[0] = 0x10010b30
a[1] = 0x10010b64
b[1] = 0x10010b54
c[1] = 0x10010b44
d[1] = 0x10010b34

The problem here is that the 2nd element of each array doesn't seem to be 16-bit aligned (their address' end with a 4).

I need the addresses to look like this:

a[0] = 0xXXXXXXX0
b[0] = 0xXXXXXXX0
c[0] = 0xXXXXXXX0
d[0] = 0xXXXXXXX0
a[1] = 0xXXXXXXX0
b[1] = 0xXXXXXXX0
c[1] = 0xXXXXXXX0
d[1] = 0xXXXXXXX0

Answer

Olaf Dietsche picture Olaf Dietsche · Apr 29, 2014

The alignment attribute specifies the alignment of variables or structure fields, not single array elements. See Specifying Attributes of Variables for details.

If you always want to align two integers together, you can define a structure

struct dma_transfer {
    unsigned int e0 __attribute__ ((aligned (16)));
    unsigned int e1 __attribute__ ((aligned (16)));
};

This aligns the elements on 16 byte boundaries.

int main(int argc, char **argv)
{
    static struct dma_transfer a;
    static unsigned int b[2];

    printf("a.e0 = %p\n", &a.e0);
    printf("a.e1 = %p\n", &a.e1);
    printf("b[0] = %p\n", &b[0]);
    printf("b[1] = %p\n", &b[1]);

    return 0;
}

gives, e.g.

a.e0 = 0x601060
a.e1 = 0x601070
b[0] = 0x601080
b[1] = 0x601084

But this means also, that you have holes between the two integer values. On a 32 bit system, you will have

| int 4 bytes | hole 12 bytes |
| int 4 bytes | hole 12 bytes |