Page 1 of 1

Implicitly run ALL C++ stack frame deconstructors?

Posted: Sun Sep 30, 2012 5:34 pm
by OSwhatever
Threads in my OS live a very short life and they are ended with by calling an exit thread system call. This can be pure exit thread call or a send message call which can also exit the thread if desired. The reason for this is to avoid a "tail", basically that the scheduler must run the last of the thread if there was context switch because of the send call. This model works quite well and reduces the number of context switches but it has a side effect that the stack frame deconstructors are not run automatically due to the function never exits in the world of C++. This can be solved by calling all the deconstructors implicitly but it is kind of ugly and it is easy to forget which can lead that program leaks memory which kind of defeats one of the benefits of C++.

In my case I use GCC and I wonder if there is any way to tell the compiler to insert all the stack frame deconstructors before these exit thread system calls?

Re: Implicitly run ALL C++ stack frame deconstructors?

Posted: Sun Sep 30, 2012 6:41 pm
by Owen
Throw an "exit thread exception" and catch it in the thread's start routine. Otherwise, no.

How is GCC supposed to know what destructors need to be run, except for by walking the stack?

And, of course, this will be slower than just letting the normal flow of code unwind things.

I'd suggest making the return value of the thread's entry point be how you activate this optimization. Its the only comprehensive way to bring a threads' lifetime to an end.

Re: Implicitly run ALL C++ stack frame deconstructors?

Posted: Sun Sep 30, 2012 8:03 pm
by OSwhatever
Just exit thread is easy as then you can just return to thread start stack frame. It is the merged send and exit that makes it more difficult. One possibility is that in the thread function, the send and exit function is really just setting up a stack structure and this structure is passed downwards as a pointer to the thread creation frame, the thread creation frame then do appropriate action depending on what the struct contains.

Re: Implicitly run ALL C++ stack frame deconstructors?

Posted: Mon Oct 01, 2012 1:35 am
by JamesM

Code: Select all

#define BEGIN_FUNC() {
#define END_FUNC(x) } _outlab: return x; _exitlab: syscall_exit()
#define SEND_AND_EXIT(x) do {syscall_send(x); goto _exitlab;} while(0)

int f() {
BEGIN_FUNC();
DO STUFF
SEND_AND_EXIT(4);
END_FUNC(0);
}
How about that? You need some boilerplate, but it works...

Re: Implicitly run ALL C++ stack frame deconstructors?

Posted: Mon Oct 01, 2012 10:05 am
by OSwhatever

Code: Select all

#define BEGIN_FUNC() {
#define END_FUNC(x) } _outlab: return x; _exitlab: syscall_exit()
#define SEND_AND_EXIT(x) do {syscall_send(x); goto _exitlab;} while(0)

int f() {
BEGIN_FUNC();
DO STUFF
SEND_AND_EXIT(4);
END_FUNC(0);
}
Still send and exit are separate here, the point of this solution was that send and exit was done in the same syscall. Anyway I can see that my model will have further problems if you move up the chain with languages like Java which is heavy on dynamic allocation. If an object is given to the caller (thread start frame), Java will think there is reference to the object. Also a merged send and exit call in Java will certainly make the program to leak memory as some memory references will never be decreased.

If there are lots of cleaning up to do, then a separate send could be beneficial as a higher priority thread would be able run earlier before the cleaning. Many times though, it is just about sending an integer and then exit and there was no dynamic allocation, the "tail" of the thread will then be very small.

In practice you can do this manually, tell the programmer you have to call a second function if you want to do anything that requires deconstructors. Basically:

Code: Select all

MyThreadFunction()
{
	int retval = MyRealThreadFunctionThatDoestheWork();

	SendIntegerAndExit(retval, somethread);
}
Not really beautiful but it does work, this in practice the same as a thread frame but the programmer can here control the exit procedure.