> -----Original Message-----
> From: Jason Gunthorpe [mailto:jguntho...@obsidianresearch.com]
> Sent: Friday, March 23, 2012 4:14 AM
> To: Pandit, Parav
> Cc: david.lai...@aculab.com; rol...@purestorage.com; linux-
> r...@vger.kernel.org; net...@vger.kernel.org
> Subject: Re: [PATCH 2/9] ocrdma: Driver for Emulex OneConnect RDMA
> adapter
> 
> On Thu, Mar 22, 2012 at 02:20:28PM -0700, parav.pan...@emulex.com
> wrote:
> > I got a question here lately.
> >
> > aligned directive will ensure that it will fall on boundary.  Say
> > aligned(4) ensures that structure is aligned to 4 byte boundary.
> > Compiler can (at least theoretically) still have 4 byte structure
> > aligned to 8 byte boundary on 64-bit platform (which is 4 byte aligned
> > too).
> 
> There are very specific rules defined in the platform's ABI for how C
> structures are layed out in memory, each ABI (ie CPU) has its own specific
> quirks, but broadly in Linux land you can boil it down to:
> 
> 1) The alignment of a structure is the greatest alignment of all the
>    members
> 2) Each member is aligned to its alignment.
> 
> The alignment of the structure drives the total size of the structure, and
> specifically the padding added at the end to reach that alignment.
> 
> So, no, a compiler that increased the alignment of a struct with one
> u32 to 8 would violate the various ABIs and not be usuable for Linux. It is
> important to bear in mind that Linux targets a particular set of ABI
> conventions, and it is not 'anything goes'.
> 
> > struct {
> >     u32 field;
> > };
> 
> So in this case: the u32 is aligned to 4, the structure is aligned to
> 4 and the total size of the structure is 4 on everything linux supports.
> 
> > struct {
> >       u64 fielda
> >     u32 field;
> > };
> 
> In this case: On 64 bit: the u64 is aligned to 8 and the u32 is aligned to 4. 
> So
> the structure is aligned to 8. A pad is inserted at the end of the struct to 
> bring
> it out. On 32 bit, the u64 is aligned to 4, so the struct is aligned to 4, so 
> no pad
> is added.
> 
> > struct {
> >       __float128 fielda
> >     u32 field;
> > };
> 
> In this case the float128 is aligned to 16 and thus the structure is aligned 
> to 16
> and 12 pad bytes are added.
> 
> > However requirement is to have this structure only 4 byte size(
> > because adapter excepts it to be 4B sise) and therefor packed is used.
> > I don't know the way to ensure size of 4 byte and alignment too.  Or I
> > am misunderstanding?
> 
> Yes, you are mis-understanding the rules for padding.. Structures are only
> padded out to their alignment, which depends on their constituent types.
> This is so arrays of structures have each array element starting on its 
> natural
> alignment.
> 
> The aligned attribute overrides the automatic determination of the
> alignment based on the contents and just forces it.
> 
> So, as an example, if you have this hardware layout:
> 
> struct {
>   u32 fielda;
>   u64 fieldb;
> } attribute ((aligned(4));
> 
> David is saying you will get a 12 byte struct and fieldb will be unaligned. 
> Since
> 12 is aligned to 4 no padding is added.

So I decided to experiment above example before implementing in driver. However 
I find structure of 16 bytes (instead of 12) with padding after fielda in below 
example.
Am I missing some compiler option or syntax error in attribute? Sorry to ask 
this silly question.
I tried __attribute__((__aligned__(4))); too based on usage in other kernel 
code.

#include <linux/module.h>

struct foo {
        u32 a;
        u64 b;
} __attribute__((aligned(4)));

static int __init main_init(void)
{
        printk("<1> sizeof foo=%ld\n", sizeof(struct foo));
        printk("<1> offset of a=%ld\n", offsetof(struct foo, a));
        printk("<1> offset of b=%ld\n", offsetof(struct foo, b));
        return 0;
}
static void __exit main_exit(void)
{
}
module_init(main_init);
module_exit(main_exit);
Output:
Mar 24 05:44:10 parav-sles11-sp1-64 kernel: [2006356.094931]  sizeof foo=16
Mar 24 05:44:10 parav-sles11-sp1-64 kernel: [2006356.094934]  offset of a=0
Mar 24 05:44:10 parav-sles11-sp1-64 kernel: [2006356.094936]  offset of b=8

Gcc version is below.

Using built-in specs.
Target: x86_64-suse-linux
Configured with: ../configure --prefix=/usr --infodir=/usr/share/info 
--mandir=/usr/share/man --libdir=/usr/lib64 --libexecdir=/usr/lib64 
--enable-languages=c,c++,objc,fortran,obj-c++,java,ada 
--enable-checking=release --with-gxx-include-dir=/usr/include/c++/4.3 
--enable-ssp --disable-libssp --with-bugurl=http://bugs.opensuse.org/ 
--with-pkgversion='SUSE Linux' --disable-libgcj --disable-libmudflap 
--with-slibdir=/lib64 --with-system-zlib --enable-__cxa_atexit 
--enable-libstdcxx-allocator=new --disable-libstdcxx-pch 
--enable-version-specific-runtime-libs --program-suffix=-4.3 
--enable-linux-futex --without-system-libunwind --with-cpu=generic 
--build=x86_64-suse-linux
Thread model: posix
gcc version 4.3.4 [gcc-4_3-branch revision 152973] (SUSE Linux)

> For hardware facing structures I'd combine this with a static assert to verify
> structure size at compile time.
> 
> So..
> 
> 1) Avoid using attributes unless the structure has unaligned members.
> 2) Avoid creating structures with unaligned members (eg for userspace
>    communication)
> 3) Frown at hardware/firmware developers who make communication
>    structures with unaligned members :)
> 4) Be explicit about padding in your layout for 64/32
>    compatibility.
> 
> Jason
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to