Index: trunk/kernel/kern/process.c
===================================================================
--- trunk/kernel/kern/process.c	(revision 406)
+++ trunk/kernel/kern/process.c	(revision 407)
@@ -39,4 +39,5 @@
 #include <thread.h>
 #include <list.h>
+#include <string.h>
 #include <scheduler.h>
 #include <remote_spinlock.h>
@@ -90,10 +91,20 @@
     pid_t       parent_pid;
 
-    process_dmsg("\n[DMSG] %s : core[%x,%d] enters for process %x\n",
-    __FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
+	error_t     error1;
+	error_t     error2;
+	error_t     error3;
+    xptr_t      stdin_xp;
+    xptr_t      stdout_xp;
+    xptr_t      stderr_xp;
+    uint32_t    stdin_id;
+    uint32_t    stdout_id;
+    uint32_t    stderr_id;
+
+process_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x\n",
+__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
 
     // get parent process cluster, local pointer, and pid
-    // for all processes other than process_zero
-    if( process == &process_zero )
+    // for all processes other than kernel process
+    if( process == &process_zero )                   // kernel process
     {
         assert( (pid == 0) , __FUNCTION__ , "process_zero must have PID = 0\n");
@@ -101,10 +112,8 @@
         parent_cxy = 0;
         parent_ptr = NULL;
-        parent_pid = 0;      // process_zero is its own parent...
-    }
-    else
-    {
-        assert( (parent_xp != XPTR_NULL) , __FUNCTION__ , "parent_xp cannot be NULL\n");
-
+        parent_pid = 0;      
+    }
+    else                                             // user process
+    {
         parent_cxy = GET_CXY( parent_xp );
         parent_ptr = (process_t *)GET_PTR( parent_xp );
@@ -112,34 +121,98 @@
     }
 
-    // initialize PID and PPID
-	process->pid   = pid;
-    process->ppid  = parent_pid;
-
-    // initialize reference process vmm (not for kernel process)
-    if( pid ) vmm_init( process );
-
-    // reset reference process file descriptors array
-	process_fd_init( process );
-
-    // reset reference process files structures and cwd_lock
-	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
-    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 parent children list (not for kernel process)
+    // initialize PID, PPID, and REF
+	process->pid    = pid;
+    process->ppid   = parent_pid;
+    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", 
+__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 );
+
+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 );
@@ -156,7 +229,4 @@
     spinlock_init( &process->th_lock );
 
-    // set ref_xp field
-    process->ref_xp = XPTR( local_cxy , process );
-
     // register new process descriptor in local cluster manager local_list
     cluster_process_local_link( process );
@@ -169,6 +239,6 @@
 	hal_fence();
 
-    process_dmsg("\n[DMSG] %s : exit for process %x in cluster %x\n",
-                 __FUNCTION__ , pid );
+process_dmsg("\n[DBG] %s : core[%x,%d] exit for process %x\n",
+__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
 
 }  // process_reference init()
@@ -181,4 +251,12 @@
     cxy_t       ref_cxy = GET_CXY( reference_process_xp );
     process_t * ref_ptr = (process_t *)GET_PTR( reference_process_xp );
+
+    // set the pid, ppid, ref_xp fields in local process
+    local_process->pid    = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->pid ) );
+    local_process->ppid   = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->ppid ) );
+    local_process->ref_xp = reference_process_xp;
+
+process_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x in cluster %x\n",
+__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , local_process->pid );
 
     // reset local process vmm
@@ -192,12 +270,4 @@
     local_process->vfs_bin_xp  = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->vfs_bin_xp ) );
     local_process->vfs_cwd_xp  = XPTR_NULL;
-
-    // set the pid, ppid, ref_xp fields
-    local_process->pid    = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->pid ) );
-    local_process->ppid   = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->ppid ) );
-    local_process->ref_xp = reference_process_xp;
-
-    process_dmsg("\n[DMSG] %s : enter for process %x in cluster %x\n",
-                 __FUNCTION__ , local_process->pid );
 
     // reset children list root (not used in a process descriptor copy)
