linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH 00/45] C++: Convert the kernel to C++
@ 2018-04-01 21:32 Alexey Dobriyan
  0 siblings, 0 replies; 40+ messages in thread
From: Alexey Dobriyan @ 2018-04-01 21:32 UTC (permalink / raw)
  To: dhowells; +Cc: linux-kernel

> We could, for example, wrap things like userspace pointers, __be numbers,
> ioport addresses and control access to them that way, but I don't know that it
> gains a whole load that sparse doesn't give us.

The problem with sparse is that it is not mandatory part of a build
process. And it spams lot ATM.

^ 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

* Re: [PATCH 00/45] C++: Convert the kernel to C++
  2024-01-12  9:20 ` David Howells
  2024-01-12 21:35   ` Arsen Arsenović
@ 2024-01-12 23:41   ` David Howells
  1 sibling, 0 replies; 40+ messages in thread
From: David Howells @ 2024-01-12 23:41 UTC (permalink / raw)
  To: Arsen =?utf-8?Q?Arsenovi=C4=87?=; +Cc: dhowells, linux-kernel

Arsen Arsenović <arsen@aarsen.me> wrote:

> >> >  (7) 'class', 'private', 'namespace'.
> >>
> >> 'class' does nothing that struct doesn't do, private and namespace serve
> >> simply for encapsulation, so I don't see why banning these is useful.
> >
> > Namespaces would lead to image bloat as they make the symbols bigger.
> > Remember, the symbol list uses up unswappable memory.
> 
> Ah, I was not aware of this restriction of the kernel (my understanding
> was that the symbol table is outside of the kernel image).  That poses a
> problem, yes.  I wonder if a big part of the symbol table (or even the
> entirety of it) could be dropped from the kernel.  I must say, I do not
> know why the kernel has it, so I cannot speak on this issue.

You need at least a partial symbol table for module loading and we also have
the symbol table optionally included for oops message generation.

David


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 00/45] C++: Convert the kernel to C++
       [not found]     ` <69fe1c0c-b5ec-4031-b719-d9c14742929c@metux.net>
@ 2024-01-12 21:58       ` Michael de Lang
  0 siblings, 0 replies; 40+ messages in thread
From: Michael de Lang @ 2024-01-12 21:58 UTC (permalink / raw)
  To: Enrico Weigelt, metux IT consult, H. Peter Anvin, David Howells,
	linux-kernel, pinskia

Thanks for your reply.

>> Namely, to prevent stagnation for the Kernel as well as continue to be 
>> interesting to new developers.
> 
> Which stagnation are you talking about, exactly ?

While I do not know what Linus was exactly thinking about when he 
mentioned stagnation, I assume he was looking at it from the lens of 
long-term maintainers. I'm basing this on the 2021 discussion on lwn: 
https://lwn.net/Articles/870581/. Obviously there are plenty of 
contributors every kernel release and while I don't have any numbers 
there, I don't think # of contributors or # of contributions is an issue.

Still, the idea of C discouraging people to contribute resonates with 
me. That is largely based on subjectivity so feel free to ignore it.

> 
> While I've got a long list of ideas for modernizing the kernel
> (which I'm lacking time to actually work on), I'm unsure whether
> C++ really would be of much benefit. Especially considering that for
> many things there's no way to know / define how things will really
> look like on binary level.

Do you have any examples on what exactly in C++ obfuscates the resulting 
binary? Everything I can think of, also applies to C: anything 
implementation-defined, e.g. struct layout, high-order bit propagation 
for shift operations,

There are things in the STL that are implementation defined, but the 
proposal excludes the STL.

> Personally, the opposite had been one my primary reasons.
> Because it's so simple to understand - in contrast to the usual C++
> monster's i've seen so often in the wild. (I usually try to keep far
> away from C++ projects). 

I have never understood the sentiment that C is supposedly simple. 
Looking at the macros used in the kernel is one obvious big argument 
against using C, as macros can be considered their own 
language-inside-a-language. Another big argument against the sentiment 
is the loose type system, where void* casts are everywhere you want to 
do anything remotely type-generic, losing type information and making it 
harder to grok the original intent.

Creating a compiler for C is 'easier' than creating one for C++ (or Rust 
for that matter), but coding in it as a user requires years of 
experience to avoid a lot of the pitfalls. A simple language would be 
something like golang, with its GC and prescribed coding patterns.

C is a language to be (ab)used like any other, the same goes for C++. 
The kernel has shown that it is possible to create maintainable C, I 
feel confident saying that it is also possible in C++.

 > Note that C++ is a very complex language,
 > and w/ STL it's even much, much more complex.

Note that the proposal here is to use C++ without the STL as well as 
apply some other restrictions.

> Can't judge what you see as interesting, but frankly, I really don't
> have it on my list of interesting things - instead would prefer phasing
> C++ out in favour of many other languages.

I could give you concrete examples of C++ language addition examples, 
but I don't think that adds much to the discussion. Many languages, 
including C++, have additions that C does not have and provide benefits 
such as reduced cognitive load, standardised ways to do things 
preventing NIH syndrome and possibly enthuse more people to contribute 
to the kernel.

The biggest merit of using C++ in the kernel is that in comparison to 
other systems language (Zig, Rust, Swift to name a few) it requires the 
least re-skilling of existing contributors. A close second would be the 
low barrier to integrate various C++ and C codebases. Especially when 
taking into account the architectures that the kernel needs to support 
vs the other languages. Even Rust with its big push towards being a 
replacement isn't there yet today (e.g. PA-RISC).

> 
>> other languages, unlike C. The aforementioned metaprogramming is one 
> 
> Metaprogramming can be very interesting indeed - Oberon once made a 
> really good show case, but I wouldn't dare trying that in kernel space.
> And it's hard to do that w/o causing extra performance penalties.

I believe this is a case of having to try it first before being able to 
decisively say anything about the impact. Counter-examples have been 
mentioned elsewhere in the thread.

> 
>> 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.
> 
> These are exactly the things I would prefer keeping out of kernel space.
> Indeed there're several areas where it could be nice, but there're
> others where we really can't take it.

As you mention yourself, there are places where such constructs would be 
a boon and places where we should not apply them. I have faith in the 
Kernel processes to weed out using things where they should not, as is 
presumably done already for certain C constructs today.

> 
>> 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 
> 
> this seems to be pretty much an assert() - obviously something we really
> cannot have in the kernel.

gsl::not_null prevents constructing a pointer with NULL, ensuring at 
compile-time that it never happens. As such, an assert() would be 
superfluous. It is exactly an example of a C++ construct that has no 
downsides and only upsides.

> 
>> 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.
> 
> Most likely we'd need our own kernel specific library. (we also have one
> instead of libc). Some simple pieces might look similar to STL on the
> front, but it would have to be very different from userland.
> 
> At that point, your previous argument about attracting more people
> who're already used to / like C++ breaks down, because it wouldn't be
> that C++ as usual C++ devs know it (IIRC, STL is integral part of the
> standard), but just the core lang plus some very custom template lib.

It's not that the argument breaks down, it's that it applies to a 
smaller, but still greater than 0, target audience. There are plenty of 
C++ programmers out there that disable the STL on purpose: game 
developers, automotive engineers that I know and so on. You're going to 
be hard-pressed to find concrete numbers, but the fact that the EASTL 
and ETL exist shows the proliferation of non-STL C++ and that the STL 
itself is not an integral part of C++. I recommend you check out ETL 
specifically, I'm sure you'll be amazed at how much functionality it 
has, especially geared for the embedded world.

> 
>> Although compiler-specific, C++20 has enabled implementing RTTI 
>> without RTTI as well as (partial) reflection. 
> 
> You name it: compiler specific.
> 
> Is it even specified how this exactly looks at binary level, and methods
> to control the exact binary data structures ?
> 
> The least thing's need to implement such things is some pointer or tag
> inside each struct/object instance - this would change struct layouts!
> Note that we often use structs to reflect HW specific data structures,
> so we'd need a way to have exact control over this. And then we need to
> be very careful on which instances have RTTI and which ones don't.
> I see debugging nightmares on the horizon ...

I could be convinced that RTTI of any sort is just a bad idea in the 
kernel. It is one of the things that is first to be disabled in embedded 
C++ usage, alongside exceptions. Still, it has its uses even in those 
areas, but that's outside of the scope of this proposal I think.

> 
>> On top of increasing the binary size, 
> 
> That's also a huge problem:
> 
> Templates in general have the strong tendency of producing lots of
> duplicated code. That's what they're designed for: expressing similar
> things (that have to be different on binary level) by the same
> generic source code.
> 
> It might be possible to write them in a way they don't increase binary
> size, but that's not entirely trivial, and so the actual gain of all
> of that becomes questionable again.

Hmm, explicit template instantiations are an 'easy' fix to taming the 
code bloat, but any use of templates is going to mean _some_ extra code 
generation. I do not have any concrete Kernel examples here, but I'm 
sure there are switch/case statements somewhere in there that can be 
optimized away by using templates. For those, the question is: code 
bloat or run-time performance?

> 
>> 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. 
> Indeed. Also think about embedded environments, where folks can't easily
> upgrade toolchains (e.g. due regulative constraints)
> 

This argument also applies against using Rust and is directly opposed to 
modern security practices. Updating to the latest version for 
OS/compilers/libraries etc is pretty much a given since UN R155 and UN 
R156 came into effect. Though those apply only to automotive so far, the 
Cyber Resilience Act is going to force manufacturers of all kinds to 
adhere to better security. There is definitely a whole debate we can 
have just on the impacts of these regulations and what that should mean, 
but I've already written a lot ;)

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-12  9:20 ` David Howells
@ 2024-01-12 21:35   ` Arsen Arsenović
  2024-01-12 23:41   ` David Howells
  1 sibling, 0 replies; 40+ messages in thread
