Index: trunk/kernel/kern/thread.c
===================================================================
--- trunk/kernel/kern/thread.c	(revision 407)
+++ trunk/kernel/kern/thread.c	(revision 408)
@@ -116,5 +116,4 @@
 // - thread_user_fork()
 // - thread_kernel_create()
-// - thread_user_init()
 /////////////////////////////////////////////////////////////////////////////////////
 // @ thread       : pointer on thread descriptor
@@ -200,4 +199,7 @@
 	thread->signature = THREAD_SIGNATURE;
 
+    // FIXME call hal_thread_init() function to initialise the save_sr field
+    thread->save_sr = 0xFF13;
+
     // update local DQDT
     dqdt_local_update_threads( 1 );
@@ -322,4 +324,7 @@
     }
 
+	// update DQDT for new thread 
+    dqdt_local_update_threads( 1 );
+
 thread_dmsg("\n[DBG] %s : core[%x,%d] exit / trdid = %x / process %x / core = %d\n",
 __FUNCTION__, local_cxy, CURRENT_THREAD->core->lid,
@@ -331,78 +336,169 @@
 }  // 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 thread_user_fork( xptr_t      parent_thread_xp,
+                          process_t * child_process,
+                          thread_t ** child_thread )
 {
     error_t        error;
-	thread_t     * child;       // pointer on new thread descriptor
-    lid_t          core_lid;     // selected core local index
-
-thread_dmsg("\n[DBG] %s : core[%x,%d] enters\n",
-__FUNCTION__ , local_cxy , core_lid );
+	thread_t     * child_ptr;        // local pointer on local child thread
+    lid_t          core_lid;         // selected core local index
+
+    thread_t     * parent_ptr;       // local pointer on remote parent thread
+    cxy_t          parent_cxy;       // parent thread cluster
+    process_t    * parent_process;   // local pointer on parent process
+    xptr_t         parent_gpt_xp;    // extended pointer on parent thread GPT
+
+    void         * func;             // parent thread entry_func
+    void         * args;             // parent thread entry_args
+    intptr_t       base;             // parent thread u_stack_base
+    uint32_t       size;             // parent thread u_stack_size
+    uint32_t       flags;            // parent_thread flags
+    vpn_t          vpn_base;         // parent thread stack vpn_base
+    vpn_t          vpn_size;         // parent thread stack vpn_size
+    reg_t        * uzone;            // parent thread pointer on uzone  
+
+    vseg_t       * vseg;             // child thread STACK vseg
+
+thread_dmsg("\n[DBG] %s : core[%x,%d] enters at cycle %d\n",
+__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , hal_get_cycles() );
 
     // select a target core in local cluster
     core_lid = cluster_select_local_core();
 
-    // get pointer on parent thread descriptor
-    thread_t * parent = CURRENT_THREAD;
-
-    // allocate memory for new thread descriptor
-    child = thread_alloc();
-
-    if( child == NULL )
+    // get cluster and local pointer on parent thread descriptor
+    parent_cxy = GET_CXY( parent_thread_xp );
+    parent_ptr = (thread_t *)GET_PTR( parent_thread_xp );
+
+    // get relevant fields from parent thread 
+    func  = (void *)  hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->entry_func   ) );
+    args  = (void *)  hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->entry_args   ) );
+    base  = (intptr_t)hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->u_stack_base ) );
+    size  = (uint32_t)hal_remote_lw ( XPTR( parent_cxy , &parent_ptr->u_stack_size ) );
+    flags =           hal_remote_lw ( XPTR( parent_cxy , &parent_ptr->flags        ) );
+    uzone = (reg_t *) hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->uzone        ) );
+
+    vpn_base = base >> CONFIG_PPM_PAGE_SHIFT;
+    vpn_size = size >> CONFIG_PPM_PAGE_SHIFT;
+
+    // get pointer on parent process in parent thread cluster
+    parent_process = (process_t *)hal_remote_lpt( XPTR( parent_cxy,
+                                                        &parent_ptr->process ) );
+ 
+    // get extended pointer on parent GPT in parent thread cluster
+    parent_gpt_xp = XPTR( parent_cxy , &parent_process->vmm.gpt );
+
+    // allocate memory for child thread descriptor
+    child_ptr = thread_alloc();
+    if( child_ptr == NULL )
     {
         printk("\n[ERROR] in %s : cannot allocate new thread\n", __FUNCTION__ );
-        return ENOMEM;
+        return -1;
     }
 
     // initialize thread descriptor
-    error = thread_init( child,
-                         process,
+    error = thread_init( child_ptr,
+                         child_process,
                          THREAD_USER,
-                         parent->entry_func,
-                         parent->entry_args,
+                         func,
+                         args,
                          core_lid,
-                         stack_base,
-                         stack_size );
-
+                         base,
+                         size );
     if( error )
     {
-	    printk("\n[ERROR] in %s : cannot initialize new thread\n", __FUNCTION__ );
-        thread_release( child );
+	    printk("\n[ERROR] in %s : cannot initialize child thread\n", __FUNCTION__ );
+        thread_release( child_ptr );
         return EINVAL;
     }
 
     // return child pointer