@@ -233,6 +303,6 @@
 	hal_fence();
 
-    process_dmsg("\n[DMSG] %s : exit for process %x in cluster %x\n",
-                 __FUNCTION__ , local_process->pid );
+process_dmsg("\n[DBG] %s : core[%x,%d] exit for process %x in cluster %x\n",
+__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , local_process->pid );
 
     return 0;
@@ -288,7 +358,8 @@
     vmm_destroy( process );
 
-	process_dmsg("\n[DMSG] %s for pid %d / page_faults = %d\n",
+	process_dmsg("\n[DBG] %s for pid %d / page_faults = %d\n",
 	         __FUNCTION__ , process->pid, process->vmm.pgfault_nr );
-}
+
+}  // end process_destroy()
 
 ////////////////////////////////////////
@@ -298,4 +369,6 @@
     uint32_t       ltid;      // index in process th_tbl
     uint32_t       count;     // thread counter
+
+printk("\n@@@ %s enter\n", __FUNCTION__ );
 
     // get lock protecting th_tbl[]
@@ -317,5 +390,5 @@
     }
 
-    volatile uint32_t ko;
+printk("\n@@@ %s : %d signal(s) sent\n", __FUNCTION__, count );
 
     // second loop on threads to wait acknowledge from scheduler,
@@ -329,10 +402,15 @@
         if( thread != NULL )
         {
-            // wait scheduler acknowledge
-            do { ko = (thread->signals & THREAD_SIG_KILL); } while( ko );
-
-            // unlink thread from brothers list if required
-            if( (thread->flags & THREAD_FLAG_DETACHED) == 0 )
-            xlist_unlink( XPTR( local_cxy , &thread->brothers_list ) );
+
+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__ );
+
+            // detach target thread from parent if attached
+            if( (thread->flags & THREAD_FLAG_DETACHED) != 0 ) 
+            thread_child_parent_unlink( thread->parent , XPTR( local_cxy , thread ) );
 
             // unlink thread from process
@@ -346,4 +424,6 @@
     }
 
+printk("\n@@@ %s : %d ack(s) received\n", __FUNCTION__, count );
+
     // release lock protecting th_tbl[]
     spinlock_unlock( &process->th_lock );
@@ -351,5 +431,9 @@
     // release memory allocated for process descriptor
     process_destroy( process );
-}
+
+printk("\n[@@@] %s : core[%x,%d] exit\n",
+__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid );
+
+}  // end process_kill()
 
 ///////////////////////////////////////////////
@@ -440,6 +524,7 @@
 
 /////////////////////////////////////////////////
-error_t process_fd_register(  xptr_t     file_xp,
-                              uint32_t * file_id )
+error_t process_fd_register( process_t * process,
+                             xptr_t      file_xp,
+                             uint32_t  * fdid )
 {
     bool_t    found;
@@ -447,8 +532,6 @@
     xptr_t    xp;
 
-    // get extended pointer on reference process
-    xptr_t ref_xp = CURRENT_THREAD->process->ref_xp;
-
     // get reference process cluster and local pointer
+    xptr_t ref_xp = process->ref_xp;
     process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
     cxy_t       ref_cxy = GET_CXY( ref_xp );
@@ -467,5 +550,5 @@
             hal_remote_swd( XPTR( ref_cxy , &ref_ptr->fd_array.array[id] ) , file_xp );
 	        hal_remote_atomic_add( XPTR( ref_cxy , &ref_ptr->fd_array.current ) , 1 );
-			*file_id = id;
+			*fdid = id;
             break;
         }
