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,


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


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