Readit News logoReadit News
jcelerier · 4 years ago
> You see the problem. My C++ code expected the calling convention that pushed arguments on the stack,

that would be very weird on Linux. The x86_64 linux ABI mandates that the first arguments go on registers afaik (I'm assuming x86_64 here since the post mentions linux distros which are overwhelmingly x64). What compiler would default to a pure stack-based calling convention ? Certainly not GCC or clang, no ?

> and the kernel expected my code to pass arguments in the registers.

so, how is that a problem with C++ and not the compiler defaults ?

> I found the real gold mine of C++ kernel module development knowledge in OSDev.org. They have an entire article on C++ issues. That includes avoiding templates

bullshit it is then. https://www.youtube.com/watch?v=A_saS93Clgk

if templates are good (sometimes better even) on AVR microcontrollers with memory in kilobytes, there's no reason to not use them in a kernel meant to run on large embedded.

Also what's that rant about strings for ? In the end there is zero substance to this article, only very strange rants.

10000truths · 4 years ago
> that would be very weird on Linux. The x86_64 linux ABI mandates that the first arguments go on registers afaik (I'm assuming x86_64 here since the post mentions linux distros which are overwhelmingly x64). What compiler would default to a pure stack-based calling convention ? Certainly not GCC or clang, no ?

The System V i386 ABI passes parameters through the stack. Perhaps that is what the author is referring to, although I wouldn't be surprised if he mixed it up with the x64 ABI.

ivegotnoaccount · 4 years ago
In case it is talking about the x64 calling convention, there is actually some kind of an odd case where you would get something that looks like an argument was pushed on the stack:

When a non-trivially-copyable object is passed by value to a function, you need to ensure that through the lifetime of the copy, it's address will never change because the constructor may have stored address of some of the field (for instance, a pointer to a field). The way this is handled at list in the SystemV x84_64 ABI is that the object is created on the caller's stack, and a pointer to it is stored in a register, so just like if it was passed as a pointer.

I have seen several cases where a header would have an "ifdef c++" clause with copy constructors and destructors in them ("It does not add field so it should be OK, right ?"), which make the object non trivially-copyable, leading to clashing calling convention between C and C++ codes. I am curious about if this may be the issue he encountered.

saagarjha · 4 years ago
The 32-bit Linux kernel uses a register-based ABI internally, rather than System V.
inkyoto · 4 years ago
> The System V i386 ABI passes parameters through the stack.

No. The C/C++ ABI is quite uniform across architectures. The first 1..N (N is ISA dependant) parameters that can fit into a CPU register are passed via registers. The first input parameter that _can't_ fit into a register (e.g. a structure passed by value) is pushed onto the stack, with every other following parameter being pushed onto the stack as well. N+1… parameters are always passed through the stack.

varajelle · 4 years ago
> so, how is that a problem with C++ and not [...]

I don't think you should see this article as a criticism of C++. Just a rent on how hard it is to use in the Linux kernel which is openly against it.

saagarjha · 4 years ago
Perhaps the article is old enough to have been written in the 32-bit era?
jcranmer · 4 years ago
The Page Info I see says this:

> article:published-time 2016-10-28T11:40:06+00:00

which is well into the era of 64-bit code.

pajko · 4 years ago
The LDD3 mentioned is 32-bit era, and 2.6.x kernel, which had a CONFIG_REGPARM to allow passing parameters in registers (because the default was not to do that).
kevin_thibedeau · 4 years ago
AVRs don't have enough storage for templated code to explode into an unmanageable problem.
pjmlp · 4 years ago
Somehow C64 can deal with them.

"CppCon 2016: Jason Turner “Rich Code for Tiny Computers: A Simple Commodore 64 Game in C++17”"

https://www.youtube.com/watch?v=zBkNBP00wJE

"C++20 For The Commodore 64"

https://www.youtube.com/watch?v=EIKAqcLxtT0

inkyoto · 4 years ago
C++ templates are unwound at the compile time before the «expanded» template code passes along into the optimiser where most of the unused code is elided.

Unless the templates have been externalised (i.e. defined as «extern template …», of course). Even then, a modern compiler+linker combo will optimise most of the unused code away at the linking time thus reducing the final binary size. I do understand that the LTO might not be available for every embedded platform, though.

P.S. That is exactly the point of the C++ template metaprogramming – the hard lifting is delegated to the compiler, which leads to increased compile times but also to more efficient and very compact runtime code.

paulmooreparks · 4 years ago
What do templates have to do with storage, though? My primary attraction to C++ templates is that they let me write very expressive code that will compile down to a handful of instructions. Now, actually compiling complex C++ templates on a storage-constrained system can be a problem, since templates are compile-time beasts, not runtime. Once compiled, though, they have a Cheshire-cat existence.

Edit: Unless you're doing something rather silly with the templates, but again, that's not a template problem.

qalmakka · 4 years ago
I have _never_ had any issue with C++ templates on _modern_ µControllers such as the ESP32. Unless you have an incredibly minuscule flash, modern GCC or LLVM are very good at deleting unused code when you compile everything with -Os. Even -Og isn't that critical either.
zauguin · 4 years ago
> I found the real gold mine of C++ kernel module development knowledge in OSDev.org. They have an entire article on C++ issues. That includes avoiding templates

No, it doesn't?!? The linked article mentions templates two times (+ 2 mentions of the standard template library), once saying that templates can be used without further setup and the other times recommending that some template based data structures should be implemented. That's pretty far from "avoiding templates".

monocasa · 4 years ago
Lol, part of me likes the effort taken just because, but the kernel devs _really_ do not want C++. One hint: "struct class"

https://elixir.bootlin.com/linux/latest/source/include/linux...

nly · 4 years ago
What bothers me about that is that, because C doesn't have namespaces, it's already a terrible name for a struct. What if you want another "class" of thing?

Call it device_class ffs

tuyiown · 4 years ago
You're dismissing the fact that the keyword collision really well might be intentional, the worst of it is that `/sys/class` siblings `bus` and `driver`, if their internal linux rep is actually in the `class.h` siblings, are called `struct bus_type` and `struct device_driver`

Deleted Comment

steerablesafe · 4 years ago

   #define class Class
   #include <some_linux_header.h>
   #undef class
/s

Pinus · 4 years ago
Wasn't there a period recently — around 1995 or so — when the Linux kernel had to be compiled with a C++ compiler?
cesarb · 4 years ago
Quoting from http://vger.kernel.org/lkml/#s15-3 :

"In the dark old days, in the time that most of you hadn't even heard of the word "Linux", the kernel was once modified to be compiled under g++. That lasted for a few revisions. People complained about the performance drop. It turned out that compiling a piece of C code with g++ would give you worse code. It shouldn't have made a difference, but it did. Been there, done that."

monocasa · 4 years ago
I don't think that's accurate. Maybe you're thinking of how it needs gcc extensions?
mijoharas · 4 years ago
Why was that the case?
jerrysievert · 4 years ago
as long as nothing you're including includes that in c++, it shouldn't be an issue at the linker level, and thus not be an issue at all.

at least in general - if it's something that can't handled by a c shim then you might have an issue.

monocasa · 4 years ago
It's one of the most fundamental structures in the kernel. Pretty much all driver headers include it, if indirectly.
rajeevk · 4 years ago
In the past, I wrote a unix like kernel from scratch in C++. I have summarized what I had to do to get C++ code run on bare metal in this article https://www.avabodh.com/cxxin/nostdlib.html
ReaLNero · 4 years ago
I've always been interested in writing my own Unix-like kernel! Could you share what resources you used to write it? How long did the whole thing take?

Just to understand the scope of the work, did you implement any of the following: memory isolation, networking, concurrency via interleaving on single thread, parallelism where n threads can run n processes simultaneously? How long did each take to get done?

rajeevk · 4 years ago
I did this while I was doing my bachelor degree course. It was four year course and I started doing this sometime in 2nd year and continued till 4th year. I was not always writing code as I had to study other subjects as well. Also I was just learning coding and other computer science concepts, so it was like learning and writing code. But the writing the kernel forced me to learn many computer science concepts very deeply.

At the end, what I had was a kernel which could boot on bare metal (or VM) and provided a command line interface. It had a virtual file system layer and ext2 file systems, process management (fork, exec sys call), memory management (paging and process isolation) and device drivers for keyboard and hard disk. The kernel was able to fork and exec static ELF binary.

I did not reach to networking and threading. But that was next step which could make it complete unix kernel.

I implemented in bits of assembly(nasm) and C++. So I had to learn runtime and code generation aspect of c++. Based on that learning I wrote this articles on c++ object models and other internals. https://www.avabodh.com/cxxin/cxx.html

nly · 4 years ago
These are all standard C and C++ interop problems also found in userland and typically go away if the C project at hand is cooperative.
creamytaco · 4 years ago
There's one problem with rants such as these, it's too easy for someone to be exposed as clueless and broadcast his lack of knowledge and assumption-heavy development process to the world. How is that as an advertisement for one's employer?
rramadass · 4 years ago
Valueless Article. Please stop posting these sort of articles which have no information content.

The article is merely a rant because the author doesn't have much of an idea of how C++ actually works. Merely knowing the syntax doesn't make one a "C++ programmer" and this is even more true when you are messing around in the Kernel. The article contains no specifics only general statements making me think this was put up to just be a "hit piece".

gk1256 · 4 years ago
With all due to respect, your comment is an anti-specialization rant.

> Merely knowing the syntax doesn't make one a "C++ programmer"

Does knowing all the possible abstract layers (uh, it's an ocean) make one a C ++ programmer then?

> this is even more true when you are messing around in the Kernel

It's his right to mess around Kernel and learn things.

rramadass · 4 years ago
My comment has nothing to do with "anti-specialization" or "right to mess around" anything.

The article has zero substance with a generic rant being "i tried to use C++ to write a Kernel Module and ran into problems". There are no specifics w.r.t. C++ nor The Kernel and yet the author blames the C++ Language! Whatever is written up also betrays a certain ignorance of basic C/C++ ABI conventions leading one to surmise that the author is clueless (w.r.t. these two domains). As you can see from other comments in this thread, many others are also of the same opinion while others are guessing all over the map as to what the actual problem might be.

jlkjaoifnwlekfj · 4 years ago
> A first-year computer science student can tell you that the arguments get pushed onto the stack. In other words, a call to this 3GL function results in the following assembly pseudo code

Are people this ignorant when it comes to C/C++ or any systems language? ABI & calling conventions were introduced early in my C & C++ textbooks (age 13 btw, not even close to college years).

jcranmer · 4 years ago
Well, if you believed as the author did that arguments are always pushed onto the stack, you are pretty ignorant--most major architectures these days don't use the stack for arguments, at least not for the first several arguments.

(Semi-random tangent: the hardest bug I ever had the pleasure of debugging was when I discovered that the PLT glue code to load an entry into the PLT was unexpectedly clobbering a register that the calling convention said needed to be preserved. By very, very careful using non-default calling conventions across shared object boundaries!)

Deleted Comment

sumtechguy · 4 years ago
I think it would depend on which system you were introduced into. Also 99% sure in my classes in the mid 90s they taught stack push. Which made sense as registers were pretty valuable. It was not until RISC came along, and register renaming, that you could consider 'wasting' them on passing args in the general case. In the 'DOS'/'Win16' world calling conventions were all over the place. You could get into trouble real quick if you did not pay attention to those calling convention modifiers. Especially if you were using libs from different compilers. In the linux world where you can control the whole stack it is easier to say 'this way and if you stray away from it, good luck'.

Small sample of the remnants of that in the DOS world. https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-an...

mhh__ · 4 years ago
Ab initio first years probably just about know what registers are so I can believe that.

Decoupling the compilers optimizations and the ABI (particularly what constitutes a "move" of a struct) has derailed a few conversations I've been involved with - even from very smart devs (although mainly interpretation rather than basic misunderstandings like thinking what is actually due to the ABI is an optimization)