public inbox for ecos-discuss@sourceware.org
 help / color / mirror / Atom feed
* [ECOS] Seeking Thread join / waitpid equivalent.
@ 2004-08-27  0:46 John Carter
  2004-08-27  2:41 ` Billy
  2004-08-27 13:25 ` Andrew Lunn
  0 siblings, 2 replies; 9+ messages in thread
From: John Carter @ 2004-08-27  0:46 UTC (permalink / raw)
  To: ecos-discuss

We have just been bitten by the "Don't free the thread into in the 
destructor" problem as discussed so comprehensively by Ivan Horvat in 
April.
  http://sources.redhat.com/ml/ecos-discuss/2004-04/msg00122.html

Thanks Ivan!

Unfortunately the thread exiting is explicitly our lowest priority 
thread, so Reaper in a mbox trick won't work.

However, in languages such as Ruby, you have the nifty thread.join 
primitive. With processes under posix systems you have waitpid.

Isn't there something like that in ecos, where an arbitrary thread may wait 
for another thread to exit?



John Carter                             Phone : (64)(3) 358 6639
Tait Electronics                        Fax   : (64)(3) 359 4632
PO Box 1645 Christchurch                Email : john.carter@tait.co.nz
New Zealand

The universe is absolutely plastered with the dashed lines exactly one
space long.

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [ECOS] Seeking Thread join / waitpid equivalent.
  2004-08-27  0:46 [ECOS] Seeking Thread join / waitpid equivalent John Carter
@ 2004-08-27  2:41 ` Billy
  2004-08-27  3:44   ` John Carter
  2004-08-27 13:25 ` Andrew Lunn
  1 sibling, 1 reply; 9+ messages in thread
From: Billy @ 2004-08-27  2:41 UTC (permalink / raw)
  To: John Carter; +Cc: ecos-discuss

On Fri, Aug 27, 2004 at 12:02:00PM +1200, John Carter wrote:
> We have just been bitten by the "Don't free the thread into in the 
> destructor" problem as discussed so comprehensively by Ivan Horvat in 
> April.
>  http://sources.redhat.com/ml/ecos-discuss/2004-04/msg00122.html
> 
> Thanks Ivan!
> 
> Unfortunately the thread exiting is explicitly our lowest priority 
> thread, so Reaper in a mbox trick won't work.

I think the cyg_thread destruction question above is different from the
thread.join question below.

> However, in languages such as Ruby, you have the nifty thread.join 
> primitive. With processes under posix systems you have waitpid.

> Isn't there something like that in ecos, where an arbitrary thread may wait 
> for another thread to exit?

I dealt with this by hand, by applying a thin veneer of plastic wrap to
the eCos thread API.  What it did was associate a death_semaphore with
each my thread objects.  The cyg_thread_entry function I gave to eCos
looked something like:

	void
	thread_entry_function(cyg_addrword_t data)
	{
	    struct myThreadType *thread = (struct myThreadType*)data;
	    (*thread->entry_function)(thread->data);
	    cyg_semaphore_post(&thread->death_semaphore);
	}

So thread_join() was implemented as a wait() on that thread's
death_semaphore:

	void
	thread_join(struct myThreadType *thread)
	{
	    cyg_semaphore_wait(&thread->death_semaphore);
	}

Obviously nobody's trying to join() your lowest priority thread, so
the post would go unnoticed.

Semaphores aren't the best sync primative for this, but that's what I
did.  If I redo it, I'll probably use condition variables or event flags.

So I have intercepted the death of the thread by wrapping the
entry_function.  If you wanted to dig into Cyg_Thread::exit() and
put the post() in there, I guess it would be more seamless, but
then you're changing eCos code, which I try to avoid.

Just my 0.02


-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [ECOS] Seeking Thread join / waitpid equivalent.
  2004-08-27  2:41 ` Billy