From: Arsen Arsenović @ 2024-01-12 21:35 UTC (permalink / raw)
  To: David Howells; +Cc: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 6687 bytes --]


David Howells <dhowells@redhat.com> writes:

> Arsen Arsenović <arsen@aarsen.me> wrote:
>
>> >  (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.
>>
>> This also disallows the primary benefit of C++ (RAII), though.  A lot of
>> static initialization can be achieved using constexpr and consteval,
>> too.
>
> Okay, let me downgrade that to "I wouldn't allow it at first".  The primary
> need for destructors, I think, is exception handling.

I'm not sure I agree, the amount of 'goto err' constructs in the kernel
seems to indicate otherwise to me.  This feels like the exact same code,
except more error prone.

> And don't get me wrong, I like the idea of exception handling - so
> many bugs come because we mischeck or forget to check the error.

C++ also provides possible alternative avenues for solving such
problems, such as, for instance, an expected type with monadic
operations: https://en.cppreference.com/w/cpp/utility/expected

IIRC, using std::expected in managarm (where we previously used the IMO
far less nice Frigg expected type) is what initially prompted me to
start enabling the use of a lot of libstdc++ in kernel contexts, and
indeed, it is enabled there:
https://gcc.gnu.org/cgit/gcc/tree/libstdc++-v3/include/Makefile.am#n25

>> It is incredibly useful to be able to express resource ownership in
>> terms of automatic storage duration.
>
> Oh, indeed, yes - but you also have to be careful:
>
>  (1) You don't always want to wait till the end of the scope before releasing
>      resources.

One could move a resource out, or call a function akin to the 'reset()'
method of std::unique_ptr.

>  (2) Expressing ownership of something like a lock so that it is automatically
>      undone may require extra memory is currently unnecessary:
>
> 	struct foo {
> 		struct rwsem sem;
> 	};
>
>
> 	myfunc(struct foo *foo)
> 	{
> 		...
> 		struct foo_shared_lock mylock(foo->sem);
> 		...
> 	}
>
>      This looks like a nice way to automatically take and hold a lock, but I
>      don't think it can be done without storing the address of the semaphore
>      in mylock - something that isn't strictly necessary since we can find sem
>      from foo.

The compiler can often get rid of it.  Here's an example:
https://godbolt.org/z/1W7bnYY7a

Simple enough wrapper classes like these combined with a modern
compilers IPA and inlining can really do magic :-)

>  (3) We could implement a magic pointer class that automatically does
>      reference wangling (kref done right) - but we would have to be very
>      careful using it because we want to do the minimum number of atomic ops
>      on its refcount that we can manage, firstly because atomic ops are slow
>      and secondly because the atomic counter must not overflow.

With move semantics, this could be quite effective and general.  The
shared_ptr from the standard library, for instance, won't bump
reference counts if moved.  And temporaries are automatically moved.