-    *new_thread = child;
-
-    // set DETACHED flag if required
-    if( parent->flags & THREAD_FLAG_DETACHED ) child->flags = THREAD_FLAG_DETACHED;
+    *child_thread = child_ptr;
+
+    // set detached flag if required
+    if( flags & THREAD_FLAG_DETACHED ) child_ptr->flags = THREAD_FLAG_DETACHED;
+
+    // update uzone pointer in child thread descriptor
+    child_ptr->uzone = (char *)((intptr_t)uzone +
+                                (intptr_t)child_ptr - 
+                                (intptr_t)parent_ptr );
+ 
 
     // allocate CPU context for child thread
-	if( hal_cpu_context_alloc( child ) )
+	if( hal_cpu_context_alloc( child_ptr ) )
     {
 	    printk("\n[ERROR] in %s : cannot allocate CPU context\n", __FUNCTION__ );
-        thread_release( child );
-        return ENOMEM;
+        thread_release( child_ptr );
+        return -1;
     }
 
     // allocate FPU context for child thread
-	if( hal_fpu_context_alloc( child ) )
+	if( hal_fpu_context_alloc( child_ptr ) )
     {
 	    printk("\n[ERROR] in %s : cannot allocate FPU context\n", __FUNCTION__ );
-        thread_release( child );
-        return ENOMEM;
-    }
-
-    // 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_release( child_ptr );
+        return -1;
+    }
+
+    // create and initialize STACK vseg 
+    vseg = vseg_alloc();
+    vseg_init( vseg,
+               VSEG_TYPE_STACK,
+               base,
+               size,
+               vpn_base,
+               vpn_size,
+               0, 0, XPTR_NULL,                         // not a file vseg
+               local_cxy );
+
+    // register STACK vseg in local child VSL
+    vseg_attach( &child_process->vmm , vseg );
+
+    // copy all valid STACK GPT entries   
+    vpn_t          vpn;
+    bool_t         mapped;
+    ppn_t          ppn;
+    for( vpn = vpn_base ; vpn < (vpn_base + vpn_size) ; vpn++ )
+    {
+        error = hal_gpt_pte_copy( &child_process->vmm.gpt,
+                                  parent_gpt_xp,
+                                  vpn,
+                                  true,                 // set cow
+                                  &ppn,
+                                  &mapped );
+        if( error )
+        {
+            vseg_detach( &child_process->vmm , vseg );
+            vseg_free( vseg );
+            thread_release( child_ptr );
+            printk("\n[ERROR] in %s : cannot update child GPT\n", __FUNCTION__ );
+            return -1;
+        }
+
+        // increment page descriptor fork_nr for the referenced page if mapped
+        if( mapped )
+        {
+            xptr_t   page_xp  = ppm_ppn2page( ppn );
+            cxy_t    page_cxy = GET_CXY( page_xp );
+            page_t * page_ptr = (page_t *)GET_PTR( page_xp );
+            hal_remote_atomic_add( XPTR( page_cxy , &page_ptr->fork_nr ) , 1 );
+
+thread_dmsg("\n[DBG] %s : core[%x,%d] copied PTE to child GPT : vpn %x\n",
+__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , vpn );
+
+        }
+    }
+
+    // set COW flag for STAK vseg in parent thread GPT 
+    hal_gpt_flip_cow( true,                               // set cow
+                      parent_gpt_xp,
+                      vpn_base,
+                      vpn_size );
+ 
+	// update DQDT for child thread 
+    dqdt_local_update_threads( 1 );
 
 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 );
+__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, child_ptr->trdid, child_process->pid );
 
 	return 0;
@@ -452,4 +548,7 @@
 	hal_cpu_context_create( thread );
 
+	// update DQDT for kernel thread 
+    dqdt_local_update_threads( 1 );
+
 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() );
@@ -511,11 +610,5 @@
 
     // update intrumentation values
-    uint32_t pgfaults = thread->info.pgfault_nr;
-    uint32_t u_errors = thread->info.u_err_nr;
-    uint32_t m_errors = thread->info.m_err_nr;
-
-	process->vmm.pgfault_nr += pgfaults;
-	process->vmm.u_err_nr   += u_errors;
-	process->vmm.m_err_nr   += m_errors;
+	process->vmm.pgfault_nr += thread->info.pgfault_nr;
 
     // release memory allocated for CPU context and FPU context
@@ -635,5 +728,5 @@
     {
         this->flags &= ~THREAD_FLAG_SCHED;
-        sched_yield();
+        sched_yield( "delayed scheduling" );
     }
 
@@ -697,5 +790,5 @@
 
     // deschedule
-    sched_yield();
+    sched_yield( "exit" );
     return 0;
 
@@ -721,4 +814,7 @@
     while( 1 )
     {
+        // unmask IRQs
+        hal_enable_irq( NULL );
+
         if( CONFIG_THREAD_IDLE_MODE_SLEEP ) // force core to low-power mode
         {
@@ -740,5 +836,5 @@
 
         // force scheduling at each iteration
-        sched_yield();
+        sched_yield( "idle" );
    }
 }  // end thread_idle()
@@ -754,11 +850,4 @@
 ///////////////////////////////////////////////////
 void thread_kernel_time_update( thread_t * thread )
-{
-    // TODO
-    // printk("\n[WARNING] function %s not implemented\n", __FUNCTION__ );
-}
-
-////////////////////////////////////////////////
-void thread_signals_handle( thread_t * thread )
 {
     // TODO
