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
- Cc: ecos-discuss at sources dot redhat dot com
- Date: Thu, 15 Apr 2004 01:00:55 +0200
- Subject: [ECOS] Re: Thread destructors
Hi Chris,
Thanks for the fast response. I hope you've had a happy
easter.
Thanks you for the wishes, I hope you had happy easter too (they say
it's never late). Sorry for the delay,
I'm having some problems with my email-server...
I didn't grasp this at first, but I guess that what you are
saying is that even though I have exited the thread for which
I would like to free up memory I can't just do that in the
reaper thread as it still "being used" by the scheduler. So
in the reaper thread I have to call cyg_thread_delete before
doing any clean-up (ie stack, thread object and handle)? Does
this also mean that if I wanted I could restart the thread by
calling the cyg_thread_resume?
It is actually safe to free the stack in "reaper" even *before* deleting
the thread (as the reaper has the lower priority
and the exited thread won't run any more - it is in EXITED state).
Thread handle may be freed at any time,
but the thread object can be cleaned-up *only after* deleting the thread.
After the thread calls the cyg_thread_exit(), there is still a "zombie"
thread object that never again gets the
RUNNING state (it is now in state EXITED), but it is still "hanging
arround" in scheduler thread tables.
The bad thing is that after this "zombie" descriptor is used last time
in Cyg_Scheduler::unlock_inner() in call to
HAL_THREAD_SWITCH_CONTEXT(&c, &n), it still contains *vital* information
for scheduler in form of
linked-list pointers to other thread objects. The
cyg_thread_delete(thread) actually calls the th->~Cyg_Thread(),
where the associated thread descrptor is obtained as:
Cyg_Thread *th = (Cyg_Thread *)thread;
The Cyg_Thread::~Cyg_Thread() calls Cyg_Thread::remove_from_list(),
which actually removes the object from
the scheduler's list and only now it is safe to free the space occupied
by the thread descriptor. But of course, the
function cyg_thread_delete() cannot be called by the thread to delete
itself, as it calls the Cyg_Thread::kill()
which in turn checks if it is the current thread that is about to be
"killed":
if( this == Cyg_Scheduler::get_current_thread() )
exit();
So, cyg_thread_delete() must be used from another thread (context) e.g.
"reaper" thread.
I think exited threads cannot be restarted with cyg_thread_resume(), but
as far as I know, it is safe not to free the
space of thread object and pass it to another cyg_thread_create(). This
"reuse" doesn't seem to harm the scheduler...
Your implementation of ReaperThread (under the condition it has lower
priority than any other thread it can
possibly reap) can be safely rewritten as:
void ReaperThread(cyg_addrword_t pParam)
{
// pParam is a pointer to our message box
cyg_handle_t hMsgBox = *((cyg_handle_t *)pParam);
while(1) {
// Wait for an exiting thread to send us a message
// The message contains the address to its data
ThreadData *ptp = cyg_mbox_get(hMsgBox);
// Delete the threads allocated stack // MOVED BEFORE DELETE()
delete [] ptp->pStack; // MOVED BEFORE DELETE()
// "Disconnect" thread for the scheduler
cyg_thread_delete(ptp->hThread);
// Delete rest of its data (handle,object, etc..)
delete ptp;
}
}
However, this is not necessary, and I will use your original
implementation of ReaperThread()...
Best 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