This is the mail archive of the
ecos-discuss@sources.redhat.com
mailing list for the eCos project.
Re: Thread destructors
- From: Ivan Horvat <ihorvat at xylon dot hr>
- To: chris at nimseus dot com, ecos-discuss at sources dot redhat dot com
- Date: Wed, 07 Apr 2004 23:51:53 +0200
- Subject: [ECOS] Re: Thread destructors
Hi Chris,
I may give you some answers, as I struggled with the same problems.
However, this is only
from my picture of the eCos threads and related problems, so keep that
in mind. ;-)
I have read the suggestions here regarding thread destructors
and from what I understand it is illegal to do stack clean up
in the destructor as it is it running in its own context(?).
I assume you are asking if it is possible for a thread that is about to
exit, to call its own destructor.
In other words, if the thread can clean-up after itself? The answer is
no, but there is one more issue
to be considered, besides the stack problem.
The destructor freeing the thread's stack is actually "digging the hole
under its feet", as it runs on the
very same stack that it is about to free.
But if you assume that free() wouldn't corrupt the space it just freed,
you may be tempted to lock the scheduler,
free the stack and than call cyg_thread_exit(). No other thread would
get a chance to run, so the freed stack
wouldn't be corrupted (as eCos itself never uses malloc/free) and the
scheduler would be unlocked in the method
Cyg_Scheduler::unlock_inner() called at the end of Cyg_Thread::exit().
However, this approach is *very dirty* (thus not advisable) and
*incomplete* (as I willll try to explain)!
I guess that this also means that pParam input to the
destructor is also on the stack and if it would contain the
address to the allocated stack and be freed this would mess
up the memory. Correct?
It is actually processor-dependent where is the "pParam" variable. On
Intel it would be on the stack, while
on e.g. SPARC or MIPS processors it will be in one of the "input"
registers. But if it points to the stack
(context) of the thread executing the destructor, it is illegal as it
would free the stack-memory on which the
thread is currently running. Thus, the proposed destructor:
// Illegal destructor!?
ThreadDestructor(cyg_addrword_t pParam)
{
// Release allocated stack
// pParam contains the stack address
delete [] (cyg_unit8 *)pParam;
}
is illegal.
I have read somewhere the suggestion of using message boxes.
Does this mean that I can can put a message in a message box
with for example the stack address and then let another
thread do the clean up? Will this work as long as the clean-
up thread has a lower priority than the thread exiting?
This would work, under exactly these conditions you already mentioned:
1) the cleaning is done from *another* context (i.e. thread)
2) the other thread that performs cleaning *must* have lower priority
than any other thread it is supposed to clean
Yet, this is incomplete... The thread whose resources are to be
deallocated must first perform cyg_thread_exit()
(of course, otherwise the lower priority thread wouldn't get chance to
run at all). But, remember the
cyg_thread_create() function and its last parameter? It is a pointer to
"cyg_thread" object, that is handled as a
"black-box" structure. However, this structure is also often allocated
by malloc(), and *cannot* just be freed in the
cleaner (or usually called reaper) thread, as the scheduler depends on
the link pointers in that structure in order to
operate properly. If this space is just freed, then other thread may
obtain it and corrupt the pointers causing the
scheduler to crash. Thus, to fully clean the thread, you must first call
cyg_thread_delete() with the "cyg_handle_t"
parameter associated to the "cyg_thread" object in question, which would
remove that "cyg_thread" object from
the scheduler's list. Only now, it is "safe" to free the space occupied
by the "cyg_thread" object.
From my experience: if you don't perform the cyg_thread_delete() then
the "cyg_thread" object can be "reused", but
only for the purposes of creating the new thread (i.e. passing it to the
cyg_thread_create() as its last argument).
Any other use (usually) leads to imminent scheduler crash...
I hope this helps a bit.
Any constructive flame is welcome. :-)
Regards,
Ivan.
--
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss