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: "Threads on ecos" confirmation needed...


Hi,

In your example here, could you use the thread status instead of thr_map to
know if the thread is EXITED. Assuming that the status of the thr_slots
threads are initialized to EXITED before they are started the first time,
wouldn't this eliminate the need for my_exit() ?

Cyg_Thread thr_slots[MAX_THREADS];
char thr_stacks[MAX_THREADS][STACK_SIZE];

Cyg_Thread *my_new_thread(...)
{
    int thread=MAX_THREADS-1;
    do {
        if(thr_slots[thread].status==EXITED)
            break;
    } while(thread>0);

    if(thread<0) {
        diag_printf("Ooopss... No more threads!\n");
        return NULL;
    }

    Cyg_Thread *t = new((void *)&thr_slots[thread]) Cyg_Thread
                             (... , &stack[thread][0], ...);

    return t;

}



-- Fabrice


-----Original Message-----
From: Nick Garnett [mailto:nickg@ecoscentric.com]
Sent: Saturday, January 31, 2004 8:35 AM
To: Ivan Horvat
Cc: ecos-discuss@sources.redhat.com
Subject: Re: [ECOS] "Threads on ecos" confirmation needed...



You can easily do all of this outside the kernel. For example:

Cyg_Thread thr_slots[MAX_THREADS];
char thr_stacks[MAX_THREADS][STACK_SIZE];
cyg_uint32 thr_map = 0;

Cyg_Thread *my_new_thread(...)
{
        Cyg_Scheduler::lock();

        int thread;
        HAL_LSBIT_INDEX( thread, thr_map );

        thr_map &= 1<<thread;

        Cyg_Scheduler::unlock();


        Cyg_Thread *t = new((void *)&thr_slots[thread]) Cyg_Thread
                                                          (... ,
&stack[thread][0], ...);

        return t;
}

void my_exit()
{
        int thread = Cyg_Thread::self()-&thr_slots[0];

        Cyg_Scheduler::lock();

        thr_map |= 1<<thread;

        thread->exit();
}

The one thing that you cannot do within a thread is to have it call
free() to release its thread object or stack. You would then end up
with a thread running in unallocated memory, which might be
reallocated before it successfully exits. Also, the last thing that
exit() does is context switch to another thread, for which we have to
pass through the scheduler. Going through the scheduler with an
invalid current thread would require all sorts of nasty special cases
to be added. This is why we have a two-phase thread shutdown
mechanism: exit() puts the thread to sleep and detaches it from the
scheduler data structures; the final destruction of the thread and the
freeing of its resources must then be done from another thread after
the exit() has succeeded.

> 
> Yes, this is a solution, but it requires another "garbage collector"
> thread. I would like to have the similar functionality provided by
> e.g Linux or Solaris; one can create a detached thread, and don't
> have to worry about its completion, as kernel resources are
> automatically cleaned-up.
>

Linux and Solaris are full kernel/user context operating systems. But
they must still get out of the context of the exiting thread to clean
it up. To do this they go into kernel mode. We don't have this
kernel/user dichotomy, and the only other contexts we have available
are other threads.

> 
> Why this can't be done with stacks? The "exit" method is quite
> simple and can be modified not to use stack variables. Initial
> creation of stack-frame and saving the return address can be
> avoided, I think, using "__attribute__" (or similar) gcc
> directives. Or thread->exit() may be inline... And per-thread
> clean-up code is ok for me, only if it can be done either by the
> thread that is about to exit, or by the *exit() function.

What you are suggesting here would be very architecture-specific and
incredibly fragile -- any change in the compiler might wreck it. While
it might work on register-rich architectures like MIPS or PowerPC, it
would have difficulties on smaller machines like ARM or SH4, and would
be impossible on IA32.

> 
> >
> > IH> The stack could be freed/cleaned by the exiting thread before
calling
> > IH> *exit() (I think) and
> > IH> the above solution would "free" the space for thread object.
> >
> >You're calling the thread->exit() so the return address is placed on the
> >stack.
> >
> 
> Of course. But I'm using MIPS, and it doesn't automatically place
> the return address on the stack.  The call to exit() could be
> performed from "asm" macro, without saving the return address.
> Thread never returns from thread->exit(), so return address is not
> needed any more.  However, this problem can also be solved by
> temporarily switching the stack of the thread (with some simple
> synchronization) to universal "pre-exit stack", which would resolve
> this and the above (cleaning stacks) issue as well. This would be,
> of course, platform dependent, but still simple.
>

Again, this seems like a very fragile mechanism. Another design
feature of eCos is that all code (except the initial HAL startup) runs
in the context of a valid thread. Executing code in this proposed
twilight zone would raise all sorts of problems throughout the rest of
the kernel and other subsystems.

In any case we already have other stacks available to us for this
purpose, they belong to other threads, so why not use them?


> >You can create a wrapper around the 'thread' object and modify "exit"
> >function.
> >
> 
> Yes, that's the other possibility.
> 
> >The "garbage collector" could be included inside the "idle" thread.
> >
> >
> 
> Well, this is nice one. Why "idle" should idle, when it can be useful? :-)

One reason for not doing anything in the idle thread is that the
scheduler relies on the idle thread to always be executable. If the
idle thread is doing anything that would require it to synchronize
with other threads, then it might have to sleep. This would seriously
complicate the scheduler.


-- 
Nick Garnett                    eCos Kernel Architect
http://www.ecoscentric.com      The eCos and RedBoot experts


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

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


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