Index: trunk/kernel/kern/process.c
===================================================================
--- trunk/kernel/kern/process.c	(revision 407)
+++ trunk/kernel/kern/process.c	(revision 408)
@@ -82,13 +82,36 @@
 }
 
+/////////////////////////////////////////////
+void process_zero_init( process_t * process )
+{
+    // initialize PID, PPID anf PREF
+    process->pid    = 0;
+    process->ppid   = 0;
+    process->ref_xp = XPTR( local_cxy , process );
+
+    // reset th_tbl[] array as empty
+    uint32_t i;
+    for( i = 0 ; i < CONFIG_THREAD_MAX_PER_CLUSTER ; i++ )
+	{
+        process->th_tbl[i] = NULL;
+    }
+    process->th_nr  = 0;
+    spinlock_init( &process->th_lock );
+
+	hal_fence();
+
+process_dmsg("\n[DBG] %s : core[%x,%d] exit for process %x\n",
+__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , process->pid );
+
+}  // end process_zero_init()
+
 /////////////////////////////////////////////////
 void process_reference_init( process_t * process,
                              pid_t       pid,
-                             xptr_t      parent_xp )
-{
-    cxy_t       parent_cxy;
-    process_t * parent_ptr;
-    pid_t       parent_pid;
-
+                             pid_t       ppid,
+                             xptr_t      model_xp )
+{
+    cxy_t       model_cxy;
+    process_t * model_ptr;
 	error_t     error1;
 	error_t     error2;
@@ -104,121 +127,117 @@
 __FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
 
-    // get parent process cluster, local pointer, and pid
-    // for all processes other than kernel process
-    if( process == &process_zero )                   // kernel process
-    {
-        assert( (pid == 0) , __FUNCTION__ , "process_zero must have PID = 0\n");
-
-        parent_cxy = 0;
-        parent_ptr = NULL;
-        parent_pid = 0;      
-    }
-    else                                             // user process
-    {
-        parent_cxy = GET_CXY( parent_xp );
-        parent_ptr = (process_t *)GET_PTR( parent_xp );
-        parent_pid = hal_remote_lw( XPTR( parent_cxy , &parent_ptr->pid ) );
-    }
+    // get model process cluster and local pointer
+    model_cxy = GET_CXY( model_xp );
+    model_ptr = (process_t *)GET_PTR( model_xp );
 
     // initialize PID, PPID, and REF
 	process->pid    = pid;
-    process->ppid   = parent_pid;
+    process->ppid   = ppid;
     process->ref_xp = XPTR( local_cxy , process );
 
-    // initialize vmm, fd array and others structures for user processes.
-    // These structures are not used by the kernel process.
-    if( pid )
-    {
-        // initialize vmm (not for kernel)
-        vmm_init( process );
-
-process_dmsg("\n[DBG] %s : core[%x,%d] / vmm initialised for process %x\n", 
+    // initialize vmm 
+    vmm_init( process );
+
+process_dmsg("\n[DBG] %s : core[%x,%d] / vmm empty for process %x\n", 
 __FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
 
-        // initialize fd_array (not for kernel)
-        process_fd_init( process );
-
-        // create stdin / stdout / stderr pseudo-files (not for kernel)
-        if( parent_pid == 0 )                                              // process_init
-        {
-            error1 = vfs_open( process,
-                               CONFIG_INIT_STDIN,
-                               O_RDONLY, 
-                               0,                // FIXME chmod
-                               &stdin_xp, 
-                               &stdin_id );
-
-            error2 = vfs_open( process,
-                               CONFIG_INIT_STDOUT,
-                               O_WRONLY, 
-                               0,                // FIXME chmod
-                               &stdout_xp, 
-                               &stdout_id );
-
-            error3 = vfs_open( process,
-                               CONFIG_INIT_STDERR,
-                               O_WRONLY, 
-                               0,                // FIXME chmod
-                               &stderr_xp, 
-                               &stderr_id );
-        }
-        else                                                               // user process
-        {
-            error1 = vfs_open( process,
-                               CONFIG_USER_STDIN,
-                               O_RDONLY, 
-                               0,                // FIXME chmod
-                               &stdin_xp, 
-                               &stdin_id );
-
-            error2 = vfs_open( process,
-                               CONFIG_USER_STDOUT,
-                               O_WRONLY, 
-                               0,                // FIXME chmod
-                               &stdout_xp, 
-                               &stdout_id );
-
-            error3 = vfs_open( process,
-                               CONFIG_USER_STDERR,
-                               O_WRONLY, 
-                               0,                // FIXME chmod
-                               &stderr_xp, 
-                               &stderr_id );
-        }
-
-        assert( ((error1 == 0) && (error2 == 0) && (error3 == 0)) , __FUNCTION__ ,
-        "cannot open stdin/stdout/stderr pseudo files\n");
-
-        assert( ((stdin_id == 0) && (stdout_id == 1) && (stderr_id == 2)) , __FUNCTION__ ,
-        "bad indexes : stdin %d / stdout %d / stderr %d \n", stdin_id , stdout_id , stderr_id );
+    // initialize fd_array (not for kernel)
+    process_fd_init( process );
+
+    // create stdin / stdout / stderr pseudo-files
+    if( ppid == 0 )                                        // process_init
+    {
+        error1 = vfs_open( process,
+                           CONFIG_INIT_STDIN,
+                           O_RDONLY, 
+                           0,                // FIXME chmod
+                           &stdin_xp, 
+                           &stdin_id );
+
+        error2 = vfs_open( process,
+                           CONFIG_INIT_STDOUT,
+                           O_WRONLY, 
+                           0,                // FIXME chmod
+                           &stdout_xp, 
+                           &stdout_id );
+
+        error3 = vfs_open( process,
+                           CONFIG_INIT_STDERR,
+                           O_WRONLY, 
+                           0,                // FIXME chmod
+                           &stderr_xp, 
+                           &stderr_id );
+    }
+    else                                                  // other user process
+    {
+        error1 = vfs_open( process,
+                           CONFIG_USER_STDIN,
+                           O_RDONLY, 
+                           0,                // FIXME chmod
+                           &stdin_xp, 
+                           &stdin_id );
+
+        error2 = vfs_open( process,
+                           CONFIG_USER_STDOUT,
+                           O_WRONLY, 
+                           0,                // FIXME chmod
+                           &stdout_xp, 
+                           &stdout_id );
+
+        error3 = vfs_open( process,
+                           CONFIG_USER_STDERR,
+                           O_WRONLY, 
+                           0,                // FIXME chmod
+                           &stderr_xp, 
+                           &stderr_id );
+    }
+
+    assert( ((error1 == 0) && (error2 == 0) && (error3 == 0)) , __FUNCTION__ ,
+    "cannot open stdin/stdout/stderr pseudo files\n");
+
+    assert( ((stdin_id == 0) && (stdout_id == 1) && (stderr_id == 2)) , __FUNCTION__ ,
+    "bad indexes : stdin %d / stdout %d / stderr %d \n", stdin_id , stdout_id , stderr_id );
+
+    // initialize specific files, cwd_lock, and fd_array
+    process->vfs_root_xp = (xptr_t)hal_remote_lwd( XPTR( model_cxy,
+                                                         &model_ptr->vfs_root_xp ) );
+    process->vfs_cwd_xp  = (xptr_t)hal_remote_lwd( XPTR( model_cxy,
+                                                         &model_ptr->vfs_cwd_xp ) );
+    process->vfs_bin_xp  = (xptr_t)hal_remote_lwd( XPTR( model_cxy,
+                                                         &model_ptr->vfs_bin_xp ) );
+    vfs_file_count_up( process->vfs_root_xp );
+    vfs_file_count_up( process->vfs_cwd_xp );
+    vfs_file_count_up( process->vfs_bin_xp );
+
+    process_fd_remote_copy( XPTR( local_cxy , &process->fd_array ),
+                            XPTR( model_cxy , &model_ptr->fd_array ) );
+
+    remote_rwlock_init( XPTR( local_cxy , &process->cwd_lock ) );
 
 process_dmsg("\n[DBG] %s : core[%x,%d] / fd array initialised for process %x\n", 
 __FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
 
-
-        // reset reference process files structures and cwd_lock (not for kernel)
-	    process->vfs_root_xp     = XPTR_NULL;
-	    process->vfs_bin_xp      = XPTR_NULL;
-	    process->vfs_cwd_xp      = XPTR_NULL;
-        remote_rwlock_init( XPTR( local_cxy , &process->cwd_lock ) );
-
-        // reset children list root (not for kernel)
-        xlist_root_init( XPTR( local_cxy , &process->children_root ) );
-	    process->children_nr     = 0;
-
-        // reset semaphore / mutex / barrier / condvar list roots (nor for kernel)
-        xlist_root_init( XPTR( local_cxy , &process->sem_root ) );
-        xlist_root_init( XPTR( local_cxy , &process->mutex_root ) );
-        xlist_root_init( XPTR( local_cxy , &process->barrier_root ) );
-        xlist_root_init( XPTR( local_cxy , &process->condvar_root ) );
-        remote_spinlock_init( XPTR( local_cxy , &process->sync_lock ) );
-
-        // register new process in the parent children list (nor for kernel)
-        xptr_t entry = XPTR( local_cxy  , &process->brothers_list );
-        xptr_t root  = XPTR( parent_cxy , &parent_ptr->children_root );
-        xlist_add_first( root , entry );
-    }
-
-    // reset th_tbl[] array as empty
+    // reset children list root 
+    xlist_root_init( XPTR( local_cxy , &process->children_root ) );
+    process->children_nr     = 0;
+
+    // reset semaphore / mutex / barrier / condvar list roots 
+    xlist_root_init( XPTR( local_cxy , &process->sem_root ) );
+    xlist_root_init( XPTR( local_cxy , &process->mutex_root ) );
+    xlist_root_init( XPTR( local_cxy , &process->barrier_root ) );
+    xlist_root_init( XPTR( local_cxy , &process->condvar_root ) );
+    remote_spinlock_init( XPTR( local_cxy , &process->sync_lock ) );
+
+    // register new process in the local cluster manager pref_tbl[]
+    lpid_t lpid = LPID_FROM_PID( pid );
+    LOCAL_CLUSTER->pmgr.pref_tbl[lpid] = XPTR( local_cxy , process );
+
+    // register new process descriptor in local cluster manager local_list
+    cluster_process_local_link( process );
+
+    // register new process descriptor in local cluster manager copies_list 
+    cluster_process_copies_link( process );
+
+    // reset th_tbl[] array as empty in process descriptor
     uint32_t i;
     for( i = 0 ; i < CONFIG_THREAD_MAX_PER_CLUSTER ; i++ )
@@ -228,12 +247,4 @@
     process->th_nr  = 0;
     spinlock_init( &process->th_lock );
-
-    // register new process descriptor in local cluster manager local_list
-    cluster_process_local_link( process );
-
-    // register new process descriptor in owner cluster manager copies_list
-    cluster_process_copies_link( process );
-
-    // initialize signal manager TODO [AG]
 
 	hal_fence();
@@ -370,5 +381,5 @@
     uint32_t       count;     // thread counter
 
-printk("\n@@@ %s enter\n", __FUNCTION__ );
+printk("\n[@@@] %s enter\n", __FUNCTION__ );
 
     // get lock protecting th_tbl[]
@@ -390,5 +401,5 @@
     }
 
-printk("\n@@@ %s : %d signal(s) sent\n", __FUNCTION__, count );
+printk("\n[@@@] %s : %d signal(s) sent\n", __FUNCTION__, count );
 
     // second loop on threads to wait acknowledge from scheduler,
@@ -403,10 +414,10 @@
         {
 
-printk("\n@@@ %s start polling at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
+printk("\n[@@@] %s start polling at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
 
             // poll the THREAD_SIG_KILL bit until reset
             while( thread->signals & THREAD_SIG_KILL ) asm volatile( "nop" );
 
-printk("\n@@@ %s exit polling\n", __FUNCTION__ );
+printk("\n[@@@] %s exit polling\n", __FUNCTION__ );
 
             // detach target thread from parent if attached
@@ -424,5 +435,5 @@
     }
 
-printk("\n@@@ %s : %d ack(s) received\n", __FUNCTION__, count );
+printk("\n[@@@] %s : %d ack(s) received\n", __FUNCTION__, count );
 
     // release lock protecting th_tbl[]
@@ -432,5 +443,5 @@
     process_destroy( process );
 
-printk("\n[@@@] %s : core[%x,%d] exit\n",
+printk("\n[DBG] %s : core[%x,%d] exit\n",
 __FUNCTION__, local_cxy, CURRENT_THREAD->core->lid );
 
@@ -688,92 +699,186 @@
 }  // process_remove_thread()
 
+/////////////////////////////////////////////////////////
+error_t process_make_fork( xptr_t      parent_process_xp,
+                           xptr_t      parent_thread_xp,
+                           pid_t     * child_pid,
+                           thread_t ** child_thread )
+{
+    process_t * process;         // local pointer on child process descriptor
+    thread_t  * thread;          // local pointer on child thread descriptor
+    pid_t       new_pid;         // process identifier for child process
+    pid_t       parent_pid;      // process identifier for parent process
+    xptr_t      ref_xp;          // extended pointer on reference process
+    error_t     error;
+
+    // get cluster and local pointer for parent process
+    cxy_t       parent_process_cxy = GET_CXY( parent_process_xp );
+    process_t * parent_process_ptr = (process_t *)GET_PTR( parent_process_xp );
+
+    // get parent process PID
+    parent_pid = hal_remote_lw( XPTR( parent_process_cxy , &parent_process_ptr->pid ) );
+    
+    // check parent process is the reference
+    ref_xp = hal_remote_lwd( XPTR( parent_process_cxy , &parent_process_ptr->ref_xp ) );
+    assert( (parent_process_xp == ref_xp ) , __FUNCTION__ ,
+    "parent process must be the reference process\n" );
+
+process_dmsg("\n[DBG] %s : core[%x,%d] enter at cycle %d\n",
+__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid , hal_get_cycles() );
+
+    // allocate a process descriptor
+    process = process_alloc();
+    if( process == NULL )
+    {
+        printk("\n[ERROR] in %s : cannot get process in cluster %x\n", 
+        __FUNCTION__, local_cxy ); 
+        return -1;
+    }
+
+process_dmsg("\n[DBG] %s : core[%x,%d] child process descriptor allocated at cycle %d\n",
+ __FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, hal_get_cycles() );
+
+    // allocate a child PID from local cluster
+    error = cluster_pid_alloc( XPTR( local_cxy , process ) , &new_pid );
+    if( (error != 0) || (new_pid == 0) )
+    {
+        printk("\n[ERROR] in %s : cannot get PID in cluster %x\n", 
+        __FUNCTION__, local_cxy ); 
+        process_free( process );
+        return -1;
+    }
+
+process_dmsg("\n[DBG] %s : core[%x, %d] child process PID allocated = %x at cycle %d\n",
+ __FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, new_pid , hal_get_cycles() );
+
+    // initializes child process descriptor from parent process descriptor 
+    process_reference_init( process,
+                            new_pid,
+                            parent_pid,
+                            parent_process_xp );
+
+process_dmsg("\n[DBG] %s : core[%x, %d] child process initialised at cycle %d\n",
+__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, hal_get_cycles() );
+
+    // copy VMM from parent descriptor to child descriptor
+    error = vmm_fork_copy( process,
+                           parent_process_xp );
+    if( error )
+    {
+        printk("\n[ERROR] in %s : cannot copy VMM in cluster %x\n", 
+        __FUNCTION__, local_cxy ); 
+        process_free( process );
+        cluster_pid_release( new_pid );
+        return -1;
+    }
+
+process_dmsg("\n[DBG] %s : core[%x, %d] child process VMM copied at cycle %d\n",
+__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, hal_get_cycles() );
+
+    // create child thread descriptor from parent thread descriptor
+    error = thread_user_fork( parent_thread_xp,
+                              process,
+                              &thread );
+    if( error )
+    {
+        printk("\n[ERROR] in %s : cannot create thread in cluster %x\n",
+        __FUNCTION__, local_cxy ); 
+        process_free( process );
+        cluster_pid_release( new_pid );
+        return -1;
+    }
+
+process_dmsg("\n[DBG] %s : core[%x,%d] child thread created at cycle %d\n", 
+__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, hal_get_cycles() );
+
+    // update parent process GPT to set Copy_On_Write for shared data vsegs 
+    // this includes all replicated GPT copies
+    if( parent_process_cxy == local_cxy )   // reference is local
+    {
+        vmm_set_cow( parent_process_ptr );
+    }
+    else                                    // reference is remote
+    {
+        rpc_vmm_set_cow_client( parent_process_cxy,
+                                parent_process_ptr );
+    }
+
+process_dmsg("\n[DBG] %s : core[%x,%d] COW set in parent_process at cycle %d\n",
+__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, hal_get_cycles() );
+
+    // update children list in parent process
+	xlist_add_last( XPTR( parent_process_cxy , &parent_process_ptr->children_root ),
+                    XPTR( local_cxy , &process->brothers_list ) );
+	hal_remote_atomic_add( XPTR( parent_process_cxy,
+                                 &parent_process_ptr->children_nr), 1 );
+
+// vmm_display( process , true );
+// vmm_display( parent_process_ptr , true );
+// sched_display( 0 );
+
+    // return success
+    *child_thread = thread;
+    *child_pid    = new_pid;
+
+    return 0;
+
+}  // end process_make_fork()
+
 /////////////////////////////////////////////////////
 error_t process_make_exec( exec_info_t  * exec_info )
 {
-    char           * path;                            // pathname to .elf file
-    bool_t           keep_pid;                        // new process keep parent PID if true
-    process_t      * process;                         // local pointer on new process
-    pid_t            pid;                             // new process pid
-    xptr_t           parent_xp;                       // extended pointer on parent process
-    cxy_t            parent_cxy;                      // parent process local cluster
-    process_t      * parent_ptr;                      // local pointer on parent process
-    uint32_t         parent_pid;                      // parent process identifier
-    thread_t       * thread;                          // pointer on new thread
-    pthread_attr_t   attr;                            // main thread attributes
-    core_t         * core;                            // pointer on selected core
-    lid_t            lid;                             // selected core local index
+    char           * path;                    // pathname to .elf file
+    process_t      * old;                     // local pointer on old process
+    process_t      * new;                     // local pointer on new process
+    pid_t            pid;                     // old process identifier
+    thread_t       * thread;                  // pointer on new thread
+    pthread_attr_t   attr;                    // main thread attributes
+    lid_t            lid;                     // selected core local index
 	error_t          error;
 
-	// get .elf pathname, parent_xp, and keep_pid flag from exec_info
-	path      = exec_info->path;
-    parent_xp = exec_info->parent_xp;
-    keep_pid  = exec_info->keep_pid;
-
-process_dmsg("\n[DBG] %s : core[%x,%d] enters for path = %s\n",
-__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path );
-
-    // get parent process cluster and local pointer
-    parent_cxy = GET_CXY( parent_xp );
-    parent_ptr = (process_t *)GET_PTR( parent_xp );
-    parent_pid = hal_remote_lw( XPTR( parent_cxy , &parent_ptr->pid ) );
-
-    // allocates memory for process descriptor 
-	process = process_alloc(); 
-	if( process == NULL ) return -1;
-
-    // get PID
-    if( keep_pid )    // keep parent PID
-    {
-        pid = parent_pid;
-    }
-    else              // get new PID from local cluster
-    {
-        error = cluster_pid_alloc( XPTR( local_cxy , process ) , &pid );
-        if( error ) return -1;
-    }
-
-process_dmsg("\n[DBG] %s : core[%x,%d] created process %x for path = %s\n",
+	// get .elf pathname and PID from exec_info
+	path = exec_info->path;
+    pid  = exec_info->pid;
+
+    // check local cluster is old process owner
+    assert( (CXY_FROM_PID( pid ) == local_cxy), __FUNCTION__,
+    "local cluster %x is not owner for process %x\n", local_cxy, pid );
+
+exec_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x / path = %s\n",
+__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid , path );
+
+    // get old process local pointer
+    old = (process_t *)cluster_get_local_process_from_pid( pid );
+    
+    assert( (old != NULL ) , __FUNCTION__ , 
+    "process %x not found in cluster %x\n", pid , local_cxy ); 
+
+    // allocate memory for new process descriptor
+    new = process_alloc();
+
+    // initialize new process descriptor
+    process_reference_init( new,
+                            old->pid,                   // same as old
+                            old->ppid,                  // same as old
+                            XPTR( local_cxy , old ) );
+
+exec_dmsg("\n[DBG] %s : core[%x,%d] created new process %x / path = %s\n",
 __FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid, path );
 
-    // initialize the process descriptor as the reference
-    process_reference_init( process , pid , parent_xp );
-
-process_dmsg("\n[DBG] %s : core[%x,%d] initialized process %x / path = %s\n",
-__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid, path );
-
-    // initialize vfs_root and vfs_cwd from parent process
-    xptr_t  vfs_root_xp = hal_remote_lwd( XPTR( parent_cxy , &parent_ptr->vfs_root_xp ) );
-	vfs_file_count_up( vfs_root_xp );
-	process->vfs_root_xp = vfs_root_xp;
-
-    xptr_t  vfs_cwd_xp = hal_remote_lwd( XPTR( parent_cxy , &parent_ptr->vfs_cwd_xp ) );
-	vfs_file_count_up( vfs_cwd_xp );
-	process->vfs_cwd_xp = vfs_cwd_xp;
-
-    // initialize embedded fd_array from parent process
-    process_fd_remote_copy( XPTR( local_cxy  , &process->fd_array ),
-                            XPTR( parent_cxy , &parent_ptr->fd_array) );
-
-process_dmsg("\n[DBG] %s :  core[%x,%d] copied fd_array for process %x\n",
-__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid );
-
-    // register "code" and "data" vsegs as well as the process entry-point in VMM,
-    // using information contained in the elf file.
-	error = elf_load_process( path , process );
-
-	if( error )
+    // register "code" and "data" vsegs as well as entry-point
+    // in new process VMM, using information contained in the elf file.
+	if( elf_load_process( path , new ) )
 	{
 		printk("\n[ERROR] in %s : failed to access .elf file for process %x / path = %s\n",
-		       __FUNCTION__, pid , path );
-        process_destroy( process );
-        return error;
+		__FUNCTION__, pid , path );
+        process_destroy( new );
+        return -1;
 	}
 
-process_dmsg("\n[DBG] %s : core[%x,%d] registered code/data vsegs for process %x / path = %s\n",
+exec_dmsg("\n[DBG] %s : core[%x,%d] registered code/data vsegs / process %x / path = %s\n",
 __FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid, path );
 
-    // select a core in cluster
+    // select a core in local cluster to execute the main thread
     lid  = cluster_select_local_core();
-    core = &LOCAL_CLUSTER->core_tbl[lid];
 
     // initialize pthread attributes for main thread
@@ -784,5 +889,5 @@
     // create and initialize thread descriptor
 	error = thread_user_create( pid,
-                                (void *)process->vmm.entry_point,
+                                (void *)new->vmm.entry_point,
                                 exec_info->args_pointers,
                                 &attr,
@@ -792,20 +897,21 @@
 		printk("\n[ERROR] in %s : cannot create thread for process %x / path = %s\n",
 		       __FUNCTION__, pid , path );
-        process_destroy( process );
-        return error;
+        process_destroy( new );
+        return -1;
 	}
 
-process_dmsg("\n[DBG] %s : core[%x,%d] created thread %x for process %x / path = %s\n",
-__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, thread->trdid, pid, path  );
-
-    // update children list in parent process
-	xlist_add_last( XPTR( parent_cxy , &parent_ptr->children_root ),
-                    XPTR( local_cxy  , &process->brothers_list ) );
-	hal_remote_atomic_add( XPTR( parent_cxy , &parent_ptr->children_nr) , 1 );
+exec_dmsg("\n[DBG] %s : core[%x,%d] created main thread %x for new process %x\n",
+__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, thread->trdid, pid );
+
+    // update children list (rooted in parent process)
+	xlist_replace( XPTR( local_cxy , &old->brothers_list ) ,
+                   XPTR( local_cxy , &new->brothers_list ) );
+
+    // FIXME request destruction of old process copies and threads in all clusters
 
     // activate new thread
 	thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL );
 
-process_dmsg("\n[DBG] %s : core[%x,%d] exit for path = %s\n",
+exec_dmsg("\n[DBG] %s : core[%x,%d] exit for path = %s\n",
 __FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path  );
 
@@ -818,5 +924,6 @@
 {
     exec_info_t   exec_info;     // structure to be passed to process_make_exec()
-    xptr_t        parent_xp;     // extended pointer on parent process.
+    process_t   * process;       // local pointer on process_init descriptor
+    pid_t         pid;           // process_init identifier
     error_t       error;
 
@@ -824,18 +931,40 @@
 __FUNCTION__ , local_cxy );
 
-    // parent process is local kernel process
-    parent_xp = XPTR( local_cxy , &process_zero );
+    // allocates memory for process descriptor from local cluster
+	process = process_alloc(); 
+	if( process == NULL )
+    {
+		printk("\n[PANIC] in %s : no memory for process descriptor in cluster %x\n",
+		__FUNCTION__, local_cxy );
+    }
+
+    // get new PID from local cluster
+    error = cluster_pid_alloc( XPTR( local_cxy , process ) , &pid );
+    if( error )
+    {
+		printk("\n[PANIC] in %s : cannot allocate PID in cluster %x\n",
+		__FUNCTION__, local_cxy );
+    }
+
+    // initialise the process desciptor (parent is local kernel process)
+    process_reference_init( process, 
+                            pid,
+                            process_zero.pid, 
+                            XPTR( local_cxy , &process_zero ) );
 
     // initialize the exec_info structure
-    exec_info.keep_pid     = false;
-    exec_info.parent_xp    = parent_xp;
-    strcpy( exec_info.path , CONFIG_PROCESS_INIT_PATH );
+    exec_info.pid          = pid;
     exec_info.args_nr      = 0;
     exec_info.envs_nr      = 0;
-
-    // initialize process_init and create thread_init
+    strcpy( exec_info.path , CONFIG_PROCESS_INIT_PATH );
+
+    // update process descriptor and create thread descriptor
 	error = process_make_exec( &exec_info );
 
-	if( error ) panic("cannot initialize process_init in cluster %x", local_cxy );
+	if( error )
+    { 
+		printk("\n[PANIC] in %s : cannot exec %s in cluster %x\n",
+		__FUNCTION__, CONFIG_PROCESS_INIT_PATH , local_cxy );
+    }
 
 process_dmsg("\n[DBG] %s : exit in cluster %x\n", 