@ 2004-08-27  3:44   ` John Carter
  2004-08-27  5:50     ` John Carter
  2004-08-27  6:47     ` Billy
  0 siblings, 2 replies; 9+ messages in thread
From: John Carter @ 2004-08-27  3:44 UTC (permalink / raw)
  To: Billy; +Cc: ecos-discuss

On Thu, 26 Aug 2004, Billy wrote:

> On Fri, Aug 27, 2004 at 12:02:00PM +1200, John Carter wrote:
> I think the cyg_thread destruction question above is different from the
> thread.join question below.

Yes and no. What the guy was trying to do via a thread destructor
would have been much more simply achieved via a thread.join in a
reaper thread.

thread_join(thread);
cyg_thread_delete(thread.handle);
free(thread.stack);

> 	void
> 	thread_entry_function(cyg_addrword_t data)
> 	{
> 	    struct myThreadType *thread = (struct myThreadType*)data;
> 	    (*thread->entry_function)(thread->data);
> 	    cyg_semaphore_post(&thread->death_semaphore);
> 	}
>

> 	void
> 	thread_join(struct myThreadType *thread)
> 	{
> 	    cyg_semaphore_wait(&thread->death_semaphore);
> 	}
>


So if you are doing something like..

thread_join(  &thread);
cyg_thread_delete( thread.handle);

unless the thread doing the join is of lower priority than the
exiting thread there exists a narrow gap between the post and the end
of cyg_thread_exit during which cyg_thread_delete can fail.

ie. Fundamentally _any_ userland fix to this problem is not going to
work.

The only hack I can think of is to use something like your thread
join, do the delete, test the result, if it failed sleep for a period,
repeat with exponential fall off on the sleep period.

Ugly ugly ugly.





John Carter                             Phone : (64)(3) 358 6639
Tait Electronics                        Fax   : (64)(3) 359 4632
PO Box 1645 Christchurch                Email : john.carter@tait.co.nz
New Zealand

The universe is absolutely plastered with the dashed lines exactly one
space long.

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [ECOS] Seeking Thread join / waitpid equivalent.
  2004-08-27  3:44   ` John Carter
@ 2004-08-27  5:50     ` John Carter
  2004-09-03  5:35       ` sandeep
  2004-08-27  6:47     ` Billy
  1 sibling, 1 reply; 9+ messages in thread
From: John Carter @ 2004-08-27  5:50 UTC (permalink / raw)
  To: ecos-discuss


I have just found this rather ugly code in the tftp_server.c

So it kills the tftp server thread...
        cyg_thread_kill(server->thread_handle);

whangs the priority of the thread it killed as high as possible.
        cyg_thread_set_priority(server->thread_handle, 0);

Waits a random period for it to die
         cyg_thread_delay(1);  // Make sure it gets to die...

Deletes the thread...
         if (cyg_thread_delete(server->thread_handle)) {

If deleting the thread actually worked...

             // Success shutting down the thread
Frees the memory associated with the thread..
             free(server);  // Give up memory
             return 1;
         }
Else ... we have a memory leak.

See why I'm looking for a cleaner way to do this?


On Fri, 27 Aug 2004, John Carter wrote:

>
> Yes and no. What the guy was trying to do via a thread destructor
> would have been much more simply achieved via a thread.join in a
> reaper thread.
>
> thread_join(thread);
> cyg_thread_delete(thread.handle);
> free(thread.stack);
>
>> 	void
>> 	thread_entry_function(cyg_addrword_t data)
>> 	{
>> 	    struct myThreadType *thread = (struct myThreadType*)data;
>> 	    (*thread->entry_function)(thread->data);
>> 	    cyg_semaphore_post(&thread->death_semaphore);
>> 	}
>> 
>
>> 	void
>> 	thread_join(struct myThreadType *thread)
>> 	{
>> 	    cyg_semaphore_wait(&thread->death_semaphore);
>> 	}
>> 
>
>
> So if you are doing something like..
>
> thread_join(  &thread);
> cyg_thread_delete( thread.handle);
>
> unless the thread doing the join is of lower priority than the
> exiting thread there exists a narrow gap between the post and the end
> of cyg_thread_exit during which cyg_thread_delete can fail.
>
> ie. Fundamentally _any_ userland fix to this problem is not going to
> work.
>
> The only hack I can think of is to use something like your thread
> join, do the delete, test the result, if it failed sleep for a period,
> repeat with exponential fall off on the sleep period.
>
> Ugly ugly ugly.
>
>
>
>
>
> John Carter                             Phone : (64)(3) 358 6639
> Tait Electronics                        Fax   : (64)(3) 359 4632
> PO Box 1645 Christchurch                Email : john.carter@tait.co.nz
> New Zealand
>
> The universe is absolutely plastered with the dashed lines exactly one
> space long.
>



John Carter                             Phone : (64)(3) 358 6639
Tait Electronics                        Fax   : (64)(3) 359 4632
PO Box 1645 Christchurch                Email : john.carter@tait.co.nz
New Zealand

The universe is absolutely plastered with the dashed lines exactly one
space long.

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [ECOS] Seeking Thread join / waitpid equivalent.
  2004-08-27  3:44   ` John Carter
  2004-08-27  5:50     ` John Carter
@ 2004-08-27  6:47     ` Billy
  1 sibling, 0 replies; 9+ messages in thread
