This is the mail archive of the ecos-discuss@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]