What's in a (type) name?
The C <stdint.h> header file defines a number of types for developers who need to specify exactly how they need an integer variable to be represented. For example, int16_t is a 16-bit, signed type, while uint64_t is a 64-bit, unsigned type. This level of control is needed when defining data structures that are implemented by hardware, are exchanged through communications protocols — or are passed between user and kernel space.
The kernel, though, does not use these types to define its system-call interface. Instead, the kernel has its own types defined internally. Rather than use uint64_t, for example, the kernel's API definitions use __u64. That has been the situation for a long time — since before the standard C types existed — and is simply part of how the kernel project does things.
As a general rule, the man pages reflect the kernel's definition of data types. So, for example, the bpf() man page defines one piece of the bpf_attr union as:
    struct {    /* Used by BPF_MAP_*_ELEM and BPF_MAP_GET_NEXT_KEY
                   commands */
	__u32         map_fd;
	__aligned_u64 key;
	union {
	    __aligned_u64 value;
	    __aligned_u64 next_key;
	};
	__u64         flags;
    };
These types are familiar to kernel developers, but they may look a bit strange to user-space developers. Back in April of 2021, man-pages co-maintainer Alejandro Colomar decided to make things look more familiar by rewriting the man pages to use the standard C types instead. Perhaps out of love for a challenge, Colomar started with the bpf() man page; after applying the patch, the above structure was defined as:
    struct {    /* Used by BPF_MAP_*_ELEM and BPF_MAP_GET_NEXT_KEY commands */
        uint32_t                     map_fd;
        uint64_t [[gnu::aligned(8)]] key;
        union {
            uint64_t [[gnu::aligned(8)]] value;
            uint64_t [[gnu::aligned(8)]] next_key;
         };
         uint64_t                     flags;
     };