From: Billy @ 2004-08-27  6:47 UTC (permalink / raw)
  To: John Carter; +Cc: Billy, ecos-discuss

On Fri, Aug 27, 2004 at 02:41:41PM +1200, John Carter wrote:
> On Thu, 26 Aug 2004, Billy wrote:
> 
> >On Fri, Aug 27, 2004 at 12:02:00PM +1200, John Carter wrote:
> >I think the cyg_thread destruction question above is different from the
> >thread.join question below.
> 
> Yes and no. What the guy was trying to do via a thread destructor
> would have been much more simply achieved via a thread.join in a
> reaper thread.
> 
> thread_join(thread);
> cyg_thread_delete(thread.handle);
> free(thread.stack);

True only if his reaper were stalking a single thread.  If his reaper is
stalking more than one, which would he join with first?  Maybe this is
why I thought they were different questions.

> >	void
> >	thread_entry_function(cyg_addrword_t data)
> >	{
> >	    struct myThreadType *thread = (struct myThreadType*)data;
> >	    (*thread->entry_function)(thread->data);
> >	    cyg_semaphore_post(&thread->death_semaphore);
> >	}
> >
> 
> >	void
> >	thread_join(struct myThreadType *thread)
> >	{
> >	    cyg_semaphore_wait(&thread->death_semaphore);
> >	}
> >
> 
> 
> So if you are doing something like..
> 
> thread_join(  &thread);
> cyg_thread_delete( thread.handle);
>
> unless the thread doing the join is of lower priority than the
> exiting thread there exists a narrow gap between the post and the end
> of cyg_thread_exit during which cyg_thread_delete can fail.

That's true.  I see that I was only getting away with it because I don't
ever actually delete the expired thread.

> ie. Fundamentally _any_ userland fix to this problem is not going to
> work.

Apparently so!  There are no hooks to mark the end of cyg_thread_exit()
and the thread_delete()-ability of a thread.  Seems like they might be
useful in order to make cyg_thread_delete() practical without resorting
to priority acrobatics and unnecessary thread_delay calls.   I'd hope
such a proposal would be more waitpid()-ish than join()-ish, to enable a
peer-priority reaper to stalk multiple victims.


-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [ECOS] Seeking Thread join / waitpid equivalent.
  2004-08-27  0:46 [ECOS] Seeking Thread join / waitpid equivalent John Carter
  2004-08-27  2:41 ` Billy
@ 2004-08-27 13:25 ` Andrew Lunn
  1 sibling, 0 replies; 9+ messages in thread
From: Andrew Lunn @ 2004-08-27 13:25 UTC (permalink / raw)
  To: John Carter; +Cc: ecos-discuss

On Fri, Aug 27, 2004 at 12:02:00PM +1200, John Carter wrote:
> We have just been bitten by the "Don't free the thread into in the 
> destructor" problem as discussed so comprehensively by Ivan Horvat in 
> April.
>  http://sources.redhat.com/ml/ecos-discuss/2004-04/msg00122.html
> 
> Thanks Ivan!
> 
> Unfortunately the thread exiting is explicitly our lowest priority 
> thread, so Reaper in a mbox trick won't work.

Not a problem. Change the priority of the thread as it exits to
something higher than the reaper thread.

        Andrew

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [ECOS] Seeking Thread join / waitpid equivalent.
  2004-08-27  5:50     ` John Carter
@ 2004-09-03  5:35       ` sandeep
  2004-09-03 17:22         ` Billy
  0 siblings, 1 reply; 9+ messages in thread
From: sandeep @ 2004-09-03  5:35 UTC (permalink / raw)
  To: John Carter; +Cc: ecos-discuss

John Carter wrote:
> I have just found this rather ugly code in the tftp_server.c
> 
> So it kills the tftp server thread...
>        cyg_thread_kill(server->thread_handle);
> 
> whangs the priority of the thread it killed as high as possible.
>        cyg_thread_set_priority(server->thread_handle, 0);
> 
> Waits a random period for it to die
>         cyg_thread_delay(1);  // Make sure it gets to die...
how can you ensure that delay of 1 or N ticks that you put here, makes sure that 
it gets to die??? unless ofcourse you never have any thread in your system that 
runs at priority 0 (highest) apart from these cases where you boost priority of 
thread you killed, to 0.
for, if you have some threads running at priority 0 already, you need to know 
the maximum no. of them that can be there in runqueue at any point of time, that 
will be before your boosted-priority thread (considering round robin scheduling 
and no-SMP) to find a sure-value that can be given to above cyg_thread_delay.

> Deletes the thread...
>         if (cyg_thread_delete(server->thread_handle)) {
> 
> If deleting the thread actually worked...
> 
>             // Success shutting down the thread
> Frees the memory associated with the thread..
>             free(server);  // Give up memory
>             return 1;
>         }
> Else ... we have a memory leak.

--
sandeep
--------------------------------------------------------------------------
"I do not know myself, and God forbid that I should."
--------------------------------------------------------------------------


-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [ECOS] Seeking Thread join / waitpid equivalent.
  2004-09-03  5:35       ` sandeep