@@ -481,10 +564,10 @@
 ////////////////////////////////////////////////
 xptr_t process_fd_get_xptr( process_t * process,
-                            uint32_t    file_id )
+                            uint32_t    fdid )
 {
     xptr_t  file_xp;
 
     // access local copy of process descriptor
-    file_xp = process->fd_array.array[file_id];
+    file_xp = process->fd_array.array[fdid];
 
     if( file_xp == XPTR_NULL )
@@ -496,15 +579,16 @@
 
         // access reference process descriptor
-        file_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->fd_array.array[file_id] ) );
+        file_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->fd_array.array[fdid] ) );
 
         // update local fd_array if found
         if( file_xp != XPTR_NULL )
         {
-            process->fd_array.array[file_id] = file_xp;
+            process->fd_array.array[fdid] = file_xp;
         }
     }
 
     return file_xp;
-}
+
+}  // end process_fd_get_xptr()
 
 ///////////////////////////////////////////
@@ -543,5 +627,6 @@
     // release lock on source process fd_array
 	remote_spinlock_unlock( XPTR( src_cxy , &src_ptr->lock ) );
-}
+
+}  // end process_fd_remote_copy()
 
 ////////////////////////////////////////////////////////////////////////////////////
@@ -561,7 +646,8 @@
     assert( (thread != NULL) , __FUNCTION__ , "thread argument is NULL" );
 
-    // search a free slot in th_tbl[]
+    // search a free slot in th_tbl[] 
+    // 0 is not a valid ltid value
     found = false;
-    for( ltid = 0 ; ltid < CONFIG_THREAD_MAX_PER_CLUSTER ; ltid++ )
+    for( ltid = 1 ; ltid < CONFIG_THREAD_MAX_PER_CLUSTER ; ltid++ )
     {
         if( process->th_tbl[ltid] == NULL )
@@ -606,10 +692,11 @@
 {
     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;
-    process_t      * parent_ptr;
-    uint32_t         parent_pid;
+    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
@@ -618,7 +705,11 @@
 	error_t          error;
 
-	// get parent and .elf pathname from exec_info
+	// 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
@@ -627,33 +718,27 @@
     parent_pid = hal_remote_lw( XPTR( parent_cxy , &parent_ptr->pid ) );
 
-    exec_dmsg("\n[DMSG] %s : thread %x on core[%x,%d] enters for path = %s\n",
-    __FUNCTION__, CURRENT_THREAD->trdid, local_cxy, CURRENT_THREAD->core->lid , path );
-
-    // create new process descriptor
-    process = process_alloc();
-
-    if( process == NULL )
-    {
-        printk("\n[ERROR] in %s : no memory / cluster = %x / ppid = %x / path = %s\n",
-               __FUNCTION__ , local_cxy , parent_pid , path );
-        return ENOMEM;
-    }
-
-    // get a pid from the local cluster
-    error = cluster_pid_alloc( XPTR( local_cxy , process ) , &pid );
-
-    if( error )
-    {
-        printk("\n[ERROR] in %s : cannot get PID / cluster = %x / ppid = %x / path = %s\n",
-               __FUNCTION__ , local_cxy , parent_pid , path );
-        process_free( process );
-		return ENOMEM;
-    }
+    // 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",
+__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid, path );
 
     // initialize the process descriptor as the reference
     process_reference_init( process , pid , parent_xp );
 
-    exec_dmsg("\n[DMSG] %s : thread %x on core[%x,%d] created process %x / path = %s\n",
-    __FUNCTION__, CURRENT_THREAD->trdid, local_cxy, CURRENT_THREAD->core->lid, pid, path );
+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
@@ -670,9 +755,6 @@
                             XPTR( parent_cxy , &parent_ptr->fd_array) );
 
-    exec_dmsg("\n[DMSG] %s : fd_array copied from process %x to process %x\n",
-    __FUNCTION__, parent_pid , pid );
-
-	// initialize signal manager TODO ??? [AG]
-	// signal_manager_init( process );
+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,
@@ -682,5 +764,5 @@
 	if( error )
 	{
-		printk("\n[ERROR] in %s : failed to access elf file for process %x / path = %s\n",
+		printk("\n[ERROR] in %s : failed to access .elf file for process %x / path = %s\n",
 		       __FUNCTION__, pid , path );
         process_destroy( process );
@@ -688,6 +770,6 @@
 	}
 
-    exec_dmsg("\n[DMSG] %s : code and data vsegs registered for process %x / path = %s\n",
-    __FUNCTION__ , pid , path );
+process_dmsg("\n[DBG] %s : core[%x,%d] registered code/data vsegs for process %x / path = %s\n",
+__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid, path );
 
     // select a core in cluster
@@ -709,19 +791,11 @@
 	{
 		printk("\n[ERROR] in %s : cannot create thread for process %x / path = %s\n",
-		       __FUNCTION__, pid );
+		       __FUNCTION__, pid , path );
         process_destroy( process );
         return error;
 	}
 
