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