@ 2004-09-03 17:22         ` Billy
  0 siblings, 0 replies; 9+ messages in thread
From: Billy @ 2004-09-03 17:22 UTC (permalink / raw)
  To: sandeep; +Cc: John Carter, ecos-discuss

On Fri, Sep 03, 2004 at 11:15:45AM +0530, sandeep wrote:
> John Carter wrote:
> >I have just found this rather ugly code in the tftp_server.c
> >
> >So it kills the tftp server thread...
> >       cyg_thread_kill(server->thread_handle);
> >
> >whangs the priority of the thread it killed as high as possible.
> >       cyg_thread_set_priority(server->thread_handle, 0);
> >
> >Waits a random period for it to die
> >        cyg_thread_delay(1);  // Make sure it gets to die...

> how can you ensure that delay of 1 or N ticks that you put here, makes sure 
> that it gets to die???

> unless ofcourse you never have any thread in your 
> system that runs at priority 0 (highest) apart from these cases where you 
> boost priority of thread you killed, to 0.

You can't be sure.  It's unreliable code.  At the least, it places
spooky taboos (regarding thread priorities) on applications that need to
integrate the tftp server.

This was John's point, I think.

> for, if you have some threads running at priority 0 already, you need to 
> know the maximum no. of them that can be there in runqueue at any point of 
> time, that will be before your boosted-priority thread (considering round 
> robin scheduling and no-SMP) to find a sure-value that can be given to 
> above cyg_thread_delay.

> >Deletes the thread...
> >        if (cyg_thread_delete(server->thread_handle)) {
> >
> >If deleting the thread actually worked...
> >
> >            // Success shutting down the thread
> >Frees the memory associated with the thread..
> >            free(server);  // Give up memory
> >            return 1;
> >        }
> >Else ... we have a memory leak.

A replacing the 'if' with 'while' and bringing the
cyg_thread_delay inside would be better, I guess...

Still a clumsy hack which could be avoided if there were
a mechanism to wait on a thread's 'delete'-ability.


-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [ECOS] Seeking Thread join / waitpid equivalent.
@ 2004-09-06 10:32 Øyvind Harboe
  0 siblings, 0 replies; 9+ messages in thread
From: Øyvind Harboe @ 2004-09-06 10:32 UTC (permalink / raw)
  To: ecos-discuss, john.carter

How about:


struct args
{
        cyg_handle_t caller;
};

static void invoker(cyg_addrword_t userData)
{
        args *a=(args *)userData;

	// this fn returns when the terminate flag is set
        doWork();
          
        // once the thread runs off the end of the universe, the
scheduler is
        // unlocked => it is not necessary to unlock the scheduler from 
        // the "caller" thread below.
        cyg_scheduler_lock(); 
        cyg_thread_resume(a->caller);
}


void foo()
{
        ....
        cyg_thread_create(0,
        invoker,
        (cyg_addrword_t)&a,
        "work",
        stack,
        stackSize,
        &threadHandle,
        &thread);
        
        // start thread
        cyg_thread_resume(threadHandle);
        
        doSomethingElse();

	// we do not want anyone else to run at this point
	cyg_sched_lock();

        setThreadTerminateFlag();

        // at this point we will do nothing but wait for the other
        // thread to complete.

        // we'll be resumed by the thread above when it exits
        cyg_thread_suspend(a.caller);
	cyg_sched_unlock();

        if (!cyg_thread_delete(threadHandle))
        {
                CYG_FAIL("Thread should be terminated by now");
        }

}



-- 
Øyvind Harboe
http://www.zylin.com



--
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2004-09-06 10:32 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-08-27  0:46 [ECOS] Seeking Thread join / waitpid equivalent John Carter
2004-08-27  2:41 ` Billy
2004-08-27  3:44   ` John Carter
2004-08-27  5:50     ` John Carter
2004-09-03  5:35       ` sandeep
2004-09-03 17:22         ` Billy
2004-08-27  6:47     ` Billy
2004-08-27 13:25 ` Andrew Lunn
2004-09-06 10:32 Øyvind Harboe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).