You could make the class move-only so that *all* reference incrementing
requires a method call (and hence, is clear and obvious), while still
permitting auto-decrementing and preventing reference leakage.

>> >  (5) Function overloading (except in special inline cases).
>>
>> Generic code, another significant benefit of C++, requires function
>> overloading, though.
>
> I know.  But I was thinking that we might want to disable name mangling if we
> can so as not to bloat the size of the kernel image.  That said, I do like the
> idea of being able to have related functions of the same name with different
> arguments rather than having to name each one differently.

Hmm, I can understand the symbol table size being an issue.

>> >  (7) 'class', 'private', 'namespace'.
>>
>> 'class' does nothing that struct doesn't do, private and namespace serve
>> simply for encapsulation, so I don't see why banning these is useful.
>
> Namespaces would lead to image bloat as they make the symbols bigger.
> Remember, the symbol list uses up unswappable memory.

Ah, I was not aware of this restriction of the kernel (my understanding
was that the symbol table is outside of the kernel image).  That poses a
problem, yes.  I wonder if a big part of the symbol table (or even the
entirety of it) could be dropped from the kernel.  I must say, I do not
know why the kernel has it, so I cannot speak on this issue.

> We use class and private a lot as symbols already, so to get my stuff to
> compile I had to #define them.  Granted there's nothing intrinsically
> different about classes and we could rename every instance of the symbol in
> the kernel first.

I see.  That is quite understandable then, especially if temporary.

> When it comes to 'private', actually, I might withdraw my objection to it: it
> would help delineate internal fields - but we would then have to change
> out-of-line functions that use it to be members of the class - again
> potentially increasing the size of the symbol table.

This is what I like about it too.

>> >  (8) 'virtual'.  Don't want virtual base classes, though virtual function
>> >      tables might make operations tables more efficient.
>>
>> Virtual base classes are seldom useful, but I see no reason to
>> blanket-ban them (and I suspect you'll never notice that they're not
>> banned).
>
> You can end up increasing the size of your structure as you may need multiple
> virtual method pointer tables - and we have to be very careful about that as
> some structures (dentry, inode and page for example) we have a *lot* of
> instances of in a running kernel.

I retract what I said about virtual classes - I had, indeed, forgotten
about that issue (but, again, I doubt anyone will miss them ;-) ).

