Alan Stern <[EMAIL PROTECTED]> writes:
> On Mon, 12 Feb 2007, Sergei Organov wrote:
>
>> The fact remains that even GCC extensions to C can't deal with
>> endianness. I'd like to have such an extension though.
>
> It would be nice.  And useful.  It would also be nice if the compiler 
> could deal with unaligned data automatically.

Probably, but the only sane way to achieve the latter is declaring a
type to be unaligned, not an object. Using "packed" on a struct doesn't
change the types of the fields, only their alignment, and that's a
problem.

Now, __attribute__((aligned(1))) attached to a type doesn't change GCC's
behavior w.r.t. fetches using a pointer to this type. I begin to think
that it's indeed more consistent and useful to actually have such
attributes attached to the type, but the fact remains that it's not an
option just now.

So, provided we don't have proper endianness and alignment support in the
compiler, what option is the best to solve the problem at hand? I still
think that opaque struct utilizing u8[2] is the way to go.

> Bear in mind that sometimes you don't need to convert data values from
> foreign byte-ordering to native.  Bitwise operations like ~, &, |, and ==
> will work okay provided both operands have the same byte-ordering.

Yes, I once did that (defined constants representing bits in the
registers in non-native mode) for a little-endian controller attached to
big-endian target, and then dropped this idea even though it was not a
requirement for this code to be portable to a little-endian target. IMHO
it's much cleaner to get to the native endianness first.

Anyway, in those rare cases where possible speed-up is indeed valuable,
bitwise operations could still be implemented on the opaque type, and
the only thing we will loose is C syntax.

>> Besides, I've already said that I agree that __le16 is better than, say,
>> __u16 due to the fact that it imposes more restrictions on the usage of
>> corresponding fields, but having 'le' in its name doesn't help with
>> endianness issues the same way having "percentage" in a type name
>> doesn't help with its expected 0--100 range.
>> 
>> What I argue against, is that "__le16 foo" is any better than "__u8
>> foo_le[2]" from the POV of endianness. Or, let's put it another way,
>> provided we prefer to encode endianness in the type name, why not to
>> declare it like this:
>> 
>>   typedef struct { __u8 bytes[2]; } __le16_t;
>> 
>> IMHO, this declarations express the intent of the type better than
>> current declaration of __le16. It allows to correctly declare descriptor
>> structures without 'packed' hackery. It avoids alignment problems.
>
> Alignment (and packing) is a completely independent issue.  It would still
> be a problem even if the data value used native byte-ordering.

Yes, indeed. In fact these two issues (endianness and alignment) were
made dependent in this discussion due to 2 reasons:

1. I said that often the code that uses "packed" on structs contains
   endianness problems as well. This happens to be my previous
   experience, nothing more.

2. Somebody else said that we'd miss some essential type information if
   we use u8[2] instead of __le16, and I was arguing against that.

>> It prevents using of variables/fields of this type as bare integers
>> without resorting to GCC extensions/sparse annotations. Finally, it
>> makes it obvious that your favorite:
>> 
>>     get_unaligned_le16(__le16_t const*)
>> 
>> is indeed a good idea ;)
>
> :-)
>
>> I'm yet to hear single argument against the above.
>
>     1.  It would prevent using bitwise operations.

To some extent. If you use it as an opaque structure you still can
define routines/macros to perform bitwise operations on it. Not that I
think it's a good idea to use bitwise operations in non-native
endianness in most cases.

>     2.  It might prevent (depending on how clever the implementation was)
>       certain optimizations on little-endian CPUs.

Maybe. But on the other hand, fetching an (unaligned) int in wrong
endianness and then converting it to the native endianness might be not
very efficient either. The fact is that almost for sure the code could
be made clever enough to perform just fine.

>
>     3.  It would essentially force all accesses to be treated as if they
>       were unaligned, even when the programmer knew they were not.

IMHO, it's safer to be pessimistic in this situation and do safe
unaligned access by default. Then, nobody prevents to define and use
special routines that will behave as if the pointer passed is indeed
aligned, but this usage will then be explicit.

Though in fact I think it won't hurt if all the fields of USB
descriptors are considered to be unaligned, so I'd bet on safety,
correctness, and simplicity in this case.

> Then there's the pragmatic reason: A lot of code has already been written
> and would all need to be changed over.

Yes, that's a very sound reason, and in fact I'm far from insisting on
(urgent) changes of the existing code. I consider this discussion to be
more an educational one that hopefully will lead to better selection of
strategies in the future. On the other hand, changing the code in a
right direction is a good thing.

Returning back to "packed", I still think it's the worst method to deal
with alignment issues.

-- Sergei

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier.
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to