Re: [RFC] Documentation about unaligned memory access

Jan Engelhardt
2007-11-23T10:07:12Z

On Nov 23 2007 00:15, Daniel Drake wrote:
>
>What's the definition of an unaligned access?
>=============================================
>
>Unaligned memory accesses occur when you try to read N bytes of data starting
>from an address that is not evenly divisible by N (i.e. addr % N != 0).
>For example, reading 4 bytes of data from address 0x10000004 is fine, but
>reading 4 bytes of data from address 0x10000005 would be an unaligned memory
>access.
>
Try shorter numbers, like 0x10005 :)

>Code that doesn't cause unaligned access
>========================================

In written style, not using n't contracted forms might be preferable.

>Sidenote: in the above example, you may wish to reorder the fields in the
>above structure so that the overall structure uses less memory. For example,
>moving field3 to sit inbetween field1 and field2 (where the padding is
>inserted) would shrink the overall structure by 1 byte:
>
> struct foo {
> u16 field1;
> u8 field3;
> u32 field2;
> };
>
>Sidenote: it should be obvious by now, but in case it is not, accessing a
>single byte (u8 or char) can never cause an unaligned access, because all
>memory addresses are evenly divisible by 1.

Sidenote: You would want an alignment like this:

struct foo {
uint32_t field2;
uint16_t field1;
uint8_t field3;
};

>Consider the following structure:
> struct foo {
> u16 field1;
> u32 field2;
> u8 field3;
> } __attribute__((packed));
>
>It's the same structure as we looked at earlier, but the packed attribute has
>been added. This attribute ensures that the compiler never inserts any padding
>and the structure is laid out in memory exactly as is suggested above.
>
>The packed attribute is useful when you want to use a C struct to represent
>some data that comes in a fixed arrangement 'off the wire'.
>
In the packed case, does not GCC automatically output extra instructions to not
run into unaligned access?

>To avoid the unaligned memory access, you could rewrite it as follows:
>
> void myfunc(u8 *data, u32 value)
> {
> [...]
> value = cpu_to_le32(value);
> memcpy(data, value, sizeof(value));
> [...]
> }
>
>It's safe to assume that memcpy will always copy bytewise and hence will
>never cause an unaligned access.
>
Usually it copies register-size-wise where possible and bytesize at the
left and right edges if they are unaligned. That's how glibc memcpy does it,
not sure how complete the kernel memcpy is in this regard.