>> >  (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.
>>
>> This should never be useful.
>
> It's not a matter of whether it should be useful - we do this an awful lot and
> every case of assigning to/from a void pointer would require some sort of
> cast.

I see.  That could pose significant trouble.

Ideally, nearly all uses of void* could be lost sooner or later, as C++
has a more flexible (despite being stricter) type system.

Have a lovely day!

> David


--
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++
  2018-04-01 20:40 David Howells
                   ` (4 preceding siblings ...)
  2024-01-11 23:09 ` Arsen Arsenović
@ 2024-01-12  9:20 ` David Howells
  2024-01-12 21:35   ` Arsen Arsenović
  2024-01-12 23:41   ` David Howells
  5 siblings, 2 replies; 40+ messages in thread
From: David Howells @ 2024-01-12  9:20 UTC (permalink / raw)
  To: Arsen =?utf-8?Q?Arsenovi=C4=87?=; +Cc: dhowells, linux-kernel

Arsen Arsenović <arsen@aarsen.me> wrote:

> >  (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.
> 
> This also disallows the primary benefit of C++ (RAII), though.  A lot of
> static initialization can be achieved using constexpr and consteval,
> too.

Okay, let me downgrade that to "I wouldn't allow it at first".  The primary
need for destructors, I think, is exception handling.  And don't get me wrong,
I like the idea of exception handling - so many bugs come because we mischeck
or forget to check the error.

> It is incredibly useful to be able to express resource ownership in
> terms of automatic storage duration.

Oh, indeed, yes - but you also have to be careful:

 (1) You don't always want to wait till the end of the scope before releasing
     resources.

 (2) Expressing ownership of something like a lock so that it is automatically
     undone may require extra memory is currently unnecessary:

	struct foo {
		struct rwsem sem;
	};


	myfunc(struct foo *foo)
	{
		...
		struct foo_shared_lock mylock(foo->sem);
		...
	}

     This looks like a nice way to automatically take and hold a lock, but I
     don't think it can be done without storing the address of the semaphore
     in mylock - something that isn't strictly necessary since we can find sem
     from foo.

 (3) We could implement a magic pointer class that automatically does
     reference wangling (kref done right) - but we would have to be very
     careful using it because we want to do the minimum number of atomic ops
     on its refcount that we can manage, firstly because atomic ops are slow
     and secondly because the atomic counter must not overflow.

> >  (5) Function overloading (except in special inline cases).
> 
> Generic code, another significant benefit of C++, requires function
> overloading, though.

I know.  But I was thinking that we might want to disable name mangling if we
can so as not to bloat the size of the kernel image.  That said, I do like the
idea of being able to have related functions of the same name with different
arguments rather than having to name each one differently.

> >  (7) 'class', 'private', 'namespace'.
> 
> 'class' does nothing that struct doesn't do, private and namespace serve
> simply for encapsulation, so I don't see why banning these is useful.

Namespaces would lead to image bloat as they make the symbols bigger.
Remember, the symbol list uses up unswappable memory.

We use class and private a lot as symbols already, so to get my stuff to
compile I had to #define them.  Granted there's nothing intrinsically
different about classes and we could rename every instance of the symbol in
the kernel first.

When it comes to 'private', actually, I might withdraw my objection to it: it
would help delineate internal fields - but we would then have to change
out-of-line functions that use it to be members of the class - again
potentially increasing the size of the symbol table.

> >  (8) 'virtual'.  Don't want virtual base classes, though virtual function
> >      tables might make operations tables more efficient.
> 
> Virtual base classes are seldom useful, but I see no reason to
> blanket-ban them (and I suspect you'll never notice that they're not
> banned).

You can end up increasing the size of your structure as you may need multiple
virtual method pointer tables - and we have to be very careful about that as
some structures (dentry, inode and page for example) we have a *lot* of
instances of in a running kernel.

> >  (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.
> 
> This should never be useful.

It's not a matter of whether it should be useful - we do this an awful lot and
every case of assigning to/from a void pointer would require some sort of
cast.

David


^ 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
                     ` (6 preceding siblings ...)
  2024-01-12  2:54   ` H. Peter Anvin
@ 2024-01-12  8:52   ` David Howells
  2024-01-12 23:53     ` H. Peter Anvin
  7 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-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
  7 siblings, 0 replies; 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: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-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 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-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++
  2018-04-01 20:40 David Howells
                   ` (3 preceding siblings ...)
  2024-01-09 23:40 ` David Howells
@ 2024-01-11 23:09 ` Arsen Arsenović
  2024-01-12  9:20 ` David Howells
  5 siblings, 0 replies; 40+ messages in thread
From: Arsen Arsenović @ 2024-01-11 23:09 UTC (permalink / raw)
  To: David Howells; +Cc: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 10762 bytes --]


David Howells <dhowells@redhat.com> writes:

> 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.
>
>  (2) Inline overloaded functions, which makes implementation of things like
>      static_branch_likely() cleaner.
>
>  (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
>
> What I would disallow:
>
>  (1) new and delete.  There's no way to pass GFP_* flags in.
>
>  (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.

This also disallows the primary benefit of C++ (RAII), though.  A lot of
static initialization can be achieved using constexpr and consteval,
too.

It is incredibly useful to be able to express resource ownership in
terms of automatic storage duration.

>  (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.
>
>  (4) Operator overloading (except in special cases).
>
>  (5) Function overloading (except in special inline cases).

Generic code, another significant benefit of C++, requires function
overloading, though.

>  (6) STL (though some type trait bits are needed to replace __builtins that
>      don't exist in g++).

A lot of useful stuff that works fine in kernel contexts is in the STL,
though.  For instance, nearly everything from the iterators, ranges,
utility, memory, and algorithms library works fine.  Naturally,
concepts, type traits, and language support libraries are also fine.

>  (7) 'class', 'private', 'namespace'.

'class' does nothing that struct doesn't do, private and namespace serve
simply for encapsulation, so I don't see why banning these is useful.

>  (8) 'virtual'.  Don't want virtual base classes, though virtual function
>      tables might make operations tables more efficient.

Virtual base classes are seldom useful, but I see no reason to
blanket-ban them (and I suspect you'll never notice that they're not
banned).

> Issues:
>
>  (1) Need spaces inserting between strings and symbols.
>
>  (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.

This should never be useful.

Have a lovely night!

>  (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).
>
>  (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.
>
> So far, it gets as far as compiling init/main.c to a .o file.
>
> Seriously, though...
>
> Apart from the cleaner inline functions allowed by templating, I'm not sure
> there's a lot of the C++ language that we would want to use in the kernel
> unless we want to go for more advanced classes implementing interesting types.
>
> We could, for example, wrap things like userspace pointers, __be numbers,
> ioport addresses and control access to them that way, but I don't know that it
> gains a whole load that sparse doesn't give us.
>
> And finally, doing this did find a few minor things that can be fixed.
>
> David
> ---
> David Howells (45):
>       Use UINT_MAX, not -1, to represent an invalid UID, GID or project ID
>       Fix exception_enter() return value
>       Fix loop var in be32_to_cpu_array() and cpu_to_be32_array()
>       Fix use of ACPI_COMPANION_SET()
>       C++: Set compilation as C++ for .c files
>       C++: Do some basic C++ type definition
>       C++: Define a header with some C++ type traits for type checking
>       C++: Implement abs() as an inline template function
>       C++: x86: Fix the x86 syscall table production for C++
>       C++: x86: Turn xchg(), xadd() & co. into inline template functions
>       C++: x86: Turn cmpxchg() & co. into inline template functions
>       C++: x86: Turn cmpxchg_double() & co. into inline template functions
>       C++: x86: Turn cmpxchg64() & co. into inline template functions
>       C++: x86: Turn put_user(), get_user() & co. into inline template functions
>       C++: Need space between string and symbol
>       C++: Disable VERIFY_OCTAL_PERMISSIONS() for the moment
>       C++: Turn READ_ONCE(), WRITE_ONCE() & co. into inline template functions
>       C++: Turn RCU accessors into inline template functions
>       C++: Turn ktime_add/sub_ns() into inline template functions
>       C++: init/main: Constify pointers
>       C++: Set the type of atomic64_t to s64
>       C++: Define apic_intr_mode after the enum definition, not before
>       C++: Don't do "extern asmlinkage"
>       C++: Fix BUILD_BUG_ON_ZERO()
>       C++: Fix void variables
>       C++: Can't have variable/member names the same as typedef names
>       C++: Disable __same_type() for the moment
>       C++: Move ctx_state enum out of struct context_tracking
>       C++: Move the print_line_t enum before first use
>       C++: Include linux/hrtimer.h from linux/timer.h
>       C++: Avoid using 'compl' and 'and' as names
>       C++: __to_fd() needs to reduce the size of v for struct fd::flags
>       C++: Move irqchip_irq_state enum
>       C++: Fix up use of LIST_POISON*
>       C++: Fix static_branch_likely/unlikely()
>       C++: Fix kernfs_type() int->enum
>       C++: Fix page_zonenum() int->enum
>       C++: mutex_trylock_recursive_enum() int->enum
>       C++: Fix spinlock initialisation
>       C++: Fix sema_init()
>       C++: Cast in bitops
>       C++: Hide C++ keywords
>       C++: Don't need to declare struct pgd_t after typedef
>       C++: Can't declare unsized-array in struct cgroup
>       C++: Move initcall_level_names[] to __initdata section
>
>
>  Makefile                               |   13 -
>  arch/x86/Makefile                      |    2
>  arch/x86/entry/syscalls/Makefile       |    8
>  arch/x86/entry/syscalls/syscallhdr.pl  |   73 ++++
>  arch/x86/entry/syscalls/syscalltbl.pl  |   95 +++++
>  arch/x86/include/asm/alternative.h     |   10 -
>  arch/x86/include/asm/apic.h            |    2
>  arch/x86/include/asm/arch_hweight.h    |    4
>  arch/x86/include/asm/atomic.h          |    2
>  arch/x86/include/asm/atomic64_64.h     |   12 -
>  arch/x86/include/asm/cmpxchg.h         |  430 +++++++++++-----------
>  arch/x86/include/asm/cmpxchg_64.h      |   28 +
>  arch/x86/include/asm/hw_irq.h          |   38 +-
>  arch/x86/include/asm/percpu.h          |   94 ++---
>  arch/x86/include/asm/perf_event.h      |    2
>  arch/x86/include/asm/processor.h       |    2
>  arch/x86/include/asm/special_insns.h   |    2
>  arch/x86/include/asm/tlbflush.h        |    1
>  arch/x86/include/asm/uaccess.h         |  630 +++++++++++++++++---------------
>  arch/x86/include/asm/uaccess_64.h      |   66 +--
>  arch/x86/kernel/asm-offsets_32.c       |    1
>  arch/x86/kernel/asm-offsets_64.c       |    1
>  arch/x86/purgatory/Makefile            |    2
>  include/asm-generic/bitops/le.h        |   32 +-
>  include/asm-generic/sections.h         |    2
>  include/linux/acpi.h                   |    2
>  include/linux/backing-dev-defs.h       |    4
>  include/linux/blkdev.h                 |   86 ++--
>  include/linux/build_bug.h              |    5
>  include/linux/byteorder/generic.h      |    4
>  include/linux/cgroup-defs.h            |    2
>  include/linux/compat.h                 |    2
>  include/linux/compiler-c++.h           |   54 +++
>  include/linux/compiler-gcc.h           |    5
>  include/linux/compiler.h               |   93 +----
>  include/linux/compiler_types.h         |    2
>  include/linux/context_tracking.h       |    4
>  include/linux/context_tracking_state.h |   14 -
>  include/linux/cpumask.h                |    4
>  include/linux/crypto.h                 |    4
>  include/linux/elevator.h               |   82 ++--
>  include/linux/file.h                   |    2
>  include/linux/interrupt.h              |   10 -
>  include/linux/irq.h                    |    1
>  include/linux/irqflags.h               |   10 +
>  include/linux/jump_label.h             |   41 +-
>  include/linux/kernel.h                 |   35 --
>  include/linux/kernfs.h                 |    2
>  include/linux/ktime.h                  |   12 +
>  include/linux/list.h                   |    8
>  include/linux/list_bl.h                |    4
>  include/linux/list_nulls.h             |    2
>  include/linux/lockdep.h                |    2
>  include/linux/mm.h                     |    2
>  include/linux/mutex.h                  |    5
>  include/linux/page-flags.h             |    3
>  include/linux/poison.h                 |    6
>  include/linux/printk.h                 |    4
>  include/linux/projid.h                 |    2
>  include/linux/rculist.h                |    4
>  include/linux/rculist_bl.h             |    2
>  include/linux/rcupdate.h               |  124 ++++--
>  include/linux/sched/task.h             |    2
>  include/linux/semaphore.h              |    5
>  include/linux/spinlock.h               |    2
>  include/linux/spinlock_types.h         |    4
>  include/linux/start_kernel.h           |    2
>  include/linux/stddef.h                 |   12 -
>  include/linux/sysctl.h                 |    6
>  include/linux/timer.h                  |    1
>  include/linux/trace_events.h           |   16 -
>  include/linux/types.h                  |   16 +
>  include/linux/uidgid.h                 |    4
>  init/main.c                            |    4
>  scripts/checksyscalls.sh               |    2
>  tools/power/cpupower/Makefile          |    1
>  tools/virtio/Makefile                  |    2
>  77 files changed, 1269 insertions(+), 1010 deletions(-)
>  create mode 100644 arch/x86/entry/syscalls/syscallhdr.pl
>  create mode 100644 arch/x86/entry/syscalls/syscalltbl.pl
>  create mode 100644 include/linux/compiler-c++.h


--
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-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, pinskia

> 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 23:29   ` Andrew Pinski
@ 2024-01-11 21:01     ` Arsen Arsenović
  0 siblings, 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-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, pinskia

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-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-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
  2024-01-12  8:52   ` David Howells
  7 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 10:58 ` Neal Gompa
  2024-01-11 11:12   ` Alexey Dobriyan
@ 2024-01-11 12:12   ` Andreas Herrmann
  1 sibling, 0 replies; 40+ messages in thread
From: Andreas Herrmann @ 2024-01-11 12:12 UTC (permalink / raw)
  To: Neal Gompa
  Cc: Alexey Dobriyan, H. Peter Anvin, Jason Gunthorpe, jirislaby,
	dhowells, linux-kernel, pinskia, kent.overstreet

On Thu, Jan 11, 2024 at 05:58:51AM -0500, Neal Gompa wrote:
> On Thu, Jan 11, 2024 at 5:56 AM Alexey Dobriyan <adobriyan@gmail.com> wrote:
> >
> > > SFINAE giving inscrutable errors is why I'm saying C++20,
> > > since "concept" means you can get usable error messages.
> >
> > I'd say concepts are irrelevant for the kernel where standard library is
> > tightly controlled by the same people who write rest of the kernel and
> > no external users.
> >
> > static_assert() is all you need.
> 
> We have external users all the time, though. People who write external
> modules or new modules would fall in that classification. Why should
> it be harder for them?

I guess, I misunderstand something.

But WRT to the term 'external module' I have some comment.

My personal opinion is somewhat reflected in following article:

https://www.linuxfoundation.org/blog/blog/the-people-who-support-linux-snowden-revelations-spur-engineers-open-source-donation
(The People Who Support Linux: Snowden Revelations Spur Engineer's
Open Source Donation) [The Linux Foundation | 18 December 2013]

  „“The public needs fully open source OSes, where experts can review
  the whole code, to minimize the risk of hidden backdoors,” said
  Kies.“

Thinking more about this.

What exactly was the reason to allow Rust in the kernel?

What exactly is the reason to allow C++ in the kernel?

Besides, I think in general that complexity can be destructive -- even
in a world without bad actors.

> -- 
> 真実はいつも一つ!/ 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-11 10:58 ` Neal Gompa
@ 2024-01-11 11:12   ` Alexey Dobriyan
  2024-01-11 12:12   ` Andreas Herrmann
  1 sibling, 0 replies; 40+ messages in thread
From: Alexey Dobriyan @ 2024-01-11 11:12 UTC (permalink / raw)
  To: Neal Gompa
  Cc: H. Peter Anvin, Jason Gunthorpe, jirislaby, dhowells,
	linux-kernel, pinskia, kent.overstreet

On Thu, Jan 11, 2024 at 05:58:51AM -0500, Neal Gompa wrote:
> On Thu, Jan 11, 2024 at 5:56 AM Alexey Dobriyan <adobriyan@gmail.com> wrote:
> >
> > > SFINAE giving inscrutable errors is why I'm saying C++20,
> > > since "concept" means you can get usable error messages.
> >
> > I'd say concepts are irrelevant for the kernel where standard library is
> > tightly controlled by the same people who write rest of the kernel and
> > no external users.
> >
> > static_assert() is all you need.
> 
> We have external users all the time, though. People who write external
> modules or new modules would fall in that classification. Why should
> it be harder for them?

static_assert gives filename:line which clearly points to the source of
an error.

Concepts are SFINAE replacement but if there is little SFINAE there will
be little concepts too.

Another quite silly thing with concepts (and with noexcept propagation)
is that programmer has to write an implementation then chop control flow
and put everything else into the requires. And then to keep both in sync.

This is an example from cppreference:

	template<typename T>
		requires Addable<T>
	T
	add(T a, T b)
	{
		return a + b;
	}

Guess what Addable<> is?

They are kind of nice for simple things:

	template<typename It>
	concept MinimalIterator = requires(It it) { ++it; *it; it++; };

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 00/45] C++: Convert the kernel to C++
  2024-01-11 10:56 Alexey Dobriyan
