Index: trunk/kernel/kern/thread.c
===================================================================
--- trunk/kernel/kern/thread.c	(revision 406)
+++ trunk/kernel/kern/thread.c	(revision 407)
@@ -57,5 +57,4 @@
     else if( type == THREAD_RPC    ) return "RPC";
     else if( type == THREAD_DEV    ) return "DEV";
-    else if( type == THREAD_KERNEL ) return "KER";
     else if( type == THREAD_IDLE   ) return "IDL";
     else                             return "undefined";
@@ -153,4 +152,7 @@
     }
 
+    // compute thread descriptor size without kernel stack
+    uint32_t desc_size = (intptr_t)(&thread->signature) - (intptr_t)thread + 4; 
+
 	// Initialize new thread descriptor
     thread->trdid           = trdid;
@@ -170,6 +172,6 @@
     thread->u_stack_base    = u_stack_base;
     thread->u_stack_size    = u_stack_size;
-    thread->k_stack_base    = (intptr_t)thread;
-    thread->k_stack_size    = CONFIG_THREAD_DESC_SIZE;
+    thread->k_stack_base    = (intptr_t)thread + desc_size;
+    thread->k_stack_size    = CONFIG_THREAD_DESC_SIZE - desc_size;
 
     thread->entry_func      = func;         // thread entry point
@@ -178,6 +180,6 @@
     thread->signals         = 0;            // no pending signal
     thread->errno           = 0;            // no error detected
-    thread->fork_user       = 0;            // no fork required
-    thread->fork_cxy        = 0;
+    thread->fork_user       = 0;            // no user defined placement for fork
+    thread->fork_cxy        = 0;            // user defined target cluster for fork
 
     // thread blocked
@@ -221,5 +223,5 @@
     vseg_t       * vseg;         // stack vseg
 
-    thread_dmsg("\n[DMSG] %s : enters for process %x\n", __FUNCTION__ , pid );
+    assert( (attr != NULL) , __FUNCTION__, "pthread attributes must be defined" );
 
     // get process descriptor local copy
@@ -234,18 +236,28 @@
 
     // select a target core in local cluster
-    if( attr->attributes & PT_ATTR_CORE_DEFINED ) core_lid = attr->lid;
-    else                                          core_lid = cluster_select_local_core();
-
-    // check core local index
-    if( core_lid >= LOCAL_CLUSTER->cores_nr )
-    {
-	    printk("\n[ERROR] in %s : illegal core index attribute = %d\n",
-               __FUNCTION__ , core_lid );
-
-        return EINVAL;
+    if( attr->attributes & PT_ATTR_CORE_DEFINED )
+    {
+        core_lid = attr->lid;
+        if( core_lid >= LOCAL_CLUSTER->cores_nr )
+        {
+	        printk("\n[ERROR] in %s : illegal core index attribute = %d\n",
+            __FUNCTION__ , core_lid );
+            return EINVAL;
+        }
+    }
+    else
+    {
+        core_lid = cluster_select_local_core();
     }
 
     // allocate a stack from local VMM
-    vseg = vmm_create_vseg( process, 0 , 0 , VSEG_TYPE_STACK );
+    vseg = vmm_create_vseg( process,
+                            VSEG_TYPE_STACK,
+                            0,                 // size unused
+                            0,                 // length unused
+                            0,                 // file_offset unused
+                            0,                 // file_size unused
+                            XPTR_NULL,         // mapper_xp unused
+                            local_cxy );
 
     if( vseg == NULL )
@@ -287,10 +299,11 @@
 
     // set DETACHED flag if required
-    if( attr->attributes & PT_ATTR_DETACH ) thread->flags |= THREAD_FLAG_DETACHED;
+    if( attr->attributes & PT_ATTR_DETACH ) 
+    {
+        thread->flags |= THREAD_FLAG_DETACHED;
+    }
 
     // allocate & initialize CPU context
-	error = hal_cpu_context_create( thread );
-
-    if( error )
+	if( hal_cpu_context_create( thread ) )
     {
 	    printk("\n[ERROR] in %s : cannot create CPU context\n", __FUNCTION__ );
@@ -300,8 +313,6 @@
     }
 
-    // allocate & initialize FPU context
-    error = hal_fpu_context_create( thread );
-
-    if( error )
+    // allocate  FPU context
+    if( hal_fpu_context_alloc( thread ) )
     {
 	    printk("\n[ERROR] in %s : cannot create FPU context\n", __FUNCTION__ );
@@ -311,6 +322,7 @@
     }
 
-    thread_dmsg("\n[DMSG] %s : exit / trdid = %x / process %x / core = %d\n",
-                __FUNCTION__ , thread->trdid , process->pid , core_lid );
+thread_dmsg("\n[DBG] %s : core[%x,%d] exit / trdid = %x / process %x / core = %d\n",
+__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid,
+thread->trdid , process->pid , core_lid );
 
     *new_thread = thread;
@@ -319,87 +331,79 @@
 }  // end thread_user_create()
 
-//////////////////////////////////////////////
+////////////////////////////////////////////////////
 error_t thread_user_fork( process_t * process,
+                          intptr_t    stack_base,
+                          uint32_t    stack_size,
                           thread_t ** new_thread )
 {
     error_t        error;
-	thread_t     * thread;       // pointer on new thread descriptor
+	thread_t     * child;       // pointer on new thread descriptor
     lid_t          core_lid;     // selected core local index
-	vseg_t       * vseg;         // stack vseg
-
-    thread_dmsg("\n[DMSG] %s : enters\n", __FUNCTION__ );
-
-    // allocate a stack from local VMM
-    vseg = vmm_create_vseg( process, 0 , 0 , VSEG_TYPE_STACK );
-
-    if( vseg == NULL )
-    {
-	    printk("\n[ERROR] in %s : cannot create stack vseg\n", __FUNCTION__ );
-		return ENOMEM;
-    }
+
+thread_dmsg("\n[DBG] %s : core[%x,%d] enters\n",
+__FUNCTION__ , local_cxy , core_lid );
 
     // select a target core in local cluster
     core_lid = cluster_select_local_core();
 
-    // get pointer on calling thread descriptor
-    thread_t * this = CURRENT_THREAD;
+    // get pointer on parent thread descriptor
+    thread_t * parent = CURRENT_THREAD;
 
     // allocate memory for new thread descriptor
-    thread = thread_alloc();
-
-    if( thread == NULL )
+    child = thread_alloc();
+
+    if( child == NULL )
     {
         printk("\n[ERROR] in %s : cannot allocate new thread\n", __FUNCTION__ );
-        vmm_remove_vseg( vseg );
         return ENOMEM;
     }
 
     // initialize thread descriptor
-    error = thread_init( thread,
+    error = thread_init( child,
                          process,
                          THREAD_USER,
-                         this->entry_func,
-                         this->entry_args,
+                         parent->entry_func,
+                         parent->entry_args,
                          core_lid,
-                         vseg->min,
-                         vseg->max - vseg->min );
+                         stack_base,
+                         stack_size );
 
     if( error )
     {
 	    printk("\n[ERROR] in %s : cannot initialize new thread\n", __FUNCTION__ );
-        vmm_remove_vseg( vseg );
-        thread_release( thread );
+        thread_release( child );
         return EINVAL;
     }
 
-    // set ATTACHED flag if set in this thread
-    if( this->flags & THREAD_FLAG_DETACHED ) thread->flags = THREAD_FLAG_DETACHED;
-
-    // allocate & initialize CPU context from calling thread
-	error = hal_cpu_context_copy( thread , this );
-
-    if( error )
-    {
-	    printk("\n[ERROR] in %s : cannot create CPU context\n", __FUNCTION__ );
-        vmm_remove_vseg( vseg );
-        thread_release( thread );
+    // return child pointer
+    *new_thread = child;
+
+    // set DETACHED flag if required
+    if( parent->flags & THREAD_FLAG_DETACHED ) child->flags = THREAD_FLAG_DETACHED;
+
+    // allocate CPU context for child thread
+	if( hal_cpu_context_alloc( child ) )
+    {
+	    printk("\n[ERROR] in %s : cannot allocate CPU context\n", __FUNCTION__ );
+        thread_release( child );
         return ENOMEM;
     }
 
-    // allocate & initialize FPU context from calling thread
-	error = hal_fpu_context_copy( thread , this );
-
-    if( error )
-    {
-	    printk("\n[ERROR] in %s : cannot create CPU context\n", __FUNCTION__ );
-        vmm_remove_vseg( vseg );
-        thread_release( thread );
+    // allocate FPU context for child thread
+	if( hal_fpu_context_alloc( child ) )
+    {
+	    printk("\n[ERROR] in %s : cannot allocate FPU context\n", __FUNCTION__ );
+        thread_release( child );
         return ENOMEM;
     }
 
-    thread_dmsg("\n[DMSG] %s : exit / thread %x for process %x on core %d in cluster %x\n",
-                 __FUNCTION__, thread->trdid, process->pid, core_lid, local_cxy );
-
-    *new_thread = thread;
+    // copy kernel stack content from parent to child thread descriptor
+    void * dst = (void *)(&child->signature) + 4;
+    void * src = (void *)(&parent->signature) + 4;
+    memcpy( dst , src , parent->k_stack_size );
+
+thread_dmsg("\n[DBG] %s : core[%x,%d] exit / created main thread %x for process %x\n",
+__FUNCTION__, local_cxy , core_lid , child->trdid , process->pid );
+
 	return 0;
 
@@ -416,10 +420,9 @@
 	thread_t     * thread;       // pointer on new thread descriptor
 
-    thread_dmsg("\n[DMSG] %s : enter / for type %s on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , thread_type_str( type ) , local_cxy , core_lid , hal_time_stamp() );
-
-    assert( ( (type == THREAD_KERNEL) || (type == THREAD_RPC) ||
-              (type == THREAD_IDLE)   || (type == THREAD_DEV) ) ,
-              __FUNCTION__ , "illegal thread type" );
+thread_dmsg("\n[DBG] %s : core[%x,%d] enters / type % / cycle %d\n",
+__FUNCTION__ , local_cxy , core_lid , thread_type_str( type ) , hal_time_stamp() );
+
+    assert( ( (type == THREAD_IDLE) || (type == THREAD_RPC) || (type == THREAD_DEV) ) ,
+    __FUNCTION__ , "illegal thread type" );
 
     assert( (core_lid < LOCAL_CLUSTER->cores_nr) ,
@@ -449,7 +452,6 @@
 	hal_cpu_context_create( thread );
 
-    thread_dmsg("\n[DMSG] %s : exit / trdid = %x / type = %s / core = [%x,%d] / cycle %d\n",
-    __FUNCTION__ , thread->trdid , thread_type_str(type) , 
-    local_cxy , core_lid , hal_time_stamp() );
+thread_dmsg("\n[DBG] %s : core = [%x,%d] exit / trdid = %x / type %s / cycle %d\n",
+__FUNCTION__, local_cxy, core_lid, thread->trdid, thread_type_str(type), hal_time_stamp() );
 
     *new_thread = thread;
@@ -465,13 +467,7 @@
 				            lid_t           core_lid )
 {
-    assert( ( (type == THREAD_KERNEL) || (type == THREAD_RPC) ||
-              (type == THREAD_IDLE)   || (type == THREAD_DEV) ) ,
-              __FUNCTION__ , "illegal thread type" );
-
-    if( core_lid >= LOCAL_CLUSTER->cores_nr )
-    {
-        panic("illegal core_lid / cores = %d / lid = %d / cxy = %x",
-              LOCAL_CLUSTER->cores_nr , core_lid , local_cxy );
-    }
+    assert( (type == THREAD_IDLE) , __FUNCTION__ , "illegal thread type" );
+
+    assert( (core_lid < LOCAL_CLUSTER->cores_nr) , __FUNCTION__ , "illegal core index" );
 
     error_t  error = thread_init( thread,
@@ -487,5 +483,6 @@
 
     return error;
-}
+
+}  // end thread_kernel_init()
 
 ///////////////////////////////////////////////////////////////////////////////////////
@@ -502,5 +499,5 @@
     core_t     * core       = thread->core;
 
-    thread_dmsg("\n[DMSG] %s : enters for thread %x in process %x / type = %s\n",
+    thread_dmsg("\n[DBG] %s : enters for thread %x in process %x / type = %s\n",
                 __FUNCTION__ , thread->trdid , process->pid , thread_type_str( thread->type ) );
 
@@ -556,7 +553,8 @@
 	tm_end = hal_get_cycles();
 
-	thread_dmsg("\n[DMSG] %s : exit for thread %x in process %x / duration = %d\n",
+	thread_dmsg("\n[DBG] %s : exit for thread %x in process %x / duration = %d\n",
 	               __FUNCTION__, thread->trdid , process->pid , tm_end - tm_start );
-}
+
+}   // end thread_destroy()
 
 /////////////////////////////////////////////////
@@ -609,4 +607,5 @@
 {
     hal_atomic_or( &thread->signals , mask );
+    hal_fence();
 }
 
@@ -616,19 +615,5 @@
 {
     hal_atomic_and( &thread->signals , ~mask );
-}
-
-//////////////////////////////////
-inline bool_t thread_is_joinable()
-{
-    thread_t * this = CURRENT_THREAD;
-    return( (this->brothers_list.next != XPTR_NULL) &&
-            (this->brothers_list.pred != XPTR_NULL) );
-}
-
-//////////////////////////////////
-inline bool_t thread_is_runnable()
-{
-    thread_t * this = CURRENT_THREAD;
-    return( this->blocked == 0 );
+    hal_fence();
 }
 
@@ -650,7 +635,35 @@
     {
         this->flags &= ~THREAD_FLAG_SCHED;
-        sched_yield( NULL );
-    }
-}
+        sched_yield();
+    }
+
+}  // end thread_check_sched()
+
+/////////////////////////////////////
+void thread_block( thread_t * thread,
+                   uint32_t   cause )
+{
+    // set blocking cause
+    hal_atomic_or( &thread->blocked , cause );
+    hal_fence();
+
+} // end thread_block()
+
+/////////////////////////////////////////
+uint32_t thread_unblock( xptr_t   thread,
+                         uint32_t cause )
+{
+    // get thread cluster and local pointer
+    cxy_t      cxy = GET_CXY( thread );
+    thread_t * ptr = (thread_t *)GET_PTR( thread );
+
+    // reset blocking cause
+    uint32_t previous = hal_remote_atomic_and( XPTR( cxy , &ptr->blocked ) , ~cause );
+    hal_fence();
+
+    // return a non zero value if the cause bit is modified 
+    return( previous & cause );
+
+}  // end thread_unblock()
 
 /////////////////////
@@ -664,8 +677,6 @@
 	if( !thread_can_yield() )
 	{
-        printk("ERROR in %s : thread %x in process %x on core %d in cluster %x\n"
-               " did not released all locks\n",
-               __FUNCTION__ , this->trdid , this->process->pid ,
-               CURRENT_CORE->lid , local_cxy );
+        printk("ERROR in %s : locks not released for thread %x in process %x on core[%x,%d]\n",
+        __FUNCTION__, this->trdid, this->process->pid, local_cxy, this->core->lid );
         return EINVAL;
     }
@@ -686,27 +697,8 @@
 
     // deschedule
-    sched_yield( NULL );
+    sched_yield();
     return 0;
-}
-
-/////////////////////////////////////
-void thread_block( thread_t * thread,
-                   uint32_t   cause )
-{
-    // set blocking cause
-    hal_atomic_or( &thread->blocked , cause );
-}
-
-////////////////////////////////////
-void thread_unblock( xptr_t   thread,
-                    uint32_t cause )
-{
-    // get thread cluster and local pointer
-    cxy_t      cxy = GET_CXY( thread );
-    thread_t * ptr = (thread_t *)GET_PTR( thread );
-
-    // reset blocking cause
-    hal_remote_atomic_and( XPTR( cxy , &ptr->blocked ) , ~cause );
-}
+
+}  // end thread_exit()
 
 /////////////////////////////////////
