C++ in the kernel
john.w.court at nokia.com
john.w.court at nokia.com
Tue Oct 30 16:42:55 PDT 2007
I really try to avoid these type of discussions but it occurs to me that
perhaps no-one on the list has much experience with actually using C++
in a kernel or even embedded environment. Since I have done ULTRIX,
OSF1, NetBSD, Linux and now FreeBSD kernel work at various times plus
embedded device work on Motorola Digital Set Top Boxes maybe I can add
some first hand experience anecdotes. I will stay away from whether or
not it is a good idea for your FreeBSD particular situation.
So I worked for a voice recognition startup for about 7 years attempting
to bring true voice control to the Digital Cable market, you know things
like "Find movies with John Wayne". Anyway we started doing this on a
M68K based STB with only 1.5 MB or flash and 1.5MB of RAM and no disks.
The processor was clocked at 27Mhz but really ran at an equivalence of
7Mhz due to the fact that there was no cache whatsoever so it was
usually waiting for data.
Why is all this important to mention ? Mainly because the type of
solution we were creating had to do a lot of data manipulation and some
reasonably complex stuff on the STB before it sent anything to the
headend. It would have taken us a lot longer than we had to create all
the structures (hash tables, maps, communication protocols, device
handlers) using C even though that was the only language supported on
these primitive boxes. Instead we took one engineer aside and ported
the gnu C++ toolchain. We also created a H/W Serial/USB BDM device that
allowed stepping the OS code and used gdb on the other end to debug.
What we got for that one engineers effort was a development environment
not seen on those STBs ever and a productivity gain that allowed 4
engineers to develop a very complex product. The environment was then
ported to the MIPs based STBs but stopped short of an equivalent JTAG
based debugging dongle due to the company changing directions to Mobile
phones at that point.
What we learnt from all this was close to what you have all been
mentioning in one way or another.
The Bad Things :
* Exceptions are a hideous hack and compilers generated code is not
efficient at dealing with them, outlaw them from the start or even
remove them from the compiler somehow (i.e. a switch).
* RTTI is a large consumer of space although you always find you semi
re-invent the same mechanisms the minute you start to get serious about
polymorphism to reduce code.
* Multiple inheritance is just as big a mess as exceptions for OS
applications, outlaw it since for starters it tends to lure you into
needing RTTI but in general its just ugly.
The Good Things :
* STL is surprisingly damn useful. Being able to use AVL maps, lists,
queues, iterators makes coding data structures intuitive and simple.
The tricks we learnt were that STL only bloats if you use a lot of
key/data types, restrict yourself to a well defined set of keys (i.e.
only ints of various sizes) and a limited set of data (i.e. normally
To void *) and then static cast to what you need based on the fact that
the class that puts stuff into a STL structure is the one that pulls it
out and hands it off so it KNOWS what the type should be.
* STL chunking of memory needs to be looked at, the problem is that most
STL implementations assume that they are running in a process that on
exit will have its memory cleaned up for it. Because of this it
implements chunking of STL node memory in a very efficient way, but one
that assumes it never gives back memory and a way that can cause memory
fragmentation. Spending a few weeks fixing this allowed us to
extensively use STL in an environment of 1.5MB where we were caching a
lot of data.
* Polymorphism really helps in low level work, more than you would ever
think. I would be certain that device drivers could make good use of
it, I certainly did when doing software handlers for Digital Tunners on
the STB. File systems as well seem like a natural fit given that you
are already using an OO approach to them.
* Name spacing is simply a god send. It stops people worrying about
prefixs on functions.
* SmartObjects (i.e. those that are able to delete themselves when
no-one is referencing them any longer) virtually eliminated any chance
of memory leaks. This is akin to how JAVA does things but simply hugely
more efficient. It costs just a single counter in each object if you are
careful about the implementation. We literally never had to debug an
invalid reference to an object or a memory leak in the C++ code. The
same approach can be taken for SMP locks in a C++ environment which I
have done at application level but not had the chance in the kernel yet.
* All the reverse engineering tools like Umbrello, Borland Together,
Rational Rose was available to help produce automated documentation and
diagramatic views of the design. It's a sad fact that Structured
Programming never received this sort of support from design tools.
So I guess to summarise, the environement we were developing in was
probably closest to the concept of Loadable Kernel modules in FreeBSD.
We produced our own middleware and applications that got loaded off the
Cable network onto the STBS. However it was very low level as well as
having to do quite complex data manipulation on a very constrained
device. We wouldn't have even gotten close to what we achieved without
using C++ rather than the preferred vendor endorsed C approach at that
time. In addition the OO paradigm made it easier to explain very complex
interactions between system components.
I suspect eventually there will be no choice as the OS gets more and
more complex that someone will bring in a true OO language into the
kernel. For my money the obvious starting place would be to support it
in loadable kernel modules.
Cheers and I hope I haven't ranted too much.
More information about the freebsd-arch