@ 2024-01-11 10:58 ` Neal Gompa
  2024-01-11 11:12   ` Alexey Dobriyan
  2024-01-11 12:12   ` Andreas Herrmann
  0 siblings, 2 replies; 40+ messages in thread
From: Neal Gompa @ 2024-01-11 10:58 UTC (permalink / raw)
  To: Alexey Dobriyan
  Cc: H. Peter Anvin, Jason Gunthorpe, jirislaby, dhowells,
	linux-kernel, pinskia, kent.overstreet

On Thu, Jan 11, 2024 at 5:56 AM Alexey Dobriyan <adobriyan@gmail.com> wrote:
>
> > SFINAE giving inscrutable errors is why I'm saying C++20,
> > since "concept" means you can get usable error messages.
>
> I'd say concepts are irrelevant for the kernel where standard library is
> tightly controlled by the same people who write rest of the kernel and
> no external users.
>
> static_assert() is all you need.

We have external users all the time, though. People who write external
modules or new modules would fall in that classification. Why should
it be harder for them?


-- 
真実はいつも一つ!/ 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-11 10:56 Alexey Dobriyan
  2024-01-11 10:58 ` Neal Gompa
  0 siblings, 1 reply; 40+ messages in thread
From: Alexey Dobriyan @ 2024-01-11 10:56 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Jason Gunthorpe, Neal Gompa, 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.

