KernelNewbies
  • Comments
  • Immutable Page
  • Menu
    • Navigation
    • RecentChanges
    • FindPage
    • Local Site Map
    • Help
    • HelpContents
    • HelpOnMoinWikiSyntax
    • Display
    • Attachments
    • Info
    • Raw Text
    • Print View
    • Edit
    • Load
    • Save
  • Login

Kernel Hacking

  • Frontpage

  • Kernel Hacking

  • Kernel Documentation

  • Kernel Glossary

  • FAQ

  • Found a bug?

  • Kernel Changelog

  • Upstream Merge Guide

Projects

  • KernelJanitors

  • KernelMentors

  • KernelProjects

Community

  • Why a community?

  • Regional Kernelnewbies

  • Personal Pages

  • Upcoming Events

References

  • Mailing Lists

  • Related Sites

  • Programming Links

Wiki

  • Recent Changes

  • Site Editors

  • Side Bar

  • Tips for Editors

  • Hosted by WikiWall

Navigation

  • RecentChanges
  • FindPage
  • HelpContents

Upload page content

You can upload content for the page named below. If you change the page name, you can also upload content for another page. If the page name is empty, we derive the page name from the file name.

File to load page content from
Page name
Comment

KernelNewbies:
  • DataAlignment

Part of the WritingPortableDrivers section

The gcc compiler typically aligns individual fields of a structure on whatever byte boundary it likes in order to provide faster execution. For example, consider this code and resulting output:

Toggle line numbers
   1 #include <stdio.h>
   2 #include <stddef.h>
   3 
   4 struct foo {
   5         char  a;
   6         short b;
   7         int   c;
   8 };
   9 
  10 #define OFFSET_A  offsetof(struct foo, a)
  11 #define OFFSET_B  offsetof(struct foo, b)
  12 #define OFFSET_C  offsetof(struct foo, c)
  13 
  14 int main ()
  15 {
  16         printf ("offset A = %d\n", OFFSET_A);
  17         printf ("offset B = %d\n", OFFSET_B);
  18         printf ("offset C = %d\n", OFFSET_C);
  19         return 0;
  20 }

Running the program gives:

offset A = 0
offset B = 2
offset C = 4

The output shows that the compiler aligned fields b and c in struct foo on even byte boundaries. This is not a good thing when we want to overlay a structure on top of a memory location. Typically driver data structures do not have even byte padding for the individual fields. Because of this, the gcc attribute ((packed)) is used to tell the compiler not to place any "memory holes" within a structure.

If we change the struct foo structure to use the packed attribute like this:

Toggle line numbers
   1 struct foo {
   2         char    a;
   3         short   b;
   4         int     c;
   5 } __attribute__((packed));

Then the output of the program changes to:

offset A = 0
offset B = 1
offset C = 3

Now there are no more memory holes in the structure.

This packed attribute can be used to pack an entire structure, as shown above, or it can be used only to pack a number of specific fields within a structure.

For example, the struct usb_ctrlrequest is defined in include/usb.h as the following:

Toggle line numbers
   1 struct usb_ctrlrequest {
   2         __u8 bRequestType;
   3         __u8 bRequest;
   4         __le16 wValue;
   5         __le16 wIndex;
   6         __le16 wLength;
   7 } __attribute__ ((packed));

This ensures that the entire structure is packed, so that it can be used to write data directly to a USB connection.

But the definition of the struct usb_endpoint_descriptor looks like:

Toggle line numbers
   1 struct usb_endpoint_descriptor {
   2         __u8   bLength           __attribute__((packed));
   3         __u8   bDescriptorType   __attribute__((packed));
   4         __u8   bEndpointAddress  __attribute__((packed));
   5         __u8   bmAttributes      __attribute__((packed));
   6         __le16 wMaxPacketSize    __attribute__((packed));
   7         __u8   bInterval         __attribute__((packed));
   8         __u8   bRefresh          __attribute__((packed));
   9         __u8   bSynchAddress     __attribute__((packed));
  10         unsigned char *extra;   /* Extra descriptors */
  11         int extralen;
  12 };

This ensures that the first part of the structure is packed and can be used to read directly from a USB connection, but the extra and extralen fields of the structure can be aligned to whatever the compiler thinks will be fastest to access.

  • MoinMoin Powered
  • Python Powered
  • GPL licensed
  • Valid HTML 4.01