-	exec_dmsg("\n[DMSG] %s : thread created for process %x on core %d in cluster %x\n",
-               __FUNCTION__ , pid , core->lid , local_cxy );
-
-#if CONFIG_EXEC_DEBUG
-if( hal_time_stamp() > CONFIG_EXEC_DEBUG )
-{
-    grdxt_print( &process->vmm.grdxt , GRDXT_TYPE_VSEG , process->pid );
-    hal_gpt_print( &process->vmm.gpt , process->pid ); 
-}
-#endif
+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
@@ -733,10 +807,10 @@
 	thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL );
 
-    exec_dmsg("\n[DMSG] %s : exit for process %x\n",
-                __FUNCTION__, process->pid );
+process_dmsg("\n[DBG] %s : core[%x,%d] exit for path = %s\n",
+__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path  );
 
 	return 0;
 
-}  // end proces_make_exec()
+}  // end process_make_exec()
 
 //////////////////////////
@@ -744,40 +818,27 @@
 {
     exec_info_t   exec_info;     // structure to be passed to process_make_exec()
-
-	error_t   error1;
-	error_t   error2;
-	error_t   error3;
-    xptr_t    stdin_xp;
-    xptr_t    stdout_xp;
-    xptr_t    stderr_xp;
-    uint32_t  stdin_id;
-    uint32_t  stdout_id;
-    uint32_t  stderr_id;
-
-	process_dmsg("\n[DMSG] %s : enters in cluster %x\n", __FUNCTION__ , local_cxy );
-
-    // open stdin / stdout / stderr pseudo-files
-	error1 = vfs_open( XPTR_NULL, CONFIG_DEV_STDIN , O_RDONLY, 0, &stdin_xp , &stdin_id  );
-	error2 = vfs_open( XPTR_NULL, CONFIG_DEV_STDOUT, O_WRONLY, 0, &stdout_xp, &stdout_id );
-	error3 = vfs_open( XPTR_NULL, CONFIG_DEV_STDERR, O_WRONLY, 0, &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 for stdin/stdout/stderr\n");
+    xptr_t        parent_xp;     // extended pointer on parent process.
+    error_t       error;
+
+process_dmsg("\n[DBG] %s : enters in cluster %x\n", 
+__FUNCTION__ , local_cxy );
+
+    // parent process is local kernel process
+    parent_xp = XPTR( local_cxy , &process_zero );
 
     // initialize the exec_info structure
-    exec_info.parent_xp    = XPTR( local_cxy , &process_zero );
+    exec_info.keep_pid     = false;
+    exec_info.parent_xp    = parent_xp;
     strcpy( exec_info.path , CONFIG_PROCESS_INIT_PATH );
     exec_info.args_nr      = 0;
     exec_info.envs_nr      = 0;
 
-    // create process_init and thread_init
-	error1 = process_make_exec( &exec_info );
-
-	assert( (error1 == 0) , __FUNCTION__ , "cannot create process_init\n");
-
-	process_dmsg("\n[DMSG] %s : exit in cluster %x\n", __FUNCTION__ , local_cxy );
+    // initialize process_init and create thread_init
+	error = process_make_exec( &exec_info );
+
+	if( error ) panic("cannot initialize process_init in cluster %x", local_cxy );
+
+process_dmsg("\n[DBG] %s : exit in cluster %x\n", 
+__FUNCTION__ , local_cxy );
 		
     hal_fence();