I'd say concepts are irrelevant for the kernel where standard library is
tightly controlled by the same people who write rest of the kernel and
no external users.

static_assert() is all you need.

^ 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-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-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
                     ` (2 subsequent siblings)
  7 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-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 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 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 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-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
                     ` (3 subsequent siblings)
  7 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-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-09 19:57 ` H. Peter Anvin
  2024-01-09 23:29   ` Andrew Pinski
  2024-01-10  0:29   ` David Howells
@ 2024-01-10  8:58   ` Jiri Slaby
  2024-01-10 13:04     ` Neal Gompa
  2024-01-10 15:01   ` Michael de Lang
                     ` (4 subsequent siblings)
  7 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-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 19:57 ` H. Peter Anvin
  2024-01-09 23:29   ` Andrew Pinski
@ 2024-01-10  0:29   ` David Howells
  2024-01-10  8:58   ` Jiri Slaby
                     ` (5 subsequent siblings)
  7 siblings, 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++
  2018-04-01 20:40 David Howells
                   ` (2 preceding siblings ...)
  2024-01-09 19:57 ` H. Peter Anvin
@ 2024-01-09 23:40 ` David Howells
  2024-01-10  7:13   ` Alexey Dobriyan
                     ` (2 more replies)
  2024-01-11 23:09 ` Arsen Arsenović
  2024-01-12  9:20 ` David Howells
  5 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 19:57 ` H. Peter Anvin
@ 2024-01-09 23:29   ` Andrew Pinski
  2024-01-11 21:01     ` Arsen Arsenović
  2024-01-10  0:29   ` David Howells
                     ` (6 subsequent siblings)
  7 siblings, 1 reply; 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++
  2018-04-01 20:40 David Howells
  2018-04-01 22:20 ` Randy Dunlap
  2018-04-02  9:28 ` Vegard Nossum
@ 2024-01-09 19:57 ` H. Peter Anvin
  2024-01-09 23:29   ` Andrew Pinski
                     ` (7 more replies)
  2024-01-09 23:40 ` David Howells
                   ` (2 subsequent siblings)
  5 siblings, 8 replies; 40+ messages in thread
From: H. Peter Anvin @ 2024-01-09 19:57 UTC (permalink / raw)
  To: David Howells, linux-kernel, pinskia

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.

>   (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++.

>   (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++
  2018-04-01 20:40 David Howells
  2018-04-01 22:20 ` Randy Dunlap
@ 2018-04-02  9:28 ` Vegard Nossum
  2024-01-09 19:57 ` H. Peter Anvin
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 40+ messages in thread
From: Vegard Nossum @ 2018-04-02  9:28 UTC (permalink / raw)
  To: David Howells; +Cc: LKML

On 1 April 2018 at 22:40, David Howells <dhowells@redhat.com> wrote:
>
> Here are a series of patches to start converting the kernel to C++.  It
> requires g++ v8.

Nice!

I tried something similar a few years ago, but I don't think it was
nearly as neat. I did get RTTI and exceptions to work (using libcxxrt
+ libunwind), though. Having noticed that a lot of really trivial
kernel bugs are due to control flow issues (e.g. when somebody adds a
possibly-failing step to a function but forget to add a new label to
clean it up) I really wanted to see how/whether exceptions and RAII
could help in that space.

Just in case you want to compare notes, I've pushed my branch to:

https://github.com/vegard/linux-2.6/tree/cxx

I also started a little bit of work on converting a driver to use
RAII, and quickly ran into a few problems: C++ destructors don't take
arguments, which means that some objects would have to carry extra
state around because some of the information needed to destroy an
object resides with somebody else. This means that you would have to
do more refactoring work to avoid needing this in the first place,
i.e. mapping creation/destructing of various C-style structs to C++ is
_not_ straightforward.

Take dma_alloc_coherent() for example. It pairs up with
dma_free_coherent() and that one needs to know the device and buffer
size that you passed too:

