Index: trunk/kernel/syscalls/sys_fork.c
===================================================================
--- trunk/kernel/syscalls/sys_fork.c	(revision 1)
+++ trunk/kernel/syscalls/sys_fork.c	(revision 23)
@@ -1,8 +1,6 @@
 /*
- * sys_fork.c - fork the current process
+ * sys_fork.c - Fork the current process.
  * 
- * Authors  Ghassan Almaless (2008,2009,2010,2011,2012)
- *          Mohamed Lamine Karaoui (2015)
- *          Alain Greiner (2016)
+ * Authors  Alain Greiner  (2016,2017)
  *
  * Copyright (c) UPMC Sorbonne Universites
@@ -24,9 +22,11 @@
  */
 
+#include <kernel_config.h>
+#include <hal_types.h>
+#include <hal_atomic.h>
 #include <errno.h>
-#include <config.h>
-#include <cpu.h>
+#include <printk.h>
+#include <core.h>
 #include <cluster.h>
-#include <event.h>
 #include <list.h>
 #include <thread.h>
@@ -36,23 +36,6 @@
 #include <process.h>
 
-#if CONFIG_FORK_DEBUG
-#define fork_debug(...) printk(__VA_ARGS__)
-#else
-#define fork_debug(...) /**/
-#endif
-
-/***********************************************************************************************
- * This kernel function implement the "fork" system call.
- * The calling process descriptor (parent process), and the associated thread descriptor are
- * replicated in the same cluster as the calling thread, but the new process (child process)
- * is registered in another target cluster, that will become the process owner. 
- * The child process and the associated main thread will be migrated to the target cluster
- * later, when the child process makes an "exec" or any other system call. 
- * The target cluster depends on the "fork_user" flag and "fork_cxy" variable that can be
- * stored in the calling thread descriptor by the specific fork_place() system call.
- * If not, the sys_fork() function makes a query to the DQDT to select the target cluster. 
- * @ returns child process PID if success / returns -1 if failure
- **********************************************************************************************/
-int sys_fork();
+//////////////
+int sys_fork()
 {
 	process_t          * parent_process;  // pointer on parent process descriptor
@@ -63,24 +46,22 @@
 	thread_t           * child_thread;    // pointer on child main thread descriptor
     trdid_t              child_trdid;     // child main thread identifier
-    core_t             * child_core;      // pointer on core for child main thread
     lid_t                child_core_lid;  // core local index for the child main thread
     cxy_t                target_cxy;      // final target cluster for forked child process 
 	error_t              error;
 
-    cluster_t          * parent_cluster = LOCAL_CLUSTER;
-
     // get pointers on parent process and thread
 	parent_thread  = CURRENT_THREAD;
 	parent_process = parent_thread->process;
+    parent_pid     = parent_process->pid;
 
     // check parent process children number
-	if( hal_atomic_add( &parent_process->childs_nr , 1 ) >= CONFIG_PROCESS_CHILDS_MAX_NR )
-	{
-	    printk("ERROR in %s : too much children processes\n", __FUNCTION__);
-	    hal_atomic_add ( &parent_process->childs_nr , -1 );
-        return EAGAIN;
-	}
-
-	fork_debug("INFO : %s enters for process %d at cycle [%d]\n",
+	if( hal_atomic_add( &parent_process->children_nr , 1 ) >= CONFIG_PROCESS_MAX_CHILDREN )
+	{
+	    printk("\n[ERROR] in %s : too much children processes\n", __FUNCTION__);
+	    hal_atomic_add ( &parent_process->children_nr , -1 );
+        return EAGAIN;
+	}
+
+	fork_dmsg("\n[INFO] %s : enters for process %d at cycle [%d]\n",
 		  __FUNCTION__, parent_process->pid, hal_time_stamp());
 
@@ -90,22 +71,21 @@
 	{
 		hal_fpu_context_save( parent_thread );
-		fork_debug("INFO : %s save FPU\n", __FUNCTION__);
+		fork_dmsg("\n[INFO] %s : save FPU\n", __FUNCTION__);
 	}
 
     // Select target cluster for future migration of child process and main thread.
-    // The placement can be specified by user. If placement is not user-defined,
-    // the placement is defined by the DQDT. 
-    // The two first processes ("init" and "sh") on boot cluster will not migrate. 
-	if( parent_threads->fork_user )
+    // If placement is not user-defined, the placement is defined by the DQDT. 
+    // The two first processes ("init" and "sh") on boot cluster do not migrate. 
+
+	if( parent_thread->fork_user )
 	{
         // user defined placement
-        target_cxy = parent->thread.fork_cxy;
-        parent->thread.fork_cxy = false;
-	}
-    else if( (LPID_FROM_PID(parent_process->pid) < 2 )  
-             && ( parent_cluster->cxy == parent_cluster->boot_cxy ) )
+        target_cxy = parent_thread->fork_cxy;
+        parent_thread->fork_user = false;
+	}
+    else if( (LPID_FROM_PID(parent_process->pid) < 2)  && (local_cxy == 0) )
     {
         // 2 first process stay in boot cluster
-        target_cxy = parent_cluster->cxy;
+        target_cxy = local_cxy;
     }
 	else
@@ -115,31 +95,31 @@
 	}
 
