Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

c++ kernel

8 views
Skip to first unread message

Patrick Mahoney

unread,
Nov 22, 2002, 12:50:11 AM11/22/02
to
Hello people,

I have a question.

What are the _programming_ implications of writing a kernel in c++
instead of c other than having to implement 'new' and 'delete'
subroutines?

Is there additional code that the os programmer needs to write in
order to have a c++ kernel up and running? For example, does rtti or
polymorphism require some bits from libstdc++?

I would guess it would be true for rtti since static_cast<>() and such
functions would need to be implemented also... But Tim Robsinson
mentions OS support being needed for rtti and exceptions... whats that
about?
(http://groups.google.ca/groups?q=rtti+robinson+group:alt.os.development&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=9ft2bm%24480%241%40newsg2.svr.pol.co.uk&rnum=2)

How about polymorphism? Is there anything else other implication from
the programmer's point of view?


Thanks,


Pat Mahoney

Jeroen van Bemmel

unread,
Nov 22, 2002, 2:05:46 AM11/22/02
to
Hi,

I wrote a C++ kernel but so far I didn't need rtti or the C++ kind of
exceptions. Indeed, they would require some
additional support from the OS, but I did not go that far yet. It looks like
you'll need to implement some compiler
specific functions (I use gcc)

Instead I used set_jump-like exceptions (sometimes called structured
exception handling) which works fine for
me at the kernel level. I did not want to use C++ exception handling because
it introduces some additional runtime overhead.
For something similar to rtti I simply use C++ virtual functions (I know
it's not ideal, but you can make it work)

> Is there additional code that the os programmer needs to write in
> order to have a c++ kernel up and running? For example, does rtti or
> polymorphism require some bits from libstdc++?

I did not implement any libstdc++ stuff

> How about polymorphism? Is there anything else other implication from
> the programmer's point of view?

One thing you'll need to remember is to link in the methodtables that gcc
generates for C++ classes. Typically an OS kernel
would have a custom link script, which needs sections like
*(.gnu.linkonce.d.*)
*(.gnu.linkonce.t.*)

Don't worry, the system will kindly remind you if you forget to do this
(symptom: virtual methods calls fail...)

One other thing you might have to provide support for is initialization of
static variables. gcc generates functions like
static_initialization_and_destruction
(or something like that) which get called before the traditional main()
function and after. My solution was to avoid using static variables that
require these
initializers (not all static variables do, for example simple types or
uninitialized pointers don't)

Bye,

Jeroen vB


Maxim S. Shatskih

unread,
Nov 22, 2002, 4:57:38 AM11/22/02
to
> How about polymorphism? Is there anything else other implication
from
> the programmer's point of view?

No implications, it is a question of pure taste.
Personally, I despise <static_cast> and similar operators. :-)

Max

David Hovemeyer

unread,
Nov 22, 2002, 10:22:06 AM11/22/02
to
Patrick Mahoney wrote:
> What are the _programming_ implications of writing a kernel in c++
> instead of c other than having to implement 'new' and 'delete'
> subroutines?
>
> Is there additional code that the os programmer needs to write in
> order to have a c++ kernel up and running? For example, does rtti or
> polymorphism require some bits from libstdc++?

If you don't use RTTI, the runtime support needed for a kernel in
C++ is minimal. Do you really need RTTI? I don't use RTTI, so I
don't know what's required to support it.

Nothing special is required for polymorphism, at least for
single inheritance. You just need to make sure that constructors
get called for objects with virtual methods, to set up the vtable.
I don't know about multiple inheritance.

So to summarize, getting a kernel written in C++ with no RTTI and
single inheritance to run is pretty easy, at least with the GNU
compiler and linker (which is what I'm assuming you're going to use).

-Dave

Craig Graham

unread,
Nov 23, 2002, 7:17:13 AM11/23/02
to
David Hovemeyer wrote:

> Nothing special is required for polymorphism, at least for
> single inheritance. You just need to make sure that constructors
> get called for objects with virtual methods, to set up the vtable.
> I don't know about multiple inheritance.

The compiler should generate the call to the constructor for you (GCC does).
Multiple inheritance more of a can of worms - in our system, it just seemed
to "work" (eg. deriving a UI object from the Widget baseclass and the
Thread baseclass to provide background processing facilities to a UI
widget).

In GCC, you only really need to implement the following functions to get C++
code to play nice:
void *__builtin_new(unsigned long a) : a wrapper for malloc(), should memset
the memory to zero as well.
void __builtin_delete(void *p) : a wrapper for free()
void *__builtin_vec_new(unsigned long a) : exactly the same as
__builtin_new(), but called for vector allocationing object arrays.
void __builtin_vec_free(void *p) : exactly the same as __builtin_free(),
but called for vector de-allocationing object arrays.
void __pure_virtual(void) : called when a pure virtual function is invoked
(print out some error messages, it's a bug in your kernel).

Oh yeah - and one other important thing. Your startup code must invoke all
the constructors for global / staticly allocated objects:

typedef void (*CXXFPTR)(void);
extern CXXFPTR __CTOR_LIST__[];
extern CXXFPTR __DTOR_LIST__[];

void __do_global_ctors(void)
{
int f;
DbgPrint("__CTOR_LIST__=");
DbgPrintHex((unsigned long)__CTOR_LIST__);
DbgPrint("\n__CTOR_LIST__[0]=");
DbgPrintHex((unsigned long)__CTOR_LIST__[0]);
DbgPrint("\n__CTOR_LIST__[1]=");
DbgPrintHex((unsigned long)__CTOR_LIST__[1]);
DbgPrint("\n__CTOR_LIST__[2]=");
DbgPrintHex((unsigned long)__CTOR_LIST__[2]);

if(__CTOR_LIST__[0]==0)
{
DbgPrint("\nno C++ globals, skipping static constructors\n");
return;
}

DbgPrint("\nrunning static constructors: count=%d\n",__CTOR_LIST__[0]);
for(f=1; __CTOR_LIST__[f]; f++)
{
DbgPrint(" @ 0x");
DbgPrintHex((unsigned long)__CTOR_LIST__[f]);
DbgPrint("\n");
__CTOR_LIST__[f]();
}
}

In my link script, there's a block that looks like:
PROVIDE (__CTOR_LIST__ = .);
.ctors :
{
*(.ctors)
} >code

This embeds a table of constructors in the binary, and exports the symbol
__CTOR_LIST__ as a pointer to it. The function given above will then invoke
all the global constructors from the list.

Laters,
Craig.
--
You wish.

Stéphane Martineau

unread,
Nov 23, 2002, 2:02:01 PM11/23/02
to
> The compiler should generate the call to the constructor for you (GCC
does).

Anybody know why GCC generate the code for constructors two time ? Both
copy seem to be the same, weird!


Umberto Giacobbi

unread,
Nov 23, 2002, 5:55:56 PM11/23/02
to
I wrote my Kernel in c++ and i use without any trick polymorphism, static
variables and other oo things.
Only new and delete require some attenction. If you like i can send you some
code from my os.


Bye
Umberto Giacobbi


Jeroen van Bemmel

unread,
Nov 23, 2002, 6:49:58 PM11/23/02
to

"Stéphane Martineau" <sma...@mail.com.NOSPAM> wrote in message
news:MgQD9.30027$As6.4...@wagner.videotron.net...

They claim it's a 'feature', not a bug. Apparently there's different kinds
of constructors, memory allocating ones and initializing ones.
Same for destructors. I never quite understood why either, I even wrote a
small script to filter some of them out of my kernel since they're mostly
not used.
"In some cases the compiler might do better" it was said in response to all
the bug reports coming in. So hopefully there will be improvement
in future releases of GCC, because at the moment it's generating those
stupid things for even the most trivial of cases

Jeroen vB

KVP

unread,
Nov 24, 2002, 6:48:15 AM11/24/02
to
"Jeroen van Bemmel" <anon...@somewhere.com> wrote in message
> "Stéphane Martineau" <sma...@mail.com.NOSPAM> wrote in message
> > > The compiler should generate the call to the constructor for you (GCC
> > does).
> > Anybody know why GCC generate the code for constructors two time ? Both
> > copy seem to be the same, weird!
> They claim it's a 'feature', not a bug. Apparently there's different kinds
> of constructors, memory allocating ones and initializing ones.
> Same for destructors. I never quite understood why either, I even wrote a
> small script to filter some of them out of my kernel since they're mostly
> not used.
> "In some cases the compiler might do better" it was said in response to all
> the bug reports coming in. So hopefully there will be improvement
> in future releases of GCC, because at the moment it's generating those
> stupid things for even the most trivial of cases

The only thing they could do is to call the static initialization from
the allocating one. But when you turn on optimization, the compiler will
inline the code, so you end up with two constructors.

Viktor

ps:
If you can't turn this off with -O0, then it's hardwired into the compiler,
which is imho not a good solution.

Maxim S. Shatskih

unread,
Nov 24, 2002, 6:16:00 AM11/24/02
to
> Anybody know why GCC generate the code for constructors two time ?
Both
> copy seem to be the same, weird!

MSVC generates:
- your hand-written destructor as a function
- "scalal deleting destructor" thunk which calls your hand-written
destructor
- "vector deleting destructor" thunk which calls your hand-written
destructor

Nothing strange if GCC does the similar. Maintaining the correct
semantics of constuctors and destructors require a lot of machine code
auto-generated by the compiler.

Borland C++ went a way by generating the prolog/epilog code for
constuctors and destructors in a way other then for plain functions,
to avoid these "scalal deleting destructor" thunks. C++ standard
allows this - it allows implementation of constuctors and destructors
in a way other then functions, and thus prohibits taking their
addresses.

Max

Stéphane Martineau

unread,
Nov 24, 2002, 7:38:53 PM11/24/02
to
>> Anybody know why GCC generate the code for constructors two time ? Both
>> copy seem to be the same, weird!

>From Jeroen (taken from google since I never saw that reply on my
>usenet server :)


>They claim it's a 'feature', not a bug. Apparently there's different kinds
>of constructors, memory allocating ones and initializing ones.
>Same for destructors. I never quite understood why either, I even wrote a
>small script to filter some of them out of my kernel since they're mostly
>not used.
">In some cases the compiler might do better" it was said in response to all
>the bug reports coming in. So hopefully there will be improvement
>in future releases of GCC, because at the moment it's generating those
>stupid things for even the most trivial of cases

No matter what, geneting two time the exact same code in two different
function doesn't makes any sense. I solved that by inlining my constructors
which only contained a call to a private method called init() which did the
work. That way the code was only generated one time, in my case it was
important for the resulting file size to be as small as possible. Anyway,
it's just stupid, but it's certainly not the only weird thing that I found
in gcc :(


0 new messages