Macros with unnecessary __constant prefix

This is another set of macros on which I worked during last 2 weeks. Use of __constant_ macros decreased after linux 3.10. According to one research of Julia lawall on deprecated functions, there were 56 uses of __constant_htons in linux 3.10, but now there are 9 only. Basically there is complete set of __constant_ macros in byte order [little endian and big endian] header files. I was in a impression that major part of kernel which was using these macros is handled . I was not expecting that much cases primarily. So,at first my aim was to send patches for all of those remaining cases and then at the end get rid of __constant_ definitions completely. But I was surprised when I ran Coccinelle semantic patch over linux-next. I got around 30 files which are still using these functions. Now it was important to figure out that these macros are not actually handled by anyone or there is something for which these macros are working really good.

Why __constant prefix is unnecessary??

There are two definitions for each __constant_ macro. That is one for big endian case and one for little endian case. Now for example consider macro cpu_to_le16. In big endian cases, macro cpu_to_le16 unfolds to __swab16 which provides special case for constants. In little endian cases, __constant_cpu_to_le16 and cpu_to_le16 expand directly to the same expression. So, we can replace __constant_cpu_to_le16 with cpu_to_le16. On the contrary, for big endian byte order macros opposite happens. For example in little endian cases, macro cpu_to_be16 unfolds to __swab16 which provides special case for constants and in big endian cases, __constant_cpu_to_be16 and cpu_to_be16 expand directly to the same expression. That’s why __constant prefix is unnecessary and we can completely get rid of these macros.

How Coccinelle semantic patch can help in replacing __constant_ with ?

This is very simple case for Coccinelle to handle. One just need 1 metavariable and 1 branch for each transformation in a semantic patch. Here, is a complete semantic patch with all __constant_   macros:

@@expression x;@@

(
– __constant_htons(x)
+ htons(x)
|
– __constant_htonl(x)
+ htonl(x)
|
– __constant_ntohs(x)
+ htons(x)
|
– __constant_ntohl(x)
+ htonl(x)
|
– __constant_cpu_to_le64(x)
+ cpu_to_le64(x)
|
– __constant_le64_to_cpu(x)
+ le64_to_cpu(x)
|
– __constant_cpu_to_le32(x)
+ cpu_to_le32(x)
|
– __constant_le32_to_cpu(x)
+ le32_to_cpu(x)
|
– __constant_cpu_to_le16(x)
+ cpu_to_le16(x)
|
– __constant_le16_to_cpu(x)
+ le16_to_cpu(x)
|
– __constant_cpu_to_be64(x)
+ cpu_to_be64(x)
|
– __constant_be64_to_cpu(x)
+ be64_to_cpu(x)
|
– __constant_cpu_to_be32(x)
+ cpu_to_be32(x)
|
– __constant_be32_to_cpu(x)
+ be32_to_cpu(x)
|
– __constant_cpu_to_be16(x)
+ cpu_to_be16(x)
|
– __constant_be16_to_cpu(x)
+ be16_to_cpu(x)
)

Does all files compiles after this change?

Yes. They do. Only problem was with s390 directory. Although errors which we get while compiling s390 files has nothing to do with this change. But those errors are in included header files and when header files have errors gcc eventually stops from there. So, to be sure that this change is correct, I checked each s390 file with cross compiler.

I have sent some patches related to same. I hope there is nothing which I am missing in this case. And once those patches will be accepted, I will send all other patches and hopefully till the end of internship I will be done with getting rid of all __constant_ definitions and their uses. Important thing which I learned during this was cross compilation of s390. I will write about cross compilation process of s390 in my next blog along with some other architecture related stuff.

Till then stay tuned! 🙂

21 thoughts on “Macros with unnecessary __constant prefix

  1. At first it was written for constants. [http://lxr.free-electrons.com/source/include/asm-ppc/byteorder.h?v=2.0.40#L28] Here, in this link you can see that there is no difference between definitions. So, point is whether htonl() or __constant_htonl() is used, if the argument is a constant the conversion happens at compile time. Thus we can just replace them. I hope this clears your doubt. 🙂

    Like

    • Thanks, I didn’t know that the compiler acts differently if the argument was a constant or not in cases of conversion.
      I am still thinking what is the difference that the compiler does when I use cpu_to_be16(x) for example when x is constant and when it is not.

      Like

        • Now I understand. If the variable is constant the compiler already knows what is the converted value without the need to convert it using shifts/and/or (if little endian 0x1234, the compiler already knows that the big endian version is 0x3412). Thank a lot, sorry to bother.

          Like

  2. Interesting! I see your point for the little endian. I took a look a the code of __constant_cpu_to_le16 and cpu_to_le16 for big endian. And if I understand correctly, __constant_cpu_to_le16 is not needed for big endian architectures because cpu_to_le16 eventually expands to __swab16 which checks if the passed argument is a constant or not. If it is, it calls ___constant_swab16. Otherwise, it would call __fswab16(x).

    Like

  3. *Total Kernel Newbie Question*

    Do you add in the +, |, and – that is before each macro?What do they do? Also what is the @@ for, is it some sort of import or variable definition?

    Like

    • Hii Gloria

      As I told you on IRC [in one of our mini chat], I work with tool Coccinelle which uses Semantic Patch Language. So, these are some of the features of SmPL. Like it uses patch like +/- notations. Which means after running this patch over kernel directories, we will get an ouput file where files will be there showing you changes in patch format. Every rule of semantic patch starts from @@ and under @@….@@ we define metavariable and some other advanced things. ‘|’ is called disjunction. So, these are only some of those basic features of Coccinelle. For further information you can go for my blog on Coccinelle. I listed all documentation links there. You can go for them to better understand SmPL and Cocccinelle. And obviously you can ping me any time for queries. I am always open for such things. 🙂

      Like

  4. Hi Vashali,

    It is still unclear to me, So by this we mean we can use anyone of them __constant_htonl() or htonl ()

    Like

  5. Hi, so here point is we don’t really need any special macro for constants because behavior of both definitions is same and in the case of htonl() __swab32 is already checking whether the argument is constant or not.

    Like

  6. Hi,
    Can you help me on this too.I am working on porting a driver which is written for little endian architecture to big endian architecture. I do not know how to start on this.First i started with reading your this article and later moving on to explore more on this topic.I came to know that we have several macro defined which convert the code from little to big endian and so on.I just want to know how we will decide which to use and what is the difference between these functions. e.g we have htonl () ntohl () le16_to_cpu () cpu_to_le32 () and if we alreday have macros to convert from network byte to host and vice versa what is the use of other macros le16_to_cpu () cpu_to_le32 () be16_to_cpu () le32_to_cpu () cpu_to_le16 () etc. Also can you explain me the difference between Run-time endianness conversion and Compile-time endianness conversion.

    Like

Leave a comment