@@ -721,28 +713,35 @@
     // send an IPI to schedule the target thread core.
     dev_pic_send_ipi( local_cxy , target->core->lid );
-}
+
+}  // end thread_kill()
 
 ///////////////////////
 void thread_idle_func()
 {
-#if CONFIG_IDLE_DEBUG
-    lid_t  lid = CURRENT_CORE->lid;
-#endif
-
     while( 1 )
     {
-        idle_dmsg("\n[DMSG] %s : core[%x][%d] goes to sleep at cycle %d\n",
-                    __FUNCTION__ , local_cxy , lid , hal_get_cycles() );
-
-        // force core to sleeping state
-        //hal_core_sleep();
-
-        idle_dmsg("\n[DMSG] %s : core[%x][%d] wake up at cycle %d\n",
-                    __FUNCTION__ , local_cxy , lid , hal_get_cycles() );
-
-        // force scheduling
-        sched_yield( NULL );
+        if( CONFIG_THREAD_IDLE_MODE_SLEEP ) // force core to low-power mode
+        {
+
+idle_dmsg("\n[DBG] %s : core[%x][%d] goes to sleep at cycle %d\n",
+__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , hal_get_cycles() );
+
+            hal_core_sleep();
+
+idle_dmsg("\n[DBG] %s : core[%x][%d] wake up at cycle %d\n",
+__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , hal_get_cycles() );
+
+        }
+        else                                // yield each ~ 100000 cycles
+
+        {
+             hal_fixed_delay( 500000 );
+        }
+
+        // force scheduling at each iteration
+        sched_yield();
    }
-}
+}  // end thread_idle()
+
 
 /////////////////////////////////////////////////