This patch was immediately vetoed
by BPF maintainer Alexei Starovoitov, who said: "The man page should
describe the kernel api the way it is in .h file
".  Colomar answered
that the actual types used are the same either way, and that his change was
better for users:
If we have a standard syntax for fixed-width integral types (and for anything, actually), the manual pages should probably follow it, whenever possible. Any deviation from the standard (be it C or POSIX) should have a very good reason to be; otherwise, it only creates confusion.
Starovoitov stood firm in his opposition, though, saying that the man pages should describe the types as they will be defined when code includes the associated kernel header file.
Colomar returned
in May 2021 with a new version of the patch that was little changed from
its predecessor.  Also unchanged was the reception it got.  This time, Greg
Kroah-Hartman also expressed his
opposition, saying that the types involved "are not the same, they
live in different namespaces, and worlds, and can not always be swapped
out for each other on all arches
".  GNU C Library developer Zack
Weinberg disagreed,
though:
Manpage documentation of C structs is *not* expected to match the actual declaration in the headers. The documented field type is usually assignment-compatible with the actual type, but not always. There's no guarantee whatsoever that the fields are in the same order as the header, or that the listed set of fields is complete.
This argument failed to convince the kernel community, though, which remained strongly against the change. This discussion then died down for over a year.
Colomar returned with a new patch converting many more files in August 2022; he included the Nacked-by tags he had received from three different developers. Unsurprisingly, those developers had not become more sympathetic toward the idea during the pause. Starovoitov repeated his opposition and asked Colomar to stop sending the patch.
In response, Colomar went ahead and applied the patch to the man-pages repository. A kernel patch that had encountered such opposition would almost certainly never have been applied, but the man pages are not a kernel project. Colomar appears to be the only active man-pages maintainer at the moment; longtime maintainer Michael Kerrisk has seemingly vanished from the scene since the man pages 5.13 release in August 2021. So there is nobody who is in a position to overrule Colomar when it comes to decisions in this area.
Much of the discussion covered the same ground as with the previous versions, but this time Linus Torvalds jumped in as well. He pointed out that the kernel's types simply cannot be the same as the standard C types without creating namespace problems: the kernel cannot include <stdint.h> to define those types, but also cannot define those types itself in files used by user space without creating conflicts there. Torvalds agreed with the others that the documentation should match the actual types used.
Honestly, I don't think it makes a *huge* amount of difference, but documentation that doesn't actually match the source of the documentation will just confuse somebody in the end. Somebody will go "that's not right", and maybe even change the structure definitions to match the documentation.
This message, along with a request from Kroah-Hartman to revert the change, was enough to convince Colomar to back down. His concluding words were:
You convinced me. The man-pages will document the types exactly as they are in kernel. It's just simpler.As the patch was recently reverted after Greg asked me to do, I'll keep it that way. I guess this closes the man-pages discussion.
The interesting thing, of course, is that the kernel does, indeed, define
many of the standard types internally, and there are thousands of
variables defined using those types.  Using standard C types in the kernel is
not, itself, a problem; only using them in the user-space API definitions is.  With
sufficient will, this might well be a problem that could be overcome, but
it would not be a small job.
Meanwhile, it seems that the man pages will continue to document the types
that are actually used in the kernel's user-space API header files.
| Index entries for this article | |
|---|---|
| Kernel | Documentation/man pages | 
      Posted Sep 2, 2022 17:09 UTC (Fri)
                               by adobriyan (subscriber, #30858)
                              [Link] (2 responses)
       
     
    
      Posted Sep 2, 2022 20:09 UTC (Fri)
                               by Bigos (subscriber, #96807)
                              [Link] (1 responses)
       
Your proposal of u64_a8 is pretty confusing, as the first number is in bits and the second is in bytes. 
     
    
      Posted Sep 3, 2022 14:50 UTC (Sat)
                               by adobriyan (subscriber, #30858)
                              [Link] 
       
Fixed-width integer types are always in bits: uintN_t, uN, __uN, sN, iN, newly added_DecimalN, _Bitint(N) 
     
      Posted Sep 2, 2022 20:34 UTC (Fri)
                               by ddevault (subscriber, #99589)
                              [Link] (1 responses)
       
     
    
      Posted Sep 3, 2022 5:31 UTC (Sat)
                               by neilbrown (subscriber, #359)
                              [Link] 
       
https://git.kernel.org/pub/scm/docs/man-pages/man-pages.g... 
 
     
      Posted Sep 2, 2022 20:44 UTC (Fri)
                               by nickodell (subscriber, #125165)
                              [Link] (17 responses)
       
>There's a very old post from Linus where he describes the difference between things like __u32 and uint32_t [...] Dig it up if you are curious 
Does anyone have a link to this? 
     
    
      Posted Sep 2, 2022 21:11 UTC (Fri)
                               by cesarb (subscriber, #6266)
                              [Link] (15 responses)
       
     
    
      Posted Sep 2, 2022 23:00 UTC (Fri)
                               by koh (subscriber, #101482)
                              [Link] (8 responses)
       
     
    
      Posted Sep 3, 2022 1:02 UTC (Sat)
                               by abatters (✭ supporter ✭, #6932)
                              [Link] (7 responses)
       
     
    
      Posted Sep 3, 2022 3:07 UTC (Sat)
                               by ABCD (subscriber, #53650)
                              [Link] (6 responses)
       The portable (as of C99) way to use printf and scanf (in userspace) with those types is to do things like: 
     
    
      Posted Sep 3, 2022 16:37 UTC (Sat)
                               by pm215 (subscriber, #98099)
                              [Link] (5 responses)
       
 
     
    
      Posted Sep 3, 2022 19:55 UTC (Sat)
                               by SAI_Peregrinus (subscriber, #151778)
                              [Link] (2 responses)
       
When has that ever been a design principle of C? 
     
    
      Posted Sep 4, 2022 12:01 UTC (Sun)
                               by jezuch (subscriber, #52988)
                              [Link] 
       
     
      Posted Sep 5, 2022 11:06 UTC (Mon)
                               by pm215 (subscriber, #98099)
                              [Link] 
       
 
     
      Posted Sep 5, 2022 23:51 UTC (Mon)
                               by skissane (subscriber, #38675)
                              [Link] (1 responses)
       
Really, the C standards committee should introduce a nicer way of doing that. 
%(u64) or something like that. (I don't know which punctuation symbols are in use or reserved and which are not, but surely someone can come up with something which doesn't clash with existing uses.) 
     
    
      Posted Sep 6, 2022 23:02 UTC (Tue)
                               by dezgeg (subscriber, #92243)
                              [Link] 
       
     
      Posted Sep 3, 2022 9:41 UTC (Sat)
                               by pbonzini (subscriber, #60935)
                              [Link] (5 responses)
       
     
    
      Posted Sep 3, 2022 15:18 UTC (Sat)
                               by cpacejo (subscriber, #153871)
                              [Link] (1 responses)
       
It's therefore relevant that, because they are of different rank, `long` and `long long` are not "compatible types", even if they happen to be of the same width.  Notably, this means that you cannot substitute a pointer to one for the other (likely resulting in a compile time error), and that such mixed pointers are assumed by the compiler not to alias each other (possibly leading to subtle runtime issues).  See https://stackoverflow.com/a/66850819 for a good explanation. 
     
    
      Posted Sep 5, 2022 8:31 UTC (Mon)
                               by geert (subscriber, #98403)
                              [Link] 
       
For the interested, you can find some clues in the commit that removed the last remnants: 
     
      Posted Sep 3, 2022 16:01 UTC (Sat)
                               by rwmj (subscriber, #5474)
                              [Link] (2 responses)
       
     
    
      Posted Sep 3, 2022 16:48 UTC (Sat)
                               by pbonzini (subscriber, #60935)
                              [Link] (1 responses)
       
     
    
      Posted Sep 9, 2022 14:38 UTC (Fri)
                               by andyp (subscriber, #48701)
                              [Link] 
       
#ifdef __KERNEL__ 
Or something like that. 
     
      Posted Sep 4, 2022 9:00 UTC (Sun)
                               by bmork (subscriber, #88411)
                              [Link] 
       
This has been discussed so many times that it's hard to know exactly which post that refers to.  But I guess it could be the 2004 rant Russel reposted here: https://lkml.iu.edu/hypermail/linux/kernel/1506.0/00160.html 
     
      Posted Sep 2, 2022 23:33 UTC (Fri)
                               by koh (subscriber, #101482)
                              [Link] (9 responses)
       
Note: "compatible type" is all C requires for interchangeability. 
     
    
      Posted Sep 3, 2022 6:07 UTC (Sat)
                               by epa (subscriber, #39769)
                              [Link] (8 responses)
       
 
     
    
      Posted Sep 3, 2022 10:18 UTC (Sat)
                               by jengelh (guest, #33263)
                              [Link] (7 responses)
       
2. For *any* typedef for uint32_t that /usr/include/linux/types.h would provide, a libc implementation sufficiently unknown to the Linux project could provide a /usr/include/stdint.h with a re-declaration of the typedef in an incompatible form (e.g. by making use of some weird implementation-defined extensions). So that's why even a subset of the C library is not going to be used. 
(That didn't prevent people from using uint* in e.g. /usr/include/linux/sctp.h. Because frankly, the number of libcs that are decidedly playing evil is quite close to zero.) 
     
    
      Posted Sep 3, 2022 10:46 UTC (Sat)
                               by Cyberax (✭ supporter ✭, #52523)
                              [Link] (1 responses)
       
Why is this a problem? The kernel will not be using ANY libc during its build. It comes into play only when the headers are used in userspace software. Using something like: 
> #ifdef __KERNEL__  
     
    
      Posted Sep 5, 2022 8:55 UTC (Mon)
                               by metan (subscriber, #74107)
                              [Link] 
       
See the v3 of the patch I send https://lore.kernel.org/lkml/CAK8P3a2J5k2ub6TNu9qDympdWEd... 
     
      Posted Sep 3, 2022 11:01 UTC (Sat)
                               by pbonzini (subscriber, #60935)
                              [Link] 
       
One reason for Linux does not use them is for compatibility between platforms, so that the same driver code compiles independent of which types are used for the definition of uintNN_t (without e.g. warnings about incompatible pointer types between long long and intNN_t). 
     
      Posted Sep 5, 2022 22:03 UTC (Mon)
                               by NYKevin (subscriber, #129325)
                              [Link] (3 responses)
       
TL;DR: Is this man page intended for kernel developers, and just incidentally useful to userspace developers, or vice-versa? It can't be both. 
* Yes, libc probably should provide documentation for their wrappers. But they don't, because the GNU people hate man pages. 
     
    
      Posted Sep 6, 2022 17:15 UTC (Tue)
                               by Wol (subscriber, #4433)
                              [Link] (2 responses)
       
I'm inclined to agree, but they could always do info pages instead. There's a fairly simple way to convert tbem to man, I believe... 
Cheers, 
     
    
      Posted Sep 6, 2022 17:57 UTC (Tue)
                               by mpr22 (subscriber, #60784)
                              [Link] (1 responses)
       
     
    
      Posted Sep 6, 2022 19:56 UTC (Tue)
                               by NYKevin (subscriber, #129325)
                              [Link] 
       
As you can see from the table of contents (https://www.gnu.org/software/libc/manual/html_node/index....), they really aren't structured like a set of man pages at all. This manual is useful, if you're trying to learn an entire API from the ground up, but less so if you just want to look up the signature of a function, its invariants, errno values, or something like that. 
     
      Posted Sep 3, 2022 0:18 UTC (Sat)
                               by Manifault (guest, #155796)
                              [Link] (3 responses)
       
Also, it seems like a bit of a broken process if the maintainer of a documented system with a man page cannot override a suggestion to update how that system is documented in its man page. I get that man-pages is a different repo, but this doesn't seem conducive to providing users with the most accurate documentation, nor does it seem scalable. In general, I'll admit that I don't really understand why it wouldn't be better for everyone for the man-pages project to just pull documentation for these large subsystems directly from the kernel tree. What's the point of having two sources of "truth" for documentation? Especially when the maintainer of the actual subsystem only has control over one of them (so only one of them is really the source of truth). 
https://kernel-recipes.org/en/2022/once-upon-an-api/ 
     
    
      Posted Sep 3, 2022 16:02 UTC (Sat)
                               by cortana (subscriber, #24596)
                              [Link] 
       
     
      Posted Sep 3, 2022 16:41 UTC (Sat)
                               by pm215 (subscriber, #98099)
                              [Link] (1 responses)
       
     
    
      Posted Sep 6, 2022 23:51 UTC (Tue)
                               by Manifault (guest, #155796)
                              [Link] 
       
     
      Posted Sep 3, 2022 19:56 UTC (Sat)
                               by scientes (guest, #83068)
                              [Link] (2 responses)
       
This isn't true. Look at <stdbool.h> (Linus' criticism of it non-withstanding)---c compilers certainly *could* support <stdint.h> in freestanding mode, they just don't. 
It is like his criticism of the C++ memory model, which is just fine, and could totally be used by Linux. 
     
    
      Posted Sep 3, 2022 20:00 UTC (Sat)
                               by scientes (guest, #83068)
                              [Link] 
       
     
      Posted Sep 4, 2022 20:00 UTC (Sun)
                               by fw (subscriber, #26023)
                              [Link] 
       
     
      Posted Sep 8, 2022 0:32 UTC (Thu)
                               by milesrout (subscriber, #126894)
                              [Link] (1 responses)
       
     
    
      Posted Sep 9, 2022 1:13 UTC (Fri)
                               by foom (subscriber, #14868)
                              [Link] 
       
     
    What's in a (type) name?
      
What's in a (type) name?
      
What's in a (type) name?
      
Even SIMD stuff is in bits: __m128, __m256. 
What's in a (type) name?
      
What's in a (type) name?
      
What's in a (type) name?
      
What's in a (type) name?
      
What's in a (type) name?
      
      I haven't had much problem with 32-bit ints, but 64-bit ints are annoying to work with portably.
What's in a (type) name?
      
32-bit userspace, 32-bit kernel, and 64-bit kernel:
typedef unsigned long long uint64_t;
64-bit userspace:
typedef unsigned long uint64_t;
uint64_t x = 777;
// compiler complains about these depending on arch
printf("%lu", x);
printf("%llu", x);
scanf("%lu", &x);
scanf("%llu", &x);
// these are portable but require more code
printf("%llu", (unsigned long long) x);
unsigned long long tmp;
scanf("%llu", &tmp);
x = tmp;
      
          What's in a (type) name?
      #include <inttypes.h>
uint64_t x = 777;
printf("%" PRIu64, x);
scanf("%" SCNu64, &x);
      
          What's in a (type) name?
      
What's in a (type) name?
      
What's in a (type) name?
      
What's in a (type) name?
      
What's in a (type) name?
      
What's in a (type) name?
      
What's in a (type) name?
      
What's in a (type) name?
      
What's in a (type) name?
      
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/...
What's in a (type) name?
      
What's in a (type) name?
      
What's in a (type) name?
      
/* Current definitions */
#else
typedef __u64 uint64_t;
typedef __u32 uint32_t;
/* etc. */
#endif
What's in a (type) name?
      
What's in a (type) name?
      
What's in a (type) name?
      
What's in a (type) name?
      
What's in a (type) name?
      
> #include <kernels_homegrown_types.h>
> #else
> #include <stdint.h>
> #endif
What's in a (type) name?
      
What's in a (type) name?
      
What's in a (type) name?
      
What's in a (type) name?
      
Wol
What's in a (type) name?
      
What's in a (type) name?
      
What's in a (type) name?
      
What's in a (type) name?
      
What's in a (type) name?
      
What's in a (type) name?
      
What's in a (type) name?
      
"standard" names, and *cannot* use them for namespace reasons, and you
ignore all the feedback, and then you claim you are asking for review?
-Torvalds
What's in a (type) name?
      
What's in a (type) name?
      
What's in a (type) name?
      
What's in a (type) name?
      
           