void *dma_alloc_coherent(struct device *, size_t, dma_addr_t *, gfp_t);
void dma_free_coherent(struct device *, size_t, void *, dma_addr_t);

This means that if you have 1 device using 2 buffers of the same size
and the size is stored only by the device struct, then you must always
do the destruction from the device struct, since the individual
buffers don't know their size (unless you move the member there; but
it feels like a waste of memory if you could do it just fine in C).
Maybe there's a "proper" way to do it that I didn't see, but problems
like this turned me off the whole approach a little.

Another real bummer is the size and complexity of the RTTI and
unwinding support code. First of all, unwinding requires parsing and
executing DWARF code on the fly, and that just makes everything very
slow. Not to mention that it needs to be threading-aware and does a
lot of memory allocations. IIRC handling out-of-memory conditions was
extremely ugly (not that the kernel is perfect in this respect to
start with) and involved the use of "reserve buffers". I didn't like
it at all.

Also, for reference, I found a few other projects doing similar things
in the past:

https://github.com/veltzer/kcpp
http://www.drdobbs.com/cpp/c-exceptions-the-linux-kernel/229100146
https://pograph.wordpress.com/2009/04/05/porting-cpp-code-to-linux-kernel/
https://www.threatstack.com/blog/c-in-the-linux-kernel/

There's probably more, I seem to remember at least 1 commercial
product using C++ for their out-of-tree module (albeit without
RTTI/exceptions), but I can't find it right now.


Vegard

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 00/45] C++: Convert the kernel to C++
  2018-04-01 20:40 David Howells
@ 2018-04-01 22:20 ` Randy Dunlap
  2018-04-02  9:28 ` Vegard Nossum
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 40+ messages in thread
From: Randy Dunlap @ 2018-04-01 22:20 UTC (permalink / raw)
  To: David Howells, linux-kernel

