gcc packed structs?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
proxy

Re:gcc packed structs?

Post by proxy »

BTW, just a follow up, bitfields are nice and all, but they have a downside..the way they are implemented is left up to the compiler writters, it is implementation defined.

this means that the order the fields go (LSB first or MSB first?) and in fact the order they are placed can change between compilers (or even compiler versions technically speaking...though that's highly unlikely).

like i said before, if you are sticking with one compiler it really doesn't make a difference, but if you are worried about portability...stay away :)

proxy
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:gcc packed structs?

Post by Pype.Clicker »

Well, of course bitfields are architecture-dependent ... just take a look at PowerPC processors which are big-endian(?) while Intel processors are little-endian (it may be the contrary: i always mess up those two terms).

One will store the lowest bits of 0x12345678 first and the other will store the highest bits first. You shouldn't expect the same compiler to produce a bit-to-bit match of a bitfield made of 0x12345678 ... The very same way you shouldn't expect union { char c[4]; int; } to be portable across those architectures...

However, you need "trustable" bitfields mainly for architecture-dependent things like IDT, page table entries, etc. So it doesn't harm if those pieces of code are not portable.
Those architecture-dependent files are certainly full of asm(...) definitions aswell, so who cares if they're not portable to another compiler family ... If you really need another compiler to support your kernel (hum, ever tried to compile Linux kernel with msvc++ ?), you'll have to port the architecture/platform dependent code, including the bitfields definition, asm commands like "setPDBR() or FlushTranslationLookasideBuffer(), enable() and disable()" ...

Just bind those "dependent" parts to a well known place and try hard to avoid architecture/environment dependent stuff elsewhere.
The advantage of bitfields in that domain is that the rest of the text will use a *name* to access a part of the member. Whether arch/i386/stuff.h declared

Code: Select all

struct version {
    int major:10;
    int minor:10;
    int revision:10;
    int :2;
};
while arch/ppc/stuff.h declared

Code: Select all

struct version {
    int :2;
    int revision:10;
    int minor:10;
    int major:10;
};
to match the same pattern will be transparent to code that performs
v.major >= requrired.major ;)
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:gcc packed structs?

Post by Solar »

Pype.Clicker wrote: Well, of course bitfields are architecture-dependent ... just take a look at PowerPC processors which are big-endian(?) while Intel processors are little-endian (it may be the contrary: i always mess up those two terms).
Absolutely correct. Note that some PowerPC's (as well as some other CPU architectures) have the ability to switch into little-endian mode... ;-)
Every good solution is obvious once you've found it.
proxy

Re:gcc packed structs?

Post by proxy »

Pype, unfortunately you fell into a trap there:

Code: Select all

struct version {
    int major:10;
    int minor:10;
    int revision:10;
    int :2;
};
while arch/ppc/stuff.h declared

Code: Select all

struct version {
    int :2;
    int revision:10;
    int minor:10;
    int major:10;
};
is NOT correct! (well the first one is probably) but the second is not the equivalent of byte swapping....if your fields were all less that 8 bits then it would be true to jsut reverse the order...but in this case (since they are 10) you will have major problems...

on PPC it will end up being more like this:

Code: Select all

struct version {
    int major_2: 4
    int major_1: 4
    int minor_2: 4
    int revision_2: 4;
    int minor_1: 4
    int :2;    
    int revision_1: 6;
    
};

this is because the byte swapping will occur on byte boundaries (not field boundaries...resulting in the fields being broken up.

think of it this way...if you cast that structure to a 32-bit unsigned int, then byte swap it...where will the bites end up...not simply the reverse fields...

proxy
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:gcc packed structs?

Post by Candy »

Code: Select all

struct version {
    int :2;
    int revision:10;
    int minor:10;
    int major:10;
};
overview:

Code: Select all

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| pad | major                       | minor                       | revision                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

+--+--+--+--+--+--+--+--+  +--+--+--+--+--+--+--+--+  +--+--+--+--+--+--+--+--+  +--+--+--+--+--+--+--+--+
| pad | major(9-4)      |  |major(3-0) |minor(9-6) |  | minor(5-0)      |r9-8 |  | rev(7-0)              |
+--+--+--+--+--+--+--+--+  +--+--+--+--+--+--+--+--+  +--+--+--+--+--+--+--+--+  +--+--+--+--+--+--+--+--+

+--+--+--+--+--+--+--+--+  +--+--+--+--+--+--+--+--+  +--+--+--+--+--+--+--+--+  +--+--+--+--+--+--+--+--+
| rev(7-0)              |  | minor(5-0)      |r9-8 |  |major(3-0) |minor(9-6) |  | pad | major(9-4)      |
+--+--+--+--+--+--+--+--+  +--+--+--+--+--+--+--+--+  +--+--+--+--+--+--+--+--+  +--+--+--+--+--+--+--+--+

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| rev2(7-0)             | minor(5-0)      | r9-8|major(3-0) |minor(9-6) | pad | major(9-4)      |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

Code: Select all

struct version {
    int major_1: 6;
    int :2;

    int minor_1: 4;
    int major_2: 4;

    int revision_1: 2;
    int minor_2: 6;

    int revision_2: 8;
};
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:gcc packed structs?

Post by Solar »

@ proxy:

As far as I understood it, Pype didn't try to address byte swapping in his example, but rather show how named bitfields allow further source code to handle the individual fields transparently.
Every good solution is obvious once you've found it.
proxy

Re:gcc packed structs?

Post by proxy »

@Candy yea, yours seems to be just about on the money :) I knew mine wasn't quite right, but I figured it was enough to demonstrate the fault.

@Solar well It seemed to me that he was trying to show how bitfields can be handled when porting to a opposite endian system (such as PPC) and frankly his example was very wrong. This is one of the primary reasons why bitfields are "non-portable" the moment you use them. As I said earlier, if you are sticking to the same compiler/arch, well it really doesn't matter...but if you are worried about portability to some extent (as the poster indicated) then bitfields are pretty much a bad option, it introduces too many possible "oops". In fact, I've had issues with poirting from x86 to Solaris where the bitfields didn't end up stricly byteswaped, but byteswapped, then reversed (so high and low bytes were in same spot but middle two bytes seemed to be revered..it was bizzar).

proxy
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:gcc packed structs?

Post by Pype.Clicker »

i was certainly not trying to show a bit-to-bit compatible 'version' that works on both i386 and ppc architecture ... so Solar was right though the others were rightfully spotting a possible trouble that someone who trust too quickly the stuff.h i submitted could encounter :)

If you need complex bitfields (not trivially mapping on single bytes) to be bit-to-bit compatible (for instance because they're stored in files or exchanged across network) it is certainly better to have an "endianness convertion" first on the words and *then* applying the 'local' bitfield ... but even that is not guaranteed to work :-/
Post Reply