All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Arsen Arsenović" <arsen@aarsen.me>
To: David Howells <dhowells@redhat.com>
Cc: linux-kernel@vger.kernel.org
Subject: Re: [PATCH 00/45] C++: Convert the kernel to C++
Date: Fri, 12 Jan 2024 22:35:34 +0100	[thread overview]
Message-ID: <8634v2jh9s.fsf@aarsen.me> (raw)
In-Reply-To: <2154236.1705051203@warthog.procyon.org.uk>

[-- 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 --]

  reply	other threads:[~2024-01-12 22:53 UTC|newest]

Thread overview: 104+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-04-01 20:40 [PATCH 00/45] C++: Convert the kernel to C++ David Howells
2018-04-01 20:40 ` [PATCH 01/45] Use UINT_MAX, not -1, to represent an invalid UID, GID or project ID David Howells
2018-04-01 23:04   ` Randy Dunlap
2018-04-01 20:40 ` [PATCH 02/45] Fix exception_enter() return value David Howells
2018-04-05  1:34   ` Sasha Levin
2018-04-01 20:40 ` [PATCH 03/45] Fix loop var in be32_to_cpu_array() and cpu_to_be32_array() David Howells
2018-04-01 20:40 ` [PATCH 04/45] Fix use of ACPI_COMPANION_SET() David Howells
2018-04-01 20:40 ` [PATCH 05/45] C++: Set compilation as C++ for .c files David Howells
2018-04-02  6:10   ` kbuild test robot
2018-04-03 13:16     ` David Howells
2018-04-03 13:27       ` Fengguang Wu
2018-04-10  8:44         ` David Howells
2018-04-10  9:45           ` Fengguang Wu
2018-04-11  1:13             ` Li, Philip
2018-04-02  6:10   ` kbuild test robot
2018-04-01 20:40 ` [PATCH 06/45] C++: Do some basic C++ type definition David Howells
2018-04-02  4:37   ` kbuild test robot
2018-04-02  6:10   ` kbuild test robot
2018-04-01 20:40 ` [PATCH 07/45] C++: Define a header with some C++ type traits for type checking David Howells
2018-04-02  7:00   ` kbuild test robot
2018-04-01 20:41 ` [PATCH 08/45] C++: Implement abs() as an inline template function David Howells
2018-04-01 20:41 ` [PATCH 09/45] C++: x86: Fix the x86 syscall table production for C++ David Howells
2018-04-02  7:57   ` kbuild test robot
2018-04-01 20:41 ` [PATCH 10/45] C++: x86: Turn xchg(), xadd() & co. into inline template functions David Howells
2018-04-01 20:41 ` [PATCH 11/45] C++: x86: Turn cmpxchg() " David Howells
2018-04-01 20:41 ` [PATCH 12/45] C++: x86: Turn cmpxchg_double() " David Howells
2018-04-01 20:41 ` [PATCH 13/45] C++: x86: Turn cmpxchg64() " David Howells
2018-04-01 20:41 ` [PATCH 14/45] C++: x86: Turn put_user(), get_user() " David Howells
2018-04-01 20:41 ` [PATCH 15/45] C++: Need space between string and symbol David Howells
2018-04-01 20:41 ` [PATCH 16/45] C++: Disable VERIFY_OCTAL_PERMISSIONS() for the moment David Howells
2018-04-01 20:41 ` [PATCH 17/45] C++: Turn READ_ONCE(), WRITE_ONCE() & co. into inline template functions David Howells
2018-04-01 20:42 ` [PATCH 18/45] C++: Turn RCU accessors " David Howells
2018-04-01 20:42 ` [PATCH 19/45] C++: Turn ktime_add/sub_ns() " David Howells
2018-04-01 20:42 ` [PATCH 20/45] C++: init/main: Constify pointers David Howells
2018-04-01 20:42 ` [PATCH 21/45] C++: Set the type of atomic64_t to s64 David Howells
2018-04-01 20:42 ` [PATCH 22/45] C++: Define apic_intr_mode after the enum definition, not before David Howells
2018-04-01 20:42 ` [PATCH 23/45] C++: Don't do "extern asmlinkage" David Howells
2018-04-01 20:42 ` [PATCH 24/45] C++: Fix BUILD_BUG_ON_ZERO() David Howells
2018-04-01 20:42 ` [PATCH 25/45] C++: Fix void variables David Howells
2018-04-01 20:42 ` [PATCH 26/45] C++: Can't have variable/member names the same as typedef names David Howells
2018-04-01 20:42 ` [PATCH 27/45] C++: Disable __same_type() for the moment David Howells
2018-04-01 20:43 ` [PATCH 28/45] C++: Move ctx_state enum out of struct context_tracking David Howells
2018-04-01 20:43 ` [PATCH 29/45] C++: Move the print_line_t enum before first use David Howells
2018-04-01 20:43 ` [PATCH 30/45] C++: Include linux/hrtimer.h from linux/timer.h David Howells
2018-04-01 20:43 ` [PATCH 31/45] C++: Avoid using 'compl' and 'and' as names David Howells
2018-04-02  7:57   ` kbuild test robot
2018-04-01 20:43 ` [PATCH 32/45] C++: __to_fd() needs to reduce the size of v for struct fd::flags David Howells
2018-04-01 20:43 ` [PATCH 33/45] C++: Move irqchip_irq_state enum David Howells
2018-04-01 20:43 ` [PATCH 34/45] C++: Fix up use of LIST_POISON* David Howells
2018-04-01 20:43 ` [PATCH 35/45] C++: Fix static_branch_likely/unlikely() David Howells
2018-04-01 20:43 ` [PATCH 36/45] C++: Fix kernfs_type() int->enum David Howells
2018-04-01 20:43 ` [PATCH 37/45] C++: Fix page_zonenum() int->enum David Howells
2018-04-01 20:44 ` [PATCH 38/45] C++: mutex_trylock_recursive_enum() int->enum David Howells
2018-04-01 23:10   ` Randy Dunlap
2018-04-01 20:44 ` [PATCH 39/45] C++: Fix spinlock initialisation David Howells
2018-04-01 20:44 ` [PATCH 40/45] C++: Fix sema_init() David Howells
2018-04-01 20:44 ` [PATCH 41/45] C++: Cast in bitops David Howells
2018-04-02  6:10   ` kbuild test robot
2018-04-01 20:44 ` [PATCH 42/45] C++: Hide C++ keywords David Howells
2018-04-02  7:32   ` kbuild test robot
2018-04-01 20:44 ` [PATCH 43/45] C++: Don't need to declare struct pgd_t after typedef David Howells
2018-04-01 20:44 ` [PATCH 44/45] C++: Can't declare unsized-array in struct cgroup David Howells
2018-04-01 20:44 ` [PATCH 45/45] C++: Move initcall_level_names[] to __initdata section David Howells
2018-04-01 22:20 ` [PATCH 00/45] C++: Convert the kernel to C++ 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-10  0:29     ` David Howells
2024-01-11 21:01     ` Arsen Arsenović
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-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-24  6:53       ` Jiri Slaby
2024-01-12  2:54   ` H. Peter Anvin
2024-01-12  8:52     ` David Howells
2024-01-12 23:53       ` H. Peter Anvin
2025-02-27 16:44   ` Convert the kernel to C++: Lock-holding class David Howells
2024-01-11 23:09 ` [PATCH 00/45] C++: Convert the kernel to C++ Arsen Arsenović
2024-01-12  9:20   ` David Howells
2024-01-12 21:35     ` Arsen Arsenović [this message]
2024-01-12 23:41       ` David Howells
  -- strict thread matches above, loose matches on Subject: below --
2018-04-01 21:32 Alexey Dobriyan
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8634v2jh9s.fsf@aarsen.me \
    --to=arsen@aarsen.me \
    --cc=dhowells@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.