On 04/01/2018 01:40 PM, David Howells wrote:
> 
> Here are a series of patches to start converting the kernel to C++.  It
> requires g++ v8.
> 
...
> 
> What I would disallow:
> 
>  (1) new and delete.  There's no way to pass GFP_* flags in.
> 
>  (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.
> 
>  (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.
> 
>  (4) Operator overloading (except in special cases).
> 
>  (5) Function overloading (except in special inline cases).
> 
>  (6) STL (though some type trait bits are needed to replace __builtins that
>      don't exist in g++).
> 
>  (7) 'class', 'private', 'namespace'.

Please fix https://bugzilla.kernel.org/show_bug.cgi?id=191051
while you are at it.  :)


>  (8) 'virtual'.  Don't want virtual base classes, though virtual function
>      tables might make operations tables more efficient.


ta.
-- 
~Randy

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH 00/45] C++: Convert the kernel to C++
@ 2018-04-01 20:40 David Howells
  2018-04-01 22:20 ` Randy Dunlap
                   ` (5 more replies)
  0 siblings, 6 replies; 40+ messages in thread
From: David Howells @ 2018-04-01 20:40 UTC (permalink / raw)
  To: linux-kernel


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.

 (2) Inline overloaded functions, which makes implementation of things like
     static_branch_likely() cleaner.

 (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

What I would disallow:

 (1) new and delete.  There's no way to pass GFP_* flags in.

 (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.

 (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.

 (4) Operator overloading (except in special cases).

 (5) Function overloading (except in special inline cases).

 (6) STL (though some type trait bits are needed to replace __builtins that
     don't exist in g++).

 (7) 'class', 'private', 'namespace'.

 (8) 'virtual'.  Don't want virtual base classes, though virtual function
     tables might make operations tables more efficient.

Issues:

 (1) Need spaces inserting between strings and symbols.

 (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.

 (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).

 (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.

So far, it gets as far as compiling init/main.c to a .o file.

Seriously, though...

Apart from the cleaner inline functions allowed by templating, I'm not sure
there's a lot of the C++ language that we would want to use in the kernel
unless we want to go for more advanced classes implementing interesting types.

We could, for example, wrap things like userspace pointers, __be numbers,
ioport addresses and control access to them that way, but I don't know that it
gains a whole load that sparse doesn't give us.

And finally, doing this did find a few minor things that can be fixed.

David
---
David Howells (45):
      Use UINT_MAX, not -1, to represent an invalid UID, GID or project ID
      Fix exception_enter() return value
      Fix loop var in be32_to_cpu_array() and cpu_to_be32_array()
      Fix use of ACPI_COMPANION_SET()
      C++: Set compilation as C++ for .c files
      C++: Do some basic C++ type definition
      C++: Define a header with some C++ type traits for type checking
      C++: Implement abs() as an inline template function
      C++: x86: Fix the x86 syscall table production for C++
      C++: x86: Turn xchg(), xadd() & co. into inline template functions
      C++: x86: Turn cmpxchg() & co. into inline template functions
      C++: x86: Turn cmpxchg_double() & co. into inline template functions
      C++: x86: Turn cmpxchg64() & co. into inline template functions
      C++: x86: Turn put_user(), get_user() & co. into inline template functions
      C++: Need space between string and symbol
      C++: Disable VERIFY_OCTAL_PERMISSIONS() for the moment
      C++: Turn READ_ONCE(), WRITE_ONCE() & co. into inline template functions
      C++: Turn RCU accessors into inline template functions
      C++: Turn ktime_add/sub_ns() into inline template functions
      C++: init/main: Constify pointers
      C++: Set the type of atomic64_t to s64
      C++: Define apic_intr_mode after the enum definition, not before
      C++: Don't do "extern asmlinkage"
      C++: Fix BUILD_BUG_ON_ZERO()
      C++: Fix void variables
      C++: Can't have variable/member names the same as typedef names
      C++: Disable __same_type() for the moment
      C++: Move ctx_state enum out of struct context_tracking
      C++: Move the print_line_t enum before first use
      C++: Include linux/hrtimer.h from linux/timer.h
      C++: Avoid using 'compl' and 'and' as names
      C++: __to_fd() needs to reduce the size of v for struct fd::flags
      C++: Move irqchip_irq_state enum
      C++: Fix up use of LIST_POISON*
      C++: Fix static_branch_likely/unlikely()
      C++: Fix kernfs_type() int->enum
      C++: Fix page_zonenum() int->enum
      C++: mutex_trylock_recursive_enum() int->enum
      C++: Fix spinlock initialisation
      C++: Fix sema_init()
      C++: Cast in bitops
      C++: Hide C++ keywords
      C++: Don't need to declare struct pgd_t after typedef
      C++: Can't declare unsized-array in struct cgroup
      C++: Move initcall_level_names[] to __initdata section


 Makefile                               |   13 -
 arch/x86/Makefile                      |    2 
 arch/x86/entry/syscalls/Makefile       |    8 
 arch/x86/entry/syscalls/syscallhdr.pl  |   73 ++++
 arch/x86/entry/syscalls/syscalltbl.pl  |   95 +++++
 arch/x86/include/asm/alternative.h     |   10 -
 arch/x86/include/asm/apic.h            |    2 
 arch/x86/include/asm/arch_hweight.h    |    4 
 arch/x86/include/asm/atomic.h          |    2 
 arch/x86/include/asm/atomic64_64.h     |   12 -
 arch/x86/include/asm/cmpxchg.h         |  430 +++++++++++-----------
 arch/x86/include/asm/cmpxchg_64.h      |   28 +
 arch/x86/include/asm/hw_irq.h          |   38 +-
 arch/x86/include/asm/percpu.h          |   94 ++---
 arch/x86/include/asm/perf_event.h      |    2 
 arch/x86/include/asm/processor.h       |    2 
 arch/x86/include/asm/special_insns.h   |    2 
 arch/x86/include/asm/tlbflush.h        |    1 
 arch/x86/include/asm/uaccess.h         |  630 +++++++++++++++++---------------
 arch/x86/include/asm/uaccess_64.h      |   66 +--
 arch/x86/kernel/asm-offsets_32.c       |    1 
 arch/x86/kernel/asm-offsets_64.c       |    1 
 arch/x86/purgatory/Makefile            |    2 
 include/asm-generic/bitops/le.h        |   32 +-
 include/asm-generic/sections.h         |    2 
 include/linux/acpi.h                   |    2 
 include/linux/backing-dev-defs.h       |    4 
 include/linux/blkdev.h                 |   86 ++--
 include/linux/build_bug.h              |    5 
 include/linux/byteorder/generic.h      |    4 
 include/linux/cgroup-defs.h            |    2 
 include/linux/compat.h                 |    2 
 include/linux/compiler-c++.h           |   54 +++
 include/linux/compiler-gcc.h           |    5 
 include/linux/compiler.h               |   93 +----
 include/linux/compiler_types.h         |    2 
 include/linux/context_tracking.h       |    4 
 include/linux/context_tracking_state.h |   14 -
 include/linux/cpumask.h                |    4 
 include/linux/crypto.h                 |    4 
 include/linux/elevator.h               |   82 ++--
 include/linux/file.h                   |    2 
 include/linux/interrupt.h              |   10 -
 include/linux/irq.h                    |    1 
 include/linux/irqflags.h               |   10 +
 include/linux/jump_label.h             |   41 +-
 include/linux/kernel.h                 |   35 --
 include/linux/kernfs.h                 |    2 
 include/linux/ktime.h                  |   12 +
 include/linux/list.h                   |    8 
 include/linux/list_bl.h                |    4 
 include/linux/list_nulls.h             |    2 
 include/linux/lockdep.h                |    2 
 include/linux/mm.h                     |    2 
 include/linux/mutex.h                  |    5 
 include/linux/page-flags.h             |    3 
 include/linux/poison.h                 |    6 
 include/linux/printk.h                 |    4 
 include/linux/projid.h                 |    2 
 include/linux/rculist.h                |    4 
 include/linux/rculist_bl.h             |    2 
 include/linux/rcupdate.h               |  124 ++++--
 include/linux/sched/task.h             |    2 
 include/linux/semaphore.h              |    5 
 include/linux/spinlock.h               |    2 
 include/linux/spinlock_types.h         |    4 
 include/linux/start_kernel.h           |    2 
 include/linux/stddef.h                 |   12 -
 include/linux/sysctl.h                 |    6 
 include/linux/timer.h                  |    1 
 include/linux/trace_events.h           |   16 -
 include/linux/types.h                  |   16 +
 include/linux/uidgid.h                 |    4 
 init/main.c                            |    4 
 scripts/checksyscalls.sh               |    2 
 tools/power/cpupower/Makefile          |    1 
 tools/virtio/Makefile                  |    2 
 77 files changed, 1269 insertions(+), 1010 deletions(-)
 create mode 100644 arch/x86/entry/syscalls/syscallhdr.pl
 create mode 100644 arch/x86/entry/syscalls/syscalltbl.pl
 create mode 100644 include/linux/compiler-c++.h

^ permalink raw reply	[flat|nested] 40+ messages in thread

end of thread, other threads:[~2024-01-12 23:54 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-04-01 21:32 [PATCH 00/45] C++: Convert the kernel to C++ Alexey Dobriyan
  -- strict thread matches above, loose matches on Subject: below --
2024-01-11 10:56 Alexey Dobriyan
2024-01-11 10:58 ` Neal Gompa
2024-01-11 11:12   ` Alexey Dobriyan
2024-01-11 12:12   ` Andreas Herrmann
2018-04-01 20:40 David Howells
2018-04-01 22:20 ` Randy Dunlap
2018-04-02  9:28 ` Vegard Nossum
2024-01-09 19:57 ` H. Peter Anvin
2024-01-09 23:29   ` Andrew Pinski
2024-01-11 21:01     ` Arsen Arsenović
2024-01-10  0:29   ` David Howells
2024-01-10  8:58   ` Jiri Slaby
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-10 17:57           ` Theodore Ts'o
2024-01-12  2:23             ` H. Peter Anvin
2024-01-12  2:52               ` Kent Overstreet
2024-01-11  8:06       ` Andreas Herrmann
2024-01-10 15:01   ` Michael de Lang
     [not found]     ` <69fe1c0c-b5ec-4031-b719-d9c14742929c@metux.net>
2024-01-12 21:58       ` Michael de Lang
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
2024-01-11 12:39   ` Chris Down
2024-01-11 19:40     ` David Laight
2024-01-12  2:54   ` H. Peter Anvin
2024-01-12  8:52   ` David Howells
2024-01-12 23:53     ` H. Peter Anvin
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
2024-01-11 23:09 ` Arsen Arsenović
2024-01-12  9:20 ` David Howells
2024-01-12 21:35   ` Arsen Arsenović
2024-01-12 23:41   ` David Howells

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).