-	fork_debug("INFO : %s select target_cluster = %x\n",
+	fork_dmsg("INFO : %s select target_cluster = %x\n",
               __FUNCTION__ , target_cxy );
 
     // allocates memory in local cluster for the child process descriptor 
 	child_process = process_alloc(); 
+
 	if( child_process == NULL )
 	{
-	    printk("ERROR in %s : cannot allocate memory for child process\n", __FUNCTION__ );
-	    hal_atomic_add ( &parent_process->childs_nr , -1 );
-        return EAGAIN;
-	}
-
-    // get a new PID for child process
-    // it requires an RPC if target cluster is remote
-    xptr_t xp = XPTR( target_cxy , child_process ); 
-    if( target_cxy == parent_cluster->cxy )   // local cluster
-    {
-        error = process_pid_alloc( xp , &child_pid );
-    }
-    else                            // remote cluster
-    {
-        rpc_process_pid_alloc_server( target_cxy , xp , &error , &child_pid );
-    }
+	    printk("\n[ERROR] in %s : cannot allocate child process\n", __FUNCTION__ );
+	    hal_atomic_add ( &parent_process->children_nr , -1 );
+        return EAGAIN;
+	}
+
+    // get a new PID for child process,
+    if( target_cxy == local_cxy )                // target cluster is local
+    {
+        error = cluster_pid_alloc( XPTR( target_cxy , child_process ) , &child_pid );
+    }
+    else                                         // target cluster is remote
+    {
+        rpc_process_pid_alloc_client( target_cxy , child_process , &error , &child_pid );
+    }
+
     if( error )
     {
-	    printk("ERROR in %s : cannot allocate PID\n", __FUNCTION__ );
-	    atomic_add ( &parent_process->childs_nr , -1 );
+	    printk("\n[ERROR] in %s : cannot allocate PID\n", __FUNCTION__ );
+	    hal_atomic_add ( &parent_process->children_nr , -1 );
         process_destroy( child_process );
         return EAGAIN;
@@ -147,74 +127,61 @@
 
     // initialize and register the child process descriptor
-    error = process_reference_init( child_process , child_pid , parent_pid );
-    if( error )
-    {
-	    printk("ERROR in %s : cannot initialise child process\n", __FUNCTION__ );
-	    atomic_add ( &parent_process->childs_nr , -1 );
-        process_destroy( child_process );
-        return EAGAIN;
-    }
-
-	fork_debug("INFO : %s created child process : pid = %x / ppid = %x\n", 
+    process_reference_init( child_process , child_pid , parent_pid );
+
+	fork_dmsg("\n[INFO] : %s created child process : pid = %x / ppid = %x\n", 
               __FUNCTION__, child_pid , parent_pid );
-
-    // set IS_REFERENCE flag in child process descriptor
-    child_process->flags = PDF_IS_REFERENCE;
 
     // initialises child process standard files structures
     // ( root / cwd / bin ) from parent process descriptor
-	spinlock_lock( &parent_process->cwd_lock );
-
-	vfs_file_count_up( &parent_process->vfs_root );
-	child_process->vfs_root = parent_process->vfs_root;
-
-	vfs_file_count_up( &parent_process->vfs_cwd );
-	child_process->vfs_cwd  = parent_process->vfs_cwd;
-
-	vfs_file_count_up( &parent_process->vfs_bin );
-    child_process->vfs_bin = parent_process->vfs_bin;
-
-	spinlock_unlock( &parent_process->cwd_lock );
+
+	vfs_file_count_up( parent_process->vfs_root_xp );
+	child_process->vfs_root_xp = parent_process->vfs_root_xp;
+
+	vfs_file_count_up( parent_process->vfs_cwd_xp );
+	child_process->vfs_cwd_xp  = parent_process->vfs_cwd_xp;
+
+	vfs_file_count_up( parent_process->vfs_bin_xp );
+    child_process->vfs_bin_xp = parent_process->vfs_bin_xp;
+
+    // copy the parent process fd_array to the child process fd_array
+	process_fd_remote_copy( XPTR( local_cxy , &child_process->fd_array ),
+                            XPTR( local_cxy , &parent_process->fd_array ) );
+
+	fork_dmsg("\n[INFO] %s : duplicated child process from parent process\n",
+                  __FUNCTION__ );
+
+    // replicates virtual memory manager
+	error = vmm_copy( child_process , parent_process );
+
+	if( error )
+    {
+	    printk("\n[ERROR] in %s : cannot duplicate VMM\n", __FUNCTION__ );
+	    hal_atomic_add ( &parent_process->children_nr , -1 );
+        process_destroy( child_process );
+        return ENOMEM;
+    }
   
-    // copy the parent process fd_array to the child process fd_array
-	process_fd_fork( child_process , parent_process );
-
-    // initialise child process signal manager TODO ???
-	signal_manager_init( child_process );
-  
-	fork_debug("INFO : %s duplicated child process from parent process\n",
-                  __FUNCTION__ );
-
-    // replicates virtual memory manager
-	error = vmm_dup( &child_process->vmm , &parent_process->vmm );
+	fork_dmsg("\n[INFO] %s : parent vmm duplicated in child process\n", __FUNCTION__ );
+
+    // create child main thread descriptor in local cluster 
+    error = thread_user_fork( parent_process , &child_thread );
+
 	if( error )
     {
-	    printk("ERROR in %s : cannot duplicate VMM\n", __FUNCTION__ );
-	    atomic_add ( &parent_process->childs_nr , -1 );
-        process_destroy( child_process );
-        return EAGAIN;
-    }
-  
-	fork_debug("INFO : %s: parent vmm duplicated in child process\n", __FUNCTION__ );
-
-    // create child main thread descriptor in local cluster TODO stack ???
-    error = thread_user_fork( &child_thread , process , parent_thread );
-	if( error )
-    {
-	    printk("ERROR in %s : cannot duplicate thread\n", __FUNCTION__ );
-	    atomic_add ( &parent_process->childs_nr , -1 );
-        process_destroy( child_process );
-        return EAGAIN;
+	    printk("\n[ERROR] in %s : cannot duplicate thread\n", __FUNCTION__ );
+	    hal_atomic_add( &parent_process->children_nr , -1 );
+        process_destroy( child_process );
+        return ENOMEM;
     }
 
     // register child thread in child process, and get a TRDID
-    spinlock_lock( &child->process->th_lock );
-    error = process_register_thread( child->process, child->thread , &child_trdid );
-    spinlock_unlock( &process->th_lock );
+    spinlock_lock( &child_process->th_lock );
+    error = process_register_thread( child_process, child_thread , &child_trdid );
+    spinlock_unlock( &child_process->th_lock );
 
     if( error ) 
     {
-        printk("ERROR in %s : cannot register thread\n", __FUNCTION__ );
-	    atomic_add ( &parent_process->childs_nr , -1 );
+        printk("\n[ERROR] in %s : cannot register thread\n", __FUNCTION__ );
+	    hal_atomic_add ( &parent_process->children_nr , -1 );
         thread_destroy( child_thread );
         process_destroy( child_process );
@@ -226,25 +193,25 @@
 
 	// Update child thread descriptor
-	child_thread->core    = process->core_tbl[child_core_lid];
+	child_thread->core    = &LOCAL_CLUSTER->core_tbl[child_core_lid];
 	child_thread->process = child_process;
-    child_thread->trdid   = chid_trdid;
-
-	fork_debug("INFO : %s initialised child main thread\n", __FUNCTION__ );
+    child_thread->trdid   = child_trdid;
+
+	fork_dmsg("\n[INFO] %s : initialised child main thread\n", __FUNCTION__ );
 
     // register local child thread into local child process th_tbl[]
     // we don't use the th_lock because there is no concurrent access
-    ltid_t ltid = LTID_FROM_TRDID( trdid );
-	child_process->th_tbl[ltid] = XPTR( local_cxy , child_thread );
-	child_process->threads_nr = 1;
+    ltid_t ltid = LTID_FROM_TRDID( child_trdid );
+	child_process->th_tbl[ltid] = child_thread;
+	child_process->th_nr = 1;
 
     // register child thread in scheduler 
-	sched_register( child_thread->core , child_thread );
+	sched_register_thread( child_thread->core , child_thread );
   
-	fork_debug("INFO : %s registered main thread in scheduler\n", __FUNCTION__);
+	fork_dmsg("\n[INFO] %s : registered main thread in scheduler\n", __FUNCTION__);
 
 	// update DQDT for the child thread 
-    dqdt_update_threads_number( 1 );
-
-	fork_debug("INFO :%s completed / parent pid = %x / child pid = %x / at cycle [%d]\n",
+    dqdt_local_update_threads( 1 );
+
+	fork_dmsg("\n[INFO] %s : completed / parent pid = %x / child pid = %x / at cycle [%d]\n",
 	          __FUNCTION__, parent_process->pid, child_process->pid, hal_time_stamp() );
 
