* Re: [PATCH 00/45] C++: Convert the kernel to C++
2024-01-09 19:57 ` H. Peter Anvin
@ 2024-01-09 23:29 ` Andrew Pinski
2024-01-10 0:29 ` David Howells
2024-01-11 21:01 ` Arsen Arsenović
2024-01-09 23:40 ` David Howells
` (5 subsequent siblings)
6 siblings, 2 replies; 40+ messages in thread
From: Andrew Pinski @ 2024-01-09 23:29 UTC (permalink / raw)
To: H. Peter Anvin; +Cc: David Howells, linux-kernel
On Tue, Jan 9, 2024 at 11:57 AM H. Peter Anvin <hpa@zytor.com> wrote:
>
> Hi all, I'm going to stir the hornet's nest and make what has become the
> ultimate sacrilege.
>
> Andrew Pinski recently made aware of this thread. I realize it was
> released on April 1, 2018, and either was a joke or might have been
> taken as one. However, I think there is validity to it, and I'm going to
> try to motivate my opinion here.
>
> Both C and C++ has had a lot of development since 1999, and C++ has in
> fact, in my personal opinion, finally "grown up" to be a better C for
> the kind of embedded programming that an OS kernel epitomizes. I'm
> saying that as the author of a very large number of macro and inline
> assembly hacks in the kernel.
>
> What really makes me say that is that a lot of things we have recently
> asked for gcc-specific extensions are in fact relatively easy to
> implement in standard C++ and, in many cases, allows for infrastructure
> improvement *without* global code changes (see below.)
>
> C++14 is in my option the "minimum" version that has reasonable
> metaprogramming support has most of it without the type hell of earlier
> versions (C++11 had most of it, but C++14 fills in some key missing pieces).
>
> However C++20 is really the main game changer in my opinion; although
> earlier versions could play a lot of SFINAE hacks they also gave
> absolutely useless barf as error messages. C++20 adds concepts, which
> makes it possible to actually get reasonable errors.
>
> We do a lot of metaprogramming in the Linux kernel, implemented with
> some often truly hideous macro hacks. These are also virtually
> impossible to debug. Consider the uaccess.h type hacks, some of which I
> designed and wrote. In C++, the various casts and case statements can be
> unwound into separate template instances, and with some cleverness can
> also strictly enforce things like user space vs kernel space pointers as
> well as already-verified versus unverified user space pointers, not to
> mention easily handle the case of 32-bit user space types in a 64-bit
> kernel and make endianness conversion enforceable.
>
> Now, "why not Rust"? First of all, Rust uses a different (often, in my
> opinion, gratuitously so) syntax, and not only would all the kernel
> developers need to become intimately familiar to the level of getting
> the same kind of "feel" as we have for C, but converting C code to Rust
> isn't something that can be done piecemeal, whereas with some cleanups
> the existing C code can be compiled as C++.
>
> However, I find that I disagree with some of David's conclusions; in
> fact I believe David is unnecessarily *pessimistic* at least given
> modern C++.
>
> Note that no one in their sane mind would expect to use all the features
> of C++. Just like we have "kernel C" (currently a subset of C11 with a
> relatively large set of allowed compiler-specific extensions) we would
> have "kernel C++", which I would suggest to be a strictly defined subset
> of C++20 combined with a similar set of compiler extensions.) I realize
> C++20 compiler support is still very new for obvious reasons, so at
> least some of this is forward looking.
>
> So, notes on this specific subset based on David's comments.
>
> On 4/1/18 13:40, David Howells wrote:
> >
> > Here are a series of patches to start converting the kernel to C++. It
> > requires g++ v8.
> >
> > What rocks:
> >
> > (1) Inline template functions, which makes implementation of things like
> > cmpxchg() and get_user() much cleaner.
>
> Much, much cleaner indeed. But it also allows for introducing things
> like inline patching of immediates *without* having to change literally
> every instance of a variable.
>
> I wrote, in fact, such a patchset. It probably included the most awful
> assembly hacks I have ever done, in order to implement the mechanics,
> but what *really* made me give up on it was the fact that every site
> where a patchable variable is invoked would have to be changed from, say:
>
> foo = bar + some_init_offset;
>
> ... to ...
>
> foo = imm_add(bar, some_init_offset);
>
>
> > (2) Inline overloaded functions, which makes implementation of things like
> > static_branch_likely() cleaner.
>
> Basically a subset of the above (it just means that for a specific set
> of very common cases it isn't necessary to go all the way to using
> templates, which makes the syntax nicer.)
>
> > (3) Class inheritance. For instance, all those inode wrappers that require
> > the base inode struct to be included and that has to be accessed with
> > something like:
> >
> > inode->vfs_inode.i_mtime
> >
> > when you could instead do:
> >
> > inode->i_mtime
>
> This is nice, but it is fundamentally syntactic sugar. Similar things
> can be done with anonymous structures, *except* that C doesn't allow
> another structure to be anonymously included; you have to have an
> entirely new "struct" statement defining all the fields. Welcome to
> macro hell.
>
> > What I would disallow:
> >
> > (1) new and delete. There's no way to pass GFP_* flags in.
>
> Yes, there is.
>
> void * operator new (size_t count, gfp_flags_t flags);
> void operator delete(void *ptr, ...whatever kfree/vfree/etc need, or a
> suitable flag);
>
> > (2) Constructors and destructors. Nests of implicit code makes the code less
> > obvious, and the replacement of static initialisation with constructor
> > calls would make the code size larger.
>
> Yes and no. It also makes it *way* easier to convert to and from using
> dedicated slabs; we already use semi-initialized slabs for some kinds of
> objects, but it requires new code to make use of.
>
> We already *do* use constructors and *especially* destructors for a lot
> of objects, we just call them out.
>
> Note that modern C++ also has the ability to construct and destruct
> objects in-place, so allocation and construction/destruction aren't
> necessarily related.
>
> There is no reason you can't do static initialization where possible;
> even constructors can be evaluated at compile time if they are constexpr.
>
> Constructors (and destructors, for modules) in conjunction with gcc's
> init_priority() extension is also a nice replacement for linker hack
> tables to invoke intializer functions.
>
> > (3) Exceptions and RTTI. RTTI would bulk the kernel up too much and
> > exception handling is limited without it, and since destructors are not
> > allowed, you still have to manually clean up after an error.
>
> Agreed here, especially since on many platforms exception handling
> relies on DWARF unwind information.
Let me just add a few things about exceptions and RTTI.
In the darwin kernel, C++ is used for device drivers and both
exceptions and RTTI is not used there either. They have been using C++
for kernel drivers since the early 2000s even.
You can find out more at https://developer.apple.com/documentation/driverkit .
There even was a GCC option added an option which would also disable
RTTI and change the ABI to explicitly for the kernel.
-fapple-kext/-mkernel (the former is for only loadable modules while
the latter is for kernel too).
Note even in GCC, we disable exceptions and RTTI while building GCC.
This is specifically due to not wanting to use them and use other
methods to do that.
Note GDB on the other hand used to use setjmp/longjmp for their
exception handling in C and I think they moved over to using C++
exceptions which simplified things there. But as far as I know the
Linux kernel does not use a mechanism like that (I know of copy
from/to user using HW exceptions/error/interrupt handling but that is
a special case only).
>
> > (4) Operator overloading (except in special cases).
>
> See the example of inline patching above. But yes, overloading and
> *especially* operator overloading should be used only with care; this is
> pretty much true across the board.
>
> > (5) Function overloading (except in special inline cases).
>
> I think we might find non-inline cases where it matters, too.
>
> > (6) STL (though some type trait bits are needed to replace __builtins that
> > don't exist in g++).
>
> Just like there are parts of the C library which is really about the
> compiler and not part of the library. <type_traits> is part of that for C++.
There is an idea of a free standing C++ library. newer versions of
GCC/libstdc++ does support that but IIRC can only be configured at
compile time of GCC.
type_traits and a few other headers are included in that. I have not
looked into it fully though.
Thanks,
Andrew Pinski
>
> > (7) 'class', 'private', 'namespace'.
> >
> > (8) 'virtual'. Don't want virtual base classes, though virtual function
> > tables might make operations tables more efficient.
>
> Operations tables *are* virtual classes. virtual base classes make sense
> in a lot of cases, and we de facto use them already.
>
> However, Linux also does conversion of polymorphic objects from one type
> to another -- that is for example how device nodes are implemented.
> Using this with C++ polymorphism without RTTI does require some
> compiler-specific hacks, unfortunately.
>
> > Issues:
> >
> > (1) Need spaces inserting between strings and symbols.
>
> I have to admit I don't really grok this?
>
> > (2) Direct assignment of pointers to/from void* isn't allowed by C++, though
> > g++ grudgingly permits it with -fpermissive. I would imagine that a
> > compiler option could easily be added to hide the error entirely.
>
> Seriously. It should also enforce that it should be a trivial type.
> Unfortunately it doesn't look like there is a way to create user-defined
> implicit conversions from one pointer to another (via a helper class),
> which otherwise would have had some other nice applications.
>
> > (3) Need gcc v8+ to statically initialise an object of any struct that's not
> > really simple (e.g. if it's got an embedded union).
>
> Worst case: constexpr constructor.
>
> > (4) Symbol length. Really need to extern "C" everything to reduce the size
> > of the symbols stored in the kernel image. This shouldn't be a problem
> > if out-of-line function overloading isn't permitted.
>
> This really would lose arguably the absolutely biggest advantage of C++:
> type-safe linkage. This is the one reason why Linus actually tried to
> use C++ in one single version of the kernel in the early days (0.99.14,
> if I remember correctly.) At that time, g++ was nowhere near mature
> enough, and it got dropped right away.
>
>
> > So far, it gets as far as compiling init/main.c to a .o file.
>
> ;)
^ permalink raw reply [flat|nested] 40+ messages in thread* Re: [PATCH 00/45] C++: Convert the kernel to C++
2024-01-09 23:29 ` Andrew Pinski
@ 2024-01-10 0:29 ` David Howells
2024-01-11 21:01 ` Arsen Arsenović
1 sibling, 0 replies; 40+ messages in thread
From: David Howells @ 2024-01-10 0:29 UTC (permalink / raw)
To: Andrew Pinski; +Cc: dhowells, H. Peter Anvin, linux-kernel
Andrew Pinski <pinskia@gmail.com> wrote:
> Note even in GCC, we disable exceptions and RTTI while building GCC.
> This is specifically due to not wanting to use them and use other
> methods to do that.
> Note GDB on the other hand used to use setjmp/longjmp for their
> exception handling in C and I think they moved over to using C++
> exceptions which simplified things there. But as far as I know the
> Linux kernel does not use a mechanism like that (I know of copy
> from/to user using HW exceptions/error/interrupt handling but that is
> a special case only).
If we were to allow exception handling, I wonder if we would actually need to
throw anything other than a signed long integer (e.g. an error code) and just
disable RTTI. Maybe something like:
long sys_rename(...)
{
struct rwsem_lock lock_a, lock_b;
struct inode *dir_a, *dir_b;
...
try {
if (dir_a > dir_b) {
lock_a.down_write_killable(dir_a);
lock_b.down_write_killable(dir_b);
} else {
lock_b.down_write_killable(dir_b);
lock_a.down_write_killable(dir_a);
}
} catch (-EINTR) {
throw -ERESTARTSYS;
}
...
}
then have a cut-down exception unwinder that only needs to deal with long
values.
However, I think rolling out exception handling in the kernel might be too big
a task, given the huge amount of code involved - however much we might like to
avoid all those return value checks.
David
^ permalink raw reply [flat|nested] 40+ messages in thread* Re: [PATCH 00/45] C++: Convert the kernel to C++
2024-01-09 23:29 ` Andrew Pinski
2024-01-10 0:29 ` David Howells
@ 2024-01-11 21:01 ` Arsen Arsenović
1 sibling, 0 replies; 40+ messages in thread
From: Arsen Arsenović @ 2024-01-11 21:01 UTC (permalink / raw)
To: Andrew Pinski; +Cc: H. Peter Anvin, David Howells, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 12737 bytes --]
Andrew Pinski <pinskia@gmail.com> writes:
> On Tue, Jan 9, 2024 at 11:57 AM H. Peter Anvin <hpa@zytor.com> wrote:
>>
>> Hi all, I'm going to stir the hornet's nest and make what has become the
>> ultimate sacrilege.
>>
>> Andrew Pinski recently made aware of this thread. I realize it was
>> released on April 1, 2018, and either was a joke or might have been
>> taken as one. However, I think there is validity to it, and I'm going to
>> try to motivate my opinion here.
>>
>> Both C and C++ has had a lot of development since 1999, and C++ has in
>> fact, in my personal opinion, finally "grown up" to be a better C for
>> the kind of embedded programming that an OS kernel epitomizes. I'm
>> saying that as the author of a very large number of macro and inline
>> assembly hacks in the kernel.
>>
>> What really makes me say that is that a lot of things we have recently
>> asked for gcc-specific extensions are in fact relatively easy to
>> implement in standard C++ and, in many cases, allows for infrastructure
>> improvement *without* global code changes (see below.)
>>
>> C++14 is in my option the "minimum" version that has reasonable
>> metaprogramming support has most of it without the type hell of earlier
>> versions (C++11 had most of it, but C++14 fills in some key missing pieces).
>>
>> However C++20 is really the main game changer in my opinion; although
>> earlier versions could play a lot of SFINAE hacks they also gave
>> absolutely useless barf as error messages. C++20 adds concepts, which
>> makes it possible to actually get reasonable errors.
>>
>> We do a lot of metaprogramming in the Linux kernel, implemented with
>> some often truly hideous macro hacks. These are also virtually
>> impossible to debug. Consider the uaccess.h type hacks, some of which I
>> designed and wrote. In C++, the various casts and case statements can be
>> unwound into separate template instances, and with some cleverness can
>> also strictly enforce things like user space vs kernel space pointers as
>> well as already-verified versus unverified user space pointers, not to
>> mention easily handle the case of 32-bit user space types in a 64-bit
>> kernel and make endianness conversion enforceable.
>>
>> Now, "why not Rust"? First of all, Rust uses a different (often, in my
>> opinion, gratuitously so) syntax, and not only would all the kernel
>> developers need to become intimately familiar to the level of getting
>> the same kind of "feel" as we have for C, but converting C code to Rust
>> isn't something that can be done piecemeal, whereas with some cleanups
>> the existing C code can be compiled as C++.
>>
>> However, I find that I disagree with some of David's conclusions; in
>> fact I believe David is unnecessarily *pessimistic* at least given
>> modern C++.
>>
>> Note that no one in their sane mind would expect to use all the features
>> of C++. Just like we have "kernel C" (currently a subset of C11 with a
>> relatively large set of allowed compiler-specific extensions) we would
>> have "kernel C++", which I would suggest to be a strictly defined subset
>> of C++20 combined with a similar set of compiler extensions.) I realize
>> C++20 compiler support is still very new for obvious reasons, so at
>> least some of this is forward looking.
>>
>> So, notes on this specific subset based on David's comments.
>>
>> On 4/1/18 13:40, David Howells wrote:
>> >
>> > Here are a series of patches to start converting the kernel to C++. It
>> > requires g++ v8.
>> >
>> > What rocks:
>> >
>> > (1) Inline template functions, which makes implementation of things like
>> > cmpxchg() and get_user() much cleaner.
>>
>> Much, much cleaner indeed. But it also allows for introducing things
>> like inline patching of immediates *without* having to change literally
>> every instance of a variable.
>>
>> I wrote, in fact, such a patchset. It probably included the most awful
>> assembly hacks I have ever done, in order to implement the mechanics,
>> but what *really* made me give up on it was the fact that every site
>> where a patchable variable is invoked would have to be changed from, say:
>>
>> foo = bar + some_init_offset;
>>
>> ... to ...
>>
>> foo = imm_add(bar, some_init_offset);
>>
>>
>> > (2) Inline overloaded functions, which makes implementation of things like
>> > static_branch_likely() cleaner.
>>
>> Basically a subset of the above (it just means that for a specific set
>> of very common cases it isn't necessary to go all the way to using
>> templates, which makes the syntax nicer.)
>>
>> > (3) Class inheritance. For instance, all those inode wrappers that require
>> > the base inode struct to be included and that has to be accessed with
>> > something like:
>> >
>> > inode->vfs_inode.i_mtime
>> >
>> > when you could instead do:
>> >
>> > inode->i_mtime
>>
>> This is nice, but it is fundamentally syntactic sugar. Similar things
>> can be done with anonymous structures, *except* that C doesn't allow
>> another structure to be anonymously included; you have to have an
>> entirely new "struct" statement defining all the fields. Welcome to
>> macro hell.
>>
>> > What I would disallow:
>> >
>> > (1) new and delete. There's no way to pass GFP_* flags in.
>>
>> Yes, there is.
>>
>> void * operator new (size_t count, gfp_flags_t flags);
>> void operator delete(void *ptr, ...whatever kfree/vfree/etc need, or a
>> suitable flag);
>>
>> > (2) Constructors and destructors. Nests of implicit code makes the code less
>> > obvious, and the replacement of static initialisation with constructor
>> > calls would make the code size larger.
>>
>> Yes and no. It also makes it *way* easier to convert to and from using
>> dedicated slabs; we already use semi-initialized slabs for some kinds of
>> objects, but it requires new code to make use of.
>>
>> We already *do* use constructors and *especially* destructors for a lot
>> of objects, we just call them out.
>>
>> Note that modern C++ also has the ability to construct and destruct
>> objects in-place, so allocation and construction/destruction aren't
>> necessarily related.
>>
>> There is no reason you can't do static initialization where possible;
>> even constructors can be evaluated at compile time if they are constexpr.
>>
>> Constructors (and destructors, for modules) in conjunction with gcc's
>> init_priority() extension is also a nice replacement for linker hack
>> tables to invoke intializer functions.
>>
>> > (3) Exceptions and RTTI. RTTI would bulk the kernel up too much and
>> > exception handling is limited without it, and since destructors are not
>> > allowed, you still have to manually clean up after an error.
>>
>> Agreed here, especially since on many platforms exception handling
>> relies on DWARF unwind information.
>
> Let me just add a few things about exceptions and RTTI.
> In the darwin kernel, C++ is used for device drivers and both
> exceptions and RTTI is not used there either. They have been using C++
> for kernel drivers since the early 2000s even.
> You can find out more at https://developer.apple.com/documentation/driverkit .
> There even was a GCC option added an option which would also disable
> RTTI and change the ABI to explicitly for the kernel.
> -fapple-kext/-mkernel (the former is for only loadable modules while
> the latter is for kernel too).
>
> Note even in GCC, we disable exceptions and RTTI while building GCC.
> This is specifically due to not wanting to use them and use other
> methods to do that.
> Note GDB on the other hand used to use setjmp/longjmp for their
> exception handling in C and I think they moved over to using C++
> exceptions which simplified things there. But as far as I know the
> Linux kernel does not use a mechanism like that (I know of copy
> from/to user using HW exceptions/error/interrupt handling but that is
> a special case only).
>
>
>>
>> > (4) Operator overloading (except in special cases).
>>
>> See the example of inline patching above. But yes, overloading and
>> *especially* operator overloading should be used only with care; this is
>> pretty much true across the board.
>>
>> > (5) Function overloading (except in special inline cases).
>>
>> I think we might find non-inline cases where it matters, too.
>>
>> > (6) STL (though some type trait bits are needed to replace __builtins that
>> > don't exist in g++).
>>
>> Just like there are parts of the C library which is really about the
>> compiler and not part of the library. <type_traits> is part of that for C++.
>
> There is an idea of a free standing C++ library. newer versions of
> GCC/libstdc++ does support that but IIRC can only be configured at
> compile time of GCC.
> type_traits and a few other headers are included in that. I have not
> looked into it fully though.
There is, and it's quite extensive (and I plan on extending it further
in GCC 15, if I get the chance to). The full list of headers libstdc++
exports for freestanding use is a bit larger than the standard one:
https://gcc.gnu.org/cgit/gcc/tree/libstdc++-v3/include/Makefile.am#n28
(note that some are partially supported.. I lack a full list of which)
Most (actually, nearly all) of the libstdc++ code works for kernel
environments, and it is very mature and well-tested, so it can and
should be used by kernels too. I haven't fully enabled using it in such
a manner yet, but
We could handle the kernel specific configuration via a multilib or so
(so, the multilib list becomes 32, 64, x32, and a new k64 or so on
amd64). Presumably, something like that could be done for libgcc too?
It is not necessarily only configurable at build-time, but the libstdc++
configuration augmented by -ffreestanding and the one generated by a
'proper' freestanding build of libstdc++ differ currently. Maybe they
can be brought together close enough for Linux?
Managarm, which is the kernel I had in mind when working on getting more
freestanding stuff has a dedicated kernel build of GCC, however, so I
didn't test this case much. I'd like to, sooner or later, consolidate
it into the normal managarm system GCC, as a multilib, but I haven't had
time to do so yet.
In any case, I strongly prefer configuring toolchains 'properly'.
> Thanks,
> Andrew Pinski
>
>>
>> > (7) 'class', 'private', 'namespace'.
>> >
>> > (8) 'virtual'. Don't want virtual base classes, though virtual function
>> > tables might make operations tables more efficient.
>>
>> Operations tables *are* virtual classes. virtual base classes make sense
>> in a lot of cases, and we de facto use them already.
>>
>> However, Linux also does conversion of polymorphic objects from one type
>> to another -- that is for example how device nodes are implemented.
>> Using this with C++ polymorphism without RTTI does require some
>> compiler-specific hacks, unfortunately.
>>
>> > Issues:
>> >
>> > (1) Need spaces inserting between strings and symbols.
>>
>> I have to admit I don't really grok this?
>>
>> > (2) Direct assignment of pointers to/from void* isn't allowed by C++, though
>> > g++ grudgingly permits it with -fpermissive. I would imagine that a
>> > compiler option could easily be added to hide the error entirely.
>>
>> Seriously. It should also enforce that it should be a trivial type.
>> Unfortunately it doesn't look like there is a way to create user-defined
>> implicit conversions from one pointer to another (via a helper class),
>> which otherwise would have had some other nice applications.
>>
>> > (3) Need gcc v8+ to statically initialise an object of any struct that's not
>> > really simple (e.g. if it's got an embedded union).
>>
>> Worst case: constexpr constructor.
>>
>> > (4) Symbol length. Really need to extern "C" everything to reduce the size
>> > of the symbols stored in the kernel image. This shouldn't be a problem
>> > if out-of-line function overloading isn't permitted.
>>
>> This really would lose arguably the absolutely biggest advantage of C++:
>> type-safe linkage. This is the one reason why Linus actually tried to
>> use C++ in one single version of the kernel in the early days (0.99.14,
>> if I remember correctly.) At that time, g++ was nowhere near mature
>> enough, and it got dropped right away.
>>
>>
>> > So far, it gets as far as compiling init/main.c to a .o file.
>>
>> ;)
--
Arsen Arsenović
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 381 bytes --]
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 00/45] C++: Convert the kernel to C++
2024-01-09 19:57 ` H. Peter Anvin
2024-01-09 23:29 ` Andrew Pinski
@ 2024-01-09 23:40 ` David Howells
2024-01-10 7:13 ` Alexey Dobriyan
` (2 more replies)
2024-01-10 8:58 ` Jiri Slaby
` (4 subsequent siblings)
6 siblings, 3 replies; 40+ messages in thread
From: David Howells @ 2024-01-09 23:40 UTC (permalink / raw)
To: H. Peter Anvin; +Cc: dhowells, pinskia, Alexey Dobriyan, linux-kernel
H. Peter Anvin <hpa@zytor.com> wrote:
> Hi all, I'm going to stir the hornet's nest and make what has become the
> ultimate sacrilege.
:-)
> Both C and C++ has had a lot of development since 1999, and C++ has in fact,
> in my personal opinion, finally "grown up" to be a better C for the kind of
> embedded programming that an OS kernel epitomizes.
And gcc got rewritten in C++ some time back, so they have a vested interest.
> > (8) 'virtual'. Don't want virtual base classes, though virtual function
> > tables might make operations tables more efficient.
>
> Operations tables *are* virtual classes. virtual base classes make sense in a
> lot of cases, and we de facto use them already.
You end up adding storage for a 'this' pointer for each virtual base class, I
think - and then you may have extra fun if you inherit from two classes that
both inherit the same virtual base class. Abstract base classes that are just
ops tables are probably fine, though.
> > Issues:
> > (1) Need spaces inserting between strings and symbols.
>
> I have to admit I don't really grok this?
You're not allowed to do things like:
asm volatile("btl "__percpu_arg(2)",%1"
but rather have to do:
asm volatile("btl " __percpu_arg(2) ",%1"
as you're now allowed to specify type qualifiers. See
https://en.cppreference.com/w/cpp/language/user_literal
> > (2) Direct assignment of pointers to/from void* isn't allowed by C++, though
> > g++ grudgingly permits it with -fpermissive. I would imagine that a
> > compiler option could easily be added to hide the error entirely.
>
> Seriously. It should also enforce that it should be a trivial
> type. Unfortunately it doesn't look like there is a way to create user-defined
> implicit conversions from one pointer to another (via a helper class), which
> otherwise would have had some other nice applications.
Might require a compiler option to kill the warning. Inserting all the
missing casts would be a pain.
> > (3) Need gcc v8+ to statically initialise an object of any struct that's not
> > really simple (e.g. if it's got an embedded union).
>
> Worst case: constexpr constructor.
There was also a problem with leaving gaps in static array initialisation and
a problem with statically initialising fields out of order (with respect to
the order they're declared in the struct declaration). Possibly these have
been fixed in g++.
> > (4) Symbol length. Really need to extern "C" everything to reduce the size
> > of the symbols stored in the kernel image. This shouldn't be a problem
> > if out-of-line function overloading isn't permitted.
>
> This really would lose arguably the absolutely biggest advantage of C++:
> type-safe linkage. This is the one reason why Linus actually tried to use C++
> in one single version of the kernel in the early days (0.99.14, if I remember
> correctly.) At that time, g++ was nowhere near mature enough, and it got
> dropped right away.
I know. It depends on how much you want to grow your symbol table by. Given
the number of struct pointers we use, it increases it a lot IIRC. Also, you
might want a demangler for stack traces.
David
^ permalink raw reply [flat|nested] 40+ messages in thread* Re: [PATCH 00/45] C++: Convert the kernel to C++
2024-01-09 23:40 ` David Howells
@ 2024-01-10 7:13 ` Alexey Dobriyan
2024-01-12 2:25 ` H. Peter Anvin
2024-01-12 2:40 ` H. Peter Anvin
2 siblings, 0 replies; 40+ messages in thread
From: Alexey Dobriyan @ 2024-01-10 7:13 UTC (permalink / raw)
To: David Howells; +Cc: H. Peter Anvin, pinskia, linux-kernel
On Tue, Jan 09, 2024 at 11:40:45PM +0000, David Howells wrote:
> There was also a problem with leaving gaps in static array initialisation and
> a problem with statically initialising fields out of order (with respect to
> the order they're declared in the struct declaration). Possibly these have
> been fixed in g++.
They weren't :-(
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113124
Right now g++ hard errors some patterns of C99 inititialisation which
clang++ allows (with warnings which can be turned off).
However, clang++ doesn't believe in pointer arithmetic on void*.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 00/45] C++: Convert the kernel to C++
2024-01-09 23:40 ` David Howells
2024-01-10 7:13 ` Alexey Dobriyan
@ 2024-01-12 2:25 ` H. Peter Anvin
2024-01-12 2:40 ` H. Peter Anvin
2 siblings, 0 replies; 40+ messages in thread
From: H. Peter Anvin @ 2024-01-12 2:25 UTC (permalink / raw)
To: David Howells; +Cc: pinskia, Alexey Dobriyan, linux-kernel
On 1/9/24 15:40, David Howells wrote:
>
>> Both C and C++ has had a lot of development since 1999, and C++ has in fact,
>> in my personal opinion, finally "grown up" to be a better C for the kind of
>> embedded programming that an OS kernel epitomizes.
>
> And gcc got rewritten in C++ some time back, so they have a vested interest.
>
Indeed.
>>> (8) 'virtual'. Don't want virtual base classes, though virtual function
>>> tables might make operations tables more efficient.
>>
>> Operations tables *are* virtual classes. virtual base classes make sense in a
>> lot of cases, and we de facto use them already.
>
> You end up adding storage for a 'this' pointer for each virtual base class, I
> think - and then you may have extra fun if you inherit from two classes that
> both inherit the same virtual base class. Abstract base classes that are just
> ops tables are probably fine, though.
My apologies, I meant *abstract* base classes, not *virtual*. To be
honest, I don't think I have ever used virtual base classes in any other
application than games (relating to physical objects), and barely even then.
-hpa
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 00/45] C++: Convert the kernel to C++
2024-01-09 23:40 ` David Howells
2024-01-10 7:13 ` Alexey Dobriyan
2024-01-12 2:25 ` H. Peter Anvin
@ 2024-01-12 2:40 ` H. Peter Anvin
2 siblings, 0 replies; 40+ messages in thread
From: H. Peter Anvin @ 2024-01-12 2:40 UTC (permalink / raw)
To: David Howells; +Cc: pinskia, Alexey Dobriyan, linux-kernel
On 1/9/24 15:40, David Howells wrote:
>
>>> Issues:
>>> (1) Need spaces inserting between strings and symbols.
>>
>> I have to admit I don't really grok this?
>
> You're not allowed to do things like:
>
> asm volatile("btl "__percpu_arg(2)",%1"
>
> but rather have to do:
>
> asm volatile("btl " __percpu_arg(2) ",%1"
>
> as you're now allowed to specify type qualifiers. See
>
> https://en.cppreference.com/w/cpp/language/user_literal
>
Oh, right. This one should be easy enough to automate, though.
-hpa
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 00/45] C++: Convert the kernel to C++
2024-01-09 19:57 ` H. Peter Anvin
2024-01-09 23:29 ` Andrew Pinski
2024-01-09 23:40 ` David Howells
@ 2024-01-10 8:58 ` Jiri Slaby
2024-01-10 13:04 ` Neal Gompa
2024-01-10 15:01 ` Michael de Lang
` (3 subsequent siblings)
6 siblings, 1 reply; 40+ messages in thread
From: Jiri Slaby @ 2024-01-10 8:58 UTC (permalink / raw)
To: H. Peter Anvin, David Howells, linux-kernel, pinskia
Hi,
On 09. 01. 24, 20:57, H. Peter Anvin wrote:
> What really makes me say that is that a lot of things we have recently
> asked for gcc-specific extensions are in fact relatively easy to
> implement in standard C++ and, in many cases, allows for infrastructure
> improvement *without* global code changes (see below.)
>
> C++14 is in my option the "minimum" version that has reasonable
> metaprogramming support has most of it without the type hell of earlier
> versions (C++11 had most of it, but C++14 fills in some key missing
> pieces).
If you mean it, I do too. So I can only express my +1: yes, please.
I don't have much to add as you summarized most of it.
thanks,
--
js
suse labs
^ permalink raw reply [flat|nested] 40+ messages in thread* Re: [PATCH 00/45] C++: Convert the kernel to C++
2024-01-10 8:58 ` Jiri Slaby
@ 2024-01-10 13:04 ` Neal Gompa
2024-01-10 15:52 ` Jason Gunthorpe
2024-01-11 8:06 ` Andreas Herrmann
0 siblings, 2 replies; 40+ messages in thread
From: Neal Gompa @ 2024-01-10 13:04 UTC (permalink / raw)
To: jirislaby
Cc: dhowells, hpa, linux-kernel, pinskia, kent.overstreet, Neal Gompa
Hey all,
I would like to speak in support of this too. It is not uncommon
to see operating systems code written in C++ (notable examples are
Haiku OS, Serenity OS, and Zircon/Fuschia) and I do feel that there
are benefits to C++ for Linux code. Modern C++ (such as C++14 and
newer), offers a lot of nice base language features that can make
some of the kind of stuff that Linux does easier (as H. Peter Anvin
has detailed in his post[1]).
While I personally have some experience in a variety of programming
languages, C++ and Python are my preferred tools, and I would
personally be much more interested in contributing in C++ than in C.
I imagine there are a lot of other folks out there who feel the same,
but just don't feel like they can say it. I'll stick my neck out for
those who won't. ;)
Even though this started out as a "joke"[2], I really would like to
see C++ code permitted in Linux.
Thanks in advance and best regards,
Neal
[1]: https://lore.kernel.org/lkml/3465e0c6-f5b2-4c42-95eb-29361481f805@zytor.com/
[2]: https://lore.kernel.org/lkml/152261521484.30503.16131389653845029164.stgit@warthog.procyon.org.uk/
--
真実はいつも一つ!/ Always, there's only one truth!
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 00/45] C++: Convert the kernel to C++
2024-01-10 13:04 ` Neal Gompa
@ 2024-01-10 15:52 ` Jason Gunthorpe
2024-01-10 16:05 ` H. Peter Anvin
2024-01-10 16:25 ` Neal Gompa
2024-01-11 8:06 ` Andreas Herrmann
1 sibling, 2 replies; 40+ messages in thread
From: Jason Gunthorpe @ 2024-01-10 15:52 UTC (permalink / raw)
To: Neal Gompa
Cc: jirislaby, dhowells, hpa, linux-kernel, pinskia, kent.overstreet
On Wed, Jan 10, 2024 at 08:04:53AM -0500, Neal Gompa wrote:
> Hey all,
>
> I would like to speak in support of this too. It is not uncommon
> to see operating systems code written in C++ (notable examples are
> Haiku OS, Serenity OS, and Zircon/Fuschia) and I do feel that there
> are benefits to C++ for Linux code. Modern C++ (such as C++14 and
> newer), offers a lot of nice base language features that can make
> some of the kind of stuff that Linux does easier (as H. Peter Anvin
> has detailed in his post[1]).
Me too. If we are serious considering Rust I think C++20 deserves a
fair shake as well. Especially since I heard the C++ working group is
apparently looking at future C++ extensions for Rust-esque memory
safety these days.
I personally think the kernel community would have an easier and more
incremental time swallowing C++ than it would Rust, and C++17 is
already mature with fully working stable compilers. In particular I
feel someone familiar with C would have a easier ramp up to some
imagined "kernel C++20 subset" than to Rust.
Further, I feell that having a single base line of "all code compiles
in a C++20 compiler" and localized variations of what idiomatic style
and features different parts use would be ultimately more maintainable
than intermixing C and Rust togther.
I've also got a fair bit of experience with C++17 and I would add to
HPA's note that the modern idiomatic usage of C++17 is *way* different
than older versions. If someone was traumatized by early 2000's or
1990's C++ then it is not entirely fair to carry that to modern
C++17. Especially when combined with a modern environment with
something like clangd to help grok the code. (Though SFINAE is still
an inscrutable terror)
Jason
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 00/45] C++: Convert the kernel to C++
2024-01-10 15:52 ` Jason Gunthorpe
@ 2024-01-10 16:05 ` H. Peter Anvin
2024-01-10 16:25 ` Neal Gompa
1 sibling, 0 replies; 40+ messages in thread
From: H. Peter Anvin @ 2024-01-10 16:05 UTC (permalink / raw)
To: Jason Gunthorpe, Neal Gompa
Cc: jirislaby, dhowells, linux-kernel, pinskia, kent.overstreet
SFINAE giving inscrutable errors is why I'm saying C++20, since "concept" means you can get usable error messages.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 00/45] C++: Convert the kernel to C++
2024-01-10 15:52 ` Jason Gunthorpe
2024-01-10 16:05 ` H. Peter Anvin
@ 2024-01-10 16:25 ` Neal Gompa
2024-01-10 17:57 ` Theodore Ts'o
1 sibling, 1 reply; 40+ messages in thread
From: Neal Gompa @ 2024-01-10 16:25 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: jirislaby, dhowells, hpa, linux-kernel, pinskia, kent.overstreet
On Wed, Jan 10, 2024 at 10:52 AM Jason Gunthorpe <jgg@nvidia.com> wrote:
>
> On Wed, Jan 10, 2024 at 08:04:53AM -0500, Neal Gompa wrote:
> > Hey all,
> >
> > I would like to speak in support of this too. It is not uncommon
> > to see operating systems code written in C++ (notable examples are
> > Haiku OS, Serenity OS, and Zircon/Fuschia) and I do feel that there
> > are benefits to C++ for Linux code. Modern C++ (such as C++14 and
> > newer), offers a lot of nice base language features that can make
> > some of the kind of stuff that Linux does easier (as H. Peter Anvin
> > has detailed in his post[1]).
>
> Me too. If we are serious considering Rust I think C++20 deserves a
> fair shake as well. Especially since I heard the C++ working group is
> apparently looking at future C++ extensions for Rust-esque memory
> safety these days.
>
> I personally think the kernel community would have an easier and more
> incremental time swallowing C++ than it would Rust, and C++17 is
> already mature with fully working stable compilers. In particular I
> feel someone familiar with C would have a easier ramp up to some
> imagined "kernel C++20 subset" than to Rust.
>
> Further, I feell that having a single base line of "all code compiles
> in a C++20 compiler" and localized variations of what idiomatic style
> and features different parts use would be ultimately more maintainable
> than intermixing C and Rust togther.
>
> I've also got a fair bit of experience with C++17 and I would add to
> HPA's note that the modern idiomatic usage of C++17 is *way* different
> than older versions. If someone was traumatized by early 2000's or
> 1990's C++ then it is not entirely fair to carry that to modern
> C++17. Especially when combined with a modern environment with
> something like clangd to help grok the code. (Though SFINAE is still
> an inscrutable terror)
>
For what it's worth, I'm totally in favor of C++20 as well. I've
mostly written C++17 as of late and it is really nice to me, but I'm
genuinely excited about C++20 and newer revisions.
I also think that Linux adopting C++ and intentionally adopting safety
features that exist and are being added to C++ over time would also
further encourage the ecosystem to use them as well as make the Linux
codebase much easier to work with.
--
真実はいつも一つ!/ Always, there's only one truth!
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 00/45] C++: Convert the kernel to C++
2024-01-10 16:25 ` Neal Gompa
@ 2024-01-10 17:57 ` Theodore Ts'o
2024-01-12 2:23 ` H. Peter Anvin
0 siblings, 1 reply; 40+ messages in thread
From: Theodore Ts'o @ 2024-01-10 17:57 UTC (permalink / raw)
To: Neal Gompa
Cc: Jason Gunthorpe, jirislaby, dhowells, hpa, linux-kernel, pinskia,
kent.overstreet
On Wed, Jan 10, 2024 at 11:25:29AM -0500, Neal Gompa wrote:
>
> For what it's worth, I'm totally in favor of C++20 as well. I've
> mostly written C++17 as of late and it is really nice to me, but I'm
> genuinely excited about C++20 and newer revisions.
>
> I also think that Linux adopting C++ and intentionally adopting safety
> features that exist and are being added to C++ over time would also
> further encourage the ecosystem to use them as well as make the Linux
> codebase much easier to work with.
Can someone speak to whether the C++ standards committee and C++
compiler implementations are more or less unreasonable compared to
their C counterparts regarding compilers being able to arbitrary
statement reordering, or other random futzing all in the name of
better benchmarks, but which make life a living nightmware for honest
kernel developers?
- Ted
^ permalink raw reply [flat|nested] 40+ messages in thread* Re: [PATCH 00/45] C++: Convert the kernel to C++
2024-01-10 17:57 ` Theodore Ts'o
@ 2024-01-12 2:23 ` H. Peter Anvin
2024-01-12 2:52 ` Kent Overstreet
0 siblings, 1 reply; 40+ messages in thread
From: H. Peter Anvin @ 2024-01-12 2:23 UTC (permalink / raw)
To: Theodore Ts'o, Neal Gompa
Cc: Jason Gunthorpe, jirislaby, dhowells, linux-kernel, pinskia,
kent.overstreet
On 1/10/24 09:57, Theodore Ts'o wrote:
> On Wed, Jan 10, 2024 at 11:25:29AM -0500, Neal Gompa wrote:
>>
>> For what it's worth, I'm totally in favor of C++20 as well. I've
>> mostly written C++17 as of late and it is really nice to me, but I'm
>> genuinely excited about C++20 and newer revisions.
>>
>> I also think that Linux adopting C++ and intentionally adopting safety
>> features that exist and are being added to C++ over time would also
>> further encourage the ecosystem to use them as well as make the Linux
>> codebase much easier to work with.
>
> Can someone speak to whether the C++ standards committee and C++
> compiler implementations are more or less unreasonable compared to
> their C counterparts regarding compilers being able to arbitrary
> statement reordering, or other random futzing all in the name of
> better benchmarks, but which make life a living nightmware for honest
> kernel developers?
>
I suspect that the gcc and clang developers are more motivated these
days about such issues since they are now using C++ as their own
implementation language.
I had a member of the C++ standards committee reach out to me already,
and I'm going to have a discussion with him next week.
I have a lot more to say in response to all the (excellent!) comments,
but I'm about to leave for a long birthday weekend, so my apologies if I
don't get back to things until next week.
-hpa
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 00/45] C++: Convert the kernel to C++
2024-01-12 2:23 ` H. Peter Anvin
@ 2024-01-12 2:52 ` Kent Overstreet
0 siblings, 0 replies; 40+ messages in thread
From: Kent Overstreet @ 2024-01-12 2:52 UTC (permalink / raw)
To: H. Peter Anvin
Cc: Theodore Ts'o, Neal Gompa, Jason Gunthorpe, jirislaby,
dhowells, linux-kernel, pinskia, Miguel Ojeda
On Thu, Jan 11, 2024 at 06:23:10PM -0800, H. Peter Anvin wrote:
>
>
> On 1/10/24 09:57, Theodore Ts'o wrote:
> > On Wed, Jan 10, 2024 at 11:25:29AM -0500, Neal Gompa wrote:
> > >
> > > For what it's worth, I'm totally in favor of C++20 as well. I've
> > > mostly written C++17 as of late and it is really nice to me, but I'm
> > > genuinely excited about C++20 and newer revisions.
> > >
> > > I also think that Linux adopting C++ and intentionally adopting safety
> > > features that exist and are being added to C++ over time would also
> > > further encourage the ecosystem to use them as well as make the Linux
> > > codebase much easier to work with.
> >
> > Can someone speak to whether the C++ standards committee and C++
> > compiler implementations are more or less unreasonable compared to
> > their C counterparts regarding compilers being able to arbitrary
> > statement reordering, or other random futzing all in the name of
> > better benchmarks, but which make life a living nightmware for honest
> > kernel developers?
> >
>
> I suspect that the gcc and clang developers are more motivated these days
> about such issues since they are now using C++ as their own implementation
> language.
>
> I had a member of the C++ standards committee reach out to me already, and
> I'm going to have a discussion with him next week.
>
> I have a lot more to say in response to all the (excellent!) comments, but
> I'm about to leave for a long birthday weekend, so my apologies if I don't
> get back to things until next week.
Happy birthday, Peter :)
Would this cause any issues for the Rust people, e.g. linking? I'd like
to hear their input.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 00/45] C++: Convert the kernel to C++
2024-01-10 13:04 ` Neal Gompa
2024-01-10 15:52 ` Jason Gunthorpe
@ 2024-01-11 8:06 ` Andreas Herrmann
1 sibling, 0 replies; 40+ messages in thread
From: Andreas Herrmann @ 2024-01-11 8:06 UTC (permalink / raw)
To: Neal Gompa
Cc: jirislaby, dhowells, hpa, linux-kernel, pinskia, kent.overstreet
On Wed, Jan 10, 2024 at 08:04:53AM -0500, Neal Gompa wrote:
> Hey all,
Hi,
> I would like to speak in support of this too. It is not uncommon
> to see operating systems code written in C++ (notable examples are
> Haiku OS, Serenity OS, and Zircon/Fuschia) and I do feel that there
> are benefits to C++ for Linux code. Modern C++ (such as C++14 and
> newer), offers a lot of nice base language features that can make
> some of the kind of stuff that Linux does easier (as H. Peter Anvin
> has detailed in his post[1]).
>
> While I personally have some experience in a variety of programming
> languages, C++ and Python are my preferred tools, and I would
> personally be much more interested in contributing in C++ than in C.
> I imagine there are a lot of other folks out there who feel the same,
> but just don't feel like they can say it. I'll stick my neck out for
> those who won't. ;)
I had some doubts, when I've seen hpa's thread and first I've thought
of it rather as a threat. But now this paragraph totally convinced me.
> Even though this started out as a "joke"[2], I really would like to
> see C++ code permitted in Linux.
Great, let University of Minnesota contribute the code.
> Thanks in advance and best regards,
> Neal
>
> [1]: https://lore.kernel.org/lkml/3465e0c6-f5b2-4c42-95eb-29361481f805@zytor.com/
> [2]: https://lore.kernel.org/lkml/152261521484.30503.16131389653845029164.stgit@warthog.procyon.org.uk/
>
>
> --
> 真実はいつも一つ!/ Always, there's only one truth!
PS: IMO, Rust shouldn't have been allowed into the kernel tree (a gut
feeling). But who am I.
--
Regards,
Andreas
SUSE Software Solutions Germany GmbH
Frankenstrasse 146, 90461 Nürnberg, Germany
GF: Ivo Totev, Andrew McDonald, Werner Knoblich
(HRB 36809, AG Nürnberg)
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 00/45] C++: Convert the kernel to C++
2024-01-09 19:57 ` H. Peter Anvin
` (2 preceding siblings ...)
2024-01-10 8:58 ` Jiri Slaby
@ 2024-01-10 15:01 ` Michael de Lang
[not found] ` <69fe1c0c-b5ec-4031-b719-d9c14742929c@metux.net>
2024-01-11 4:24 ` John Hubbard
` (2 subsequent siblings)
6 siblings, 1 reply; 40+ messages in thread
From: Michael de Lang @ 2024-01-10 15:01 UTC (permalink / raw)
To: H. Peter Anvin, David Howells, linux-kernel, pinskia
Hey,
While I have done no work on the linux kernel, I hope to add to this
discussion anyway. Forgive me if I'm intruding.
The arguments in favour of C++ so far focus on the technical and current
kernel developers aspects. An extra argument in favour of C++ is the
same one that Linus Torvalds recently mentioned in the keynote "Linus
Torvalds in Conversation With Dirk Hohndel" w.r.t. Rust's impact on the
Linux Kernel. Namely, to prevent stagnation for the Kernel as well as
continue to be interesting to new developers.
One of the things holding me back from developping things in the Kernel
is that C is, to put it bluntly, old and not interesting for my resume.
Now there is certainly an argument to be made for "don't fix what ain't
broken", as evidenced by the Kernel being in widespread use. But most of
the interesting programming language progress has happened in C++ and
other languages, unlike C. The aforementioned metaprogramming is one
such example, but things like RAII, smart pointers and things like
gsl::not_null would reduce the changes on kernel bugs, especially memory
safety related bugs that are known to be vulnerable to security issues.
On the other hand, the benefits I mention can also turn into downsides:
if constructs like gsl::not_null are desired, does that mean that there
will be a kernel-specific template library? A KTL instead of STL? That
might be yet another thing that increases the steepness of the kernel
development learning curve.
I also have a note on the following:
> However, Linux also does conversion of polymorphic objects from one
> type to another -- that is for example how device nodes are
> implemented. Using this with C++ polymorphism without RTTI does
> require some compiler-specific hacks, unfortunately.
Although compiler-specific, C++20 has enabled implementing RTTI without
RTTI as well as (partial) reflection. Examples include the JSON library
Glaze as well as my own Dependency Injection framework Ichor. See
https://godbolt.org/z/vaWszr9WG. On top of increasing the binary size,
this then becomes a discussion on what requirements the kernel puts on
compilers, as I'm sure that the kernel needs to be compiled for
architectures which have a less than stellar conformance to the C++
specification. Regardless, this is IMO good food for thought.
Cheers,
Michael de Lang
^ permalink raw reply [flat|nested] 40+ messages in thread* Re: [PATCH 00/45] C++: Convert the kernel to C++
2024-01-09 19:57 ` H. Peter Anvin
` (3 preceding siblings ...)
2024-01-10 15:01 ` Michael de Lang
@ 2024-01-11 4:24 ` John Hubbard
2024-01-11 5:09 ` Dave Airlie
2024-01-11 12:39 ` Chris Down
2024-01-12 2:54 ` H. Peter Anvin
6 siblings, 1 reply; 40+ messages in thread
From: John Hubbard @ 2024-01-11 4:24 UTC (permalink / raw)
To: H. Peter Anvin, David Howells, linux-kernel, pinskia
On 1/9/24 11:57, H. Peter Anvin wrote:
> Hi all, I'm going to stir the hornet's nest and make what has become the ultimate sacrilege.
>
> Andrew Pinski recently made aware of this thread. I realize it was released on April 1, 2018, and either was a joke or might have been taken as one. However, I think there is validity to it, and I'm going to try to motivate my opinion here.
>
In 2018 it may have been taken as a joke, but in 2024 with Rust for Linux
upon us, C++ sounds just plain brilliant. Thank you so much for this proposal.
> Both C and C++ has had a lot of development since 1999, and C++ has in fact, in my personal opinion, finally "grown up" to be a better C for the kind of embedded programming that an OS kernel epitomizes. I'm saying that as the author of a very large number of macro and inline assembly hacks in the kernel.
>
> What really makes me say that is that a lot of things we have recently asked for gcc-specific extensions are in fact relatively easy to implement in standard C++ and, in many cases, allows for infrastructure improvement *without* global code changes (see below.)
>
> C++14 is in my option the "minimum" version that has reasonable metaprogramming support has most of it without the type hell of earlier versions (C++11 had most of it, but C++14 fills in some key missing pieces).
>
> However C++20 is really the main game changer in my opinion; although earlier versions could play a lot of SFINAE hacks they also gave absolutely useless barf as error messages. C++20 adds concepts, which makes it possible to actually get reasonable errors.
I was writing a lot of C++ in the late 1990's and early 2000's, and personally
lived through the template error madness in particular. Verity Stob had a
wonderful riff on it in her 2001 "Double Plus Good?" article [1].
But one thing I do wonder about is the template linker bloat that was
endemic: multiple instantiations of templates were not de-duplicated
by the linkers of the day, and things were just huge. 20 years later,
perhaps it is all better I hope?
>
> We do a lot of metaprogramming in the Linux kernel, implemented with some often truly hideous macro hacks. These are also virtually impossible to debug. Consider the uaccess.h type hacks, some of which I designed and wrote. In C++, the various casts and case statements can be unwound into separate template instances, and with some cleverness can also strictly enforce things like user space vs kernel space pointers as well as already-verified versus unverified user space pointers, not to mention easily handle the case of 32-bit user space types in a 64-bit kernel and make endianness conversion enforceable.
>
This sounds glorious.
> Now, "why not Rust"? First of all, Rust uses a different (often, in my opinion, gratuitously so) syntax, and not only would all the kernel developers need to become intimately familiar to the level of getting the same kind of "feel" as we have for C, but converting C code to Rust isn't something that can be done piecemeal, whereas with some cleanups the existing C code can be compiled as C++.
>
Beyond the syntax, which I'm trying to force myself not to focus on, the
compatibility layers are turning out to be quite extensive. This is just
another way of saying that Rust is a deeply, completely different language.
Whereas C++ is closer to a dialect, as far as building and linking anyway.
> However, I find that I disagree with some of David's conclusions; in fact I believe David is unnecessarily *pessimistic* at least given modern C++.
>
> Note that no one in their sane mind would expect to use all the features of C++. Just like we have "kernel C" (currently a subset of C11 with a relatively large set of allowed compiler-specific extensions) we would have "kernel C++", which I would suggest to be a strictly defined subset of C++20 combined with a similar set of compiler extensions.) I realize C++20 compiler support is still very new for obvious reasons, so at least some of this is forward looking.
There was an effort to address this, and I remember we even tried to use
it: Embedded C++ [2]. This is very simplistic and completely out of date
compared to what is being considered here, but it does show that many
others have had the same reaction: the language is so large that it
wants to be constrained. We actually wrote to Bjarne Stroustrup around
that time and asked about both embedded C++ and coding standards, and
his reaction was, "don't limit the language, just use education instead".
However, in my experience since then, that fails, and you need at least
coding standards. Because people will use *everything* they have available,
unless they can't. :)
Tentatively, coding standards are a better way forward, as opposed to
actually constraining the language (and maybe finding out later that
you wish it was left unconstrained), IMHO.
[1] https://link.springer.com/chapter/10.1007/978-1-4302-0003-1_63
[2] https://en.wikipedia.org/wiki/Embedded_C%2B%2B
thanks,
--
John Hubbard
NVIDIA
^ permalink raw reply [flat|nested] 40+ messages in thread* Re: [PATCH 00/45] C++: Convert the kernel to C++
2024-01-11 4:24 ` John Hubbard
@ 2024-01-11 5:09 ` Dave Airlie
2024-01-11 15:24 ` Eric Curtin
2024-01-11 21:37 ` David Laight
0 siblings, 2 replies; 40+ messages in thread
From: Dave Airlie @ 2024-01-11 5:09 UTC (permalink / raw)
To: John Hubbard; +Cc: H. Peter Anvin, David Howells, linux-kernel, pinskia
> There was an effort to address this, and I remember we even tried to use
> it: Embedded C++ [2]. This is very simplistic and completely out of date
> compared to what is being considered here, but it does show that many
> others have had the same reaction: the language is so large that it
> wants to be constrained. We actually wrote to Bjarne Stroustrup around
> that time and asked about both embedded C++ and coding standards, and
> his reaction was, "don't limit the language, just use education instead".
>
> However, in my experience since then, that fails, and you need at least
> coding standards. Because people will use *everything* they have available,
> unless they can't. :)
You don't just need coding standards, you need a compiler that refuses
to compile that stuff.
If you want C++ to do what Rust could do, then you need the compiler
to stop the stupid before you can even write it, otherwise people will
still write the bad stuff and code review won't catch it all.
Can we get memory safety with C++ now? and also stop people coding C++
like it's 1994?
Kernel C has kinda become a thing without enforcing it, but C wasn't
really stopping anything bad, so having C that isn't quite kernel C
get into corners isn't that bad, but introducing C++ without any
history of kernel C++ is just asking for everyone to do their own
special things and defend their usage of every corner of the language
because they wanted to learn it.
Dave.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 00/45] C++: Convert the kernel to C++
2024-01-11 5:09 ` Dave Airlie
@ 2024-01-11 15:24 ` Eric Curtin
2024-01-11 21:37 ` David Laight
1 sibling, 0 replies; 40+ messages in thread
From: Eric Curtin @ 2024-01-11 15:24 UTC (permalink / raw)
To: airlied; +Cc: dhowells, hpa, jhubbard, linux-kernel, pinskia
> You don't just need coding standards, you need a compiler that refuses
> to compile that stuff.
>
> If you want C++ to do what Rust could do, then you need the compiler
> to stop the stupid before you can even write it, otherwise people will
> still write the bad stuff and code review won't catch it all.
Completely agree with this by the way, if you could turn off features
easily via C++ compiler flags, etc. and make usage of the unwanted
features throw errors. There is a subset of C++ that would have been
useful in the kernel many years ago.
I think the C++ committee is coming around to this way of thinking with
profiles. But it should extend to more than just memory safety features
of course.
Some of the things I like about C++ over Rust:
- C++ interop with C is easier, you can just intertwine C and C++
together out of the box once your code is compiling with C++.
- It's already on the majority of platforms, even legacy ones.
But Rust is nice for other reasons.
But yeah something like this would need to be done like the Rust integration
effort and be an opt-in thing for new code, if it was done.
>
> Can we get memory safety with C++ now? and also stop people coding C++
> like it's 1994?
>
> Kernel C has kinda become a thing without enforcing it, but C wasn't
> really stopping anything bad, so having C that isn't quite kernel C
> get into corners isn't that bad, but introducing C++ without any
> history of kernel C++ is just asking for everyone to do their own
> special things and defend their usage of every corner of the language
> because they wanted to learn it.
>
> Dave.
^ permalink raw reply [flat|nested] 40+ messages in thread
* RE: [PATCH 00/45] C++: Convert the kernel to C++
2024-01-11 5:09 ` Dave Airlie
2024-01-11 15:24 ` Eric Curtin
@ 2024-01-11 21:37 ` David Laight
1 sibling, 0 replies; 40+ messages in thread
From: David Laight @ 2024-01-11 21:37 UTC (permalink / raw)
To: 'Dave Airlie', John Hubbard
Cc: H. Peter Anvin, David Howells, linux-kernel@vger.kernel.org,
pinskia@gmail.com
> Can we get memory safety with C++ now? and also stop people coding C++
> like it's 1994?
What is the run-time cost?
Things like 'smart pointers' are dumb!
CSTRING is an abomination.
I suspect you need to pass array_pointer:length pairs about in
order to get reasonably array bound checking.
So splitting C's pointer-array equivalence.
But you then need to efficiently return them from functions.
That really needs a register pair be used.
Typically two registers are reserved for function returns,
but are only ever used for double-sized integers.
Doing that without compiler support would be hard work.
The other elephant in the room is compilation speed.
David
-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 00/45] C++: Convert the kernel to C++
2024-01-09 19:57 ` H. Peter Anvin
` (4 preceding siblings ...)
2024-01-11 4:24 ` John Hubbard
@ 2024-01-11 12:39 ` Chris Down
2024-01-11 19:40 ` David Laight
2024-01-12 2:54 ` H. Peter Anvin
6 siblings, 1 reply; 40+ messages in thread
From: Chris Down @ 2024-01-11 12:39 UTC (permalink / raw)
To: H. Peter Anvin; +Cc: Peter Zijlstra, David Howells, linux-kernel, pinskia
H. Peter Anvin writes:
>We already *do* use constructors and *especially* destructors for a
>lot of objects, we just call them out.
>
>Note that modern C++ also has the ability to construct and destruct
>objects in-place, so allocation and construction/destruction aren't
>necessarily related.
>
>There is no reason you can't do static initialization where possible;
>even constructors can be evaluated at compile time if they are
>constexpr.
Side note for the constructor and destructor discussion: should we be more
widely marketing the __cleanup() infrastructure that Peter added a year or so
ago? It likely helps a lot with at least some of these cases. In systemd we use
__attribute__((cleanup)) pretty widely and my experience is that it's made the
code a lot easier to both create and consume.
^ permalink raw reply [flat|nested] 40+ messages in thread* RE: [PATCH 00/45] C++: Convert the kernel to C++
2024-01-11 12:39 ` Chris Down
@ 2024-01-11 19:40 ` David Laight
0 siblings, 0 replies; 40+ messages in thread
From: David Laight @ 2024-01-11 19:40 UTC (permalink / raw)
To: 'Chris Down', H. Peter Anvin
Cc: Peter Zijlstra, David Howells, linux-kernel@vger.kernel.org,
pinskia@gmail.com
From: Chris Down
> Sent: 11 January 2024 12:40
>
> H. Peter Anvin writes:
> >We already *do* use constructors and *especially* destructors for a
> >lot of objects, we just call them out.
> >
> >Note that modern C++ also has the ability to construct and destruct
> >objects in-place, so allocation and construction/destruction aren't
> >necessarily related.
> >
> >There is no reason you can't do static initialization where possible;
> >even constructors can be evaluated at compile time if they are
> >constexpr.
But the compiler often doesn't - look at the generated code and marvel
at all the constructors for static items.
Oh yes, and all the destructors that pretty much always get called
in the wrong order leading to SIGSEGV on exit().
C++ programs pretty much have close all files and use _exit().
> Side note for the constructor and destructor discussion: should we be more
> widely marketing the __cleanup() infrastructure that Peter added a year or so
> ago? It likely helps a lot with at least some of these cases. In systemd we use
> __attribute__((cleanup)) pretty widely and my experience is that it's made the
> code a lot easier to both create and consume.
And harder for us 'old fogies' to quickly read for correctness.
IIRC some bugs got committed during some 'simple applications'
because of the real hoops you have to go through to correctly
tidy up a malloc()ed buffer that might be passed on.
I've seen the same issue with some C++ code that was like:
(Pardon my C++ :-)
foo = new();
try {
add_foo_to_list(foo);
} except {
free(foo);
}
The problem is that you have no idea whether the exception was
thrown before or after 'foo' was saved.
Since pretty much everything can 'throw' you really can't tell.
OTOH if add_foo_to_list() returns an error code you can know
(and check) that zero is returned iff the pointer has been saved.
Then there is function and class member overloading.
How may times have you renamed a structure member (etc) and used
the compiler to find out where it is used?
I'm pretty sure that is hard work in C++.
And don't forget the default copy constructor...
David
-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 00/45] C++: Convert the kernel to C++
2024-01-09 19:57 ` H. Peter Anvin
` (5 preceding siblings ...)
2024-01-11 12:39 ` Chris Down
@ 2024-01-12 2:54 ` H. Peter Anvin
2024-01-12 8:52 ` David Howells
6 siblings, 1 reply; 40+ messages in thread
From: H. Peter Anvin @ 2024-01-12 2:54 UTC (permalink / raw)
To: David Howells, linux-kernel, pinskia
One thing I forgot to mention that would be quite useful is careful use
of namespaces. For example, putting init functions in their own
namespace would have not only make it a lot harder to call init
functions from non-init functions by mistake (calling init::func()
explicitly is a highly visible "I really do mean to do this."
However, it also let us do separate init versions of functions like
cpu_feature_enable() that contain optimizations that aren't actually
usable at init time (alternatives have not been applied.) The idea is
*not* to change the code, but rather the compiler will simply prefer
init:: functions from inside other init:: functions (a direct
consequence of how namespaces work.)
-hpa
^ permalink raw reply [flat|nested] 40+ messages in thread* Re: [PATCH 00/45] C++: Convert the kernel to C++
2024-01-12 2:54 ` H. Peter Anvin
@ 2024-01-12 8:52 ` David Howells
2024-01-12 23:53 ` H. Peter Anvin
0 siblings, 1 reply; 40+ messages in thread
From: David Howells @ 2024-01-12 8:52 UTC (permalink / raw)
To: H. Peter Anvin; +Cc: dhowells, linux-kernel, pinskia
H. Peter Anvin <hpa@zytor.com> wrote:
> One thing I forgot to mention that would be quite useful is careful use of
> namespaces.
Just be aware that the use of namespaces would make the kernel image bigger if
symbols are included.
David
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 00/45] C++: Convert the kernel to C++
2024-01-12 8:52 ` David Howells
@ 2024-01-12 23:53 ` H. Peter Anvin
0 siblings, 0 replies; 40+ messages in thread
From: H. Peter Anvin @ 2024-01-12 23:53 UTC (permalink / raw)
To: David Howells; +Cc: dhowells, linux-kernel, pinskia
On January 12, 2024 12:52:03 AM PST, David Howells <dhowells@redhat.com> wrote:
>H. Peter Anvin <hpa@zytor.com> wrote:
>
>> One thing I forgot to mention that would be quite useful is careful use of
>> namespaces.
>
>Just be aware that the use of namespaces would make the kernel image bigger if
>symbols are included.
>
>David
>
If we can leverage data compression it probably would be a lot of space due to the highly repetitive nature of most symbols. To allow for random access that requires a bit of sophistication, but nothing that couldn't be solved.
^ permalink raw reply [flat|nested] 40+ messages in thread