Index: trunk/kernel/kern/process.c
===================================================================
--- trunk/kernel/kern/process.c	(revision 450)
+++ trunk/kernel/kern/process.c	(revision 457)
@@ -25,5 +25,5 @@
 
 #include <kernel_config.h>
-#include <hal_types.h>
+#include <hal_kernel_types.h>
 #include <hal_remote.h>
 #include <hal_uspace.h>
@@ -89,11 +89,8 @@
 void process_reference_init( process_t * process,
                              pid_t       pid,
-                             xptr_t      parent_xp,
-                             xptr_t      model_xp )
+                             xptr_t      parent_xp )
 {
     cxy_t       parent_cxy;
     process_t * parent_ptr;
-    cxy_t       model_cxy;
-    process_t * model_ptr;
     xptr_t      stdin_xp;
     xptr_t      stdout_xp;
@@ -110,10 +107,5 @@
     chdev_t *   chdev_ptr;
     cxy_t       chdev_cxy;
-    pid_t       model_pid;
     pid_t       parent_pid;
-
-    // get model process cluster and local pointer
-    model_cxy = GET_CXY( model_xp );
-    model_ptr = GET_PTR( model_xp );
 
     // get parent process cluster and local pointer
@@ -121,13 +113,12 @@
     parent_ptr = GET_PTR( parent_xp );
 
-    // get model_pid and parent_pid
+    // get parent_pid
     parent_pid = hal_remote_lw( XPTR( parent_cxy , &parent_ptr->pid ) );
-    model_pid  = hal_remote_lw( XPTR( model_cxy  , &model_ptr->pid ) );
 
 #if DEBUG_PROCESS_REFERENCE_INIT
 uint32_t cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_PROCESS_REFERENCE_INIT )
-printk("\n[DBG] %s : thread %x enter / pid = %x / ppid = %x / model_pid = %x / cycle %d\n",
-__FUNCTION__ , CURRENT_THREAD , pid , parent_pid , model_pid , cycle );
+printk("\n[DBG] %s : thread %x in process %x enter to initalialize process %x / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD->trdid, parent_pid , pid , cycle );
 #endif
 
@@ -146,6 +137,6 @@
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_PROCESS_REFERENCE_INIT )
-printk("\n[DBG] %s : thread %x / vmm empty for process %x / cycle %d\n", 
-__FUNCTION__ , CURRENT_THREAD , pid , cycle );
+printk("\n[DBG] %s : thread %x in process %x / vmm empty for process %x / cycle %d\n", 
+__FUNCTION__, CURRENT_THREAD->trdid, parent_pid , cycle );
 #endif
 
@@ -154,15 +145,21 @@
 
     // define the stdin/stdout/stderr pseudo files <=> select a TXT terminal.
-    // - if INIT (pid == 1)         => link to kernel TXT[0] 
-    // - if KSH[i] (model_pid == 1) => allocate a free TXT[i] 
-    // - if USER process            => same terminal as model
-
-    if( (pid == 1) || (model_pid == 1)) // INIT or KSH process
-    {
-        if (pid == 1 )  txt_id = 0;                    // INIT
-        else            txt_id = process_txt_alloc();  // KSH[i]
-
-        // attach process to TXT[txt_id]
+    if( (pid == 1) || (parent_pid == 1)) // INIT or KSH process
+    {
+        // allocate a TXT channel
+        if( pid == 1 )  txt_id = 0;                     // INIT
+        else            txt_id = process_txt_alloc();   // KSH
+
+        // attach process to TXT
         process_txt_attach( process , txt_id ); 
+
+#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
+cycle = (uint32_t)hal_get_cycles();
+if( DEBUG_PROCESS_REFERENCE_INIT )
+printk("\n[DBG] %s : thread %x in process %x / process %x attached to TXT%d / cycle %d\n", 
+__FUNCTION__, CURRENT_THREAD->trdid, parent_pid, pid, txt_id, cycle );
+#endif
+
+
 
         // build path to TXT_RX[i] and TXT_TX[i] chdevs
@@ -184,6 +181,6 @@
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_PROCESS_REFERENCE_INIT )
-printk("\n[DBG] %s : thread %x / stdin open for process %x / cycle %d\n", 
-__FUNCTION__ , CURRENT_THREAD , pid , cycle );
+printk("\n[DBG] %s : thread %x in process %x / stdin open for process %x / cycle %d\n", 
+__FUNCTION__, CURRENT_THREAD->trdid, parent_pid, pid, cycle );
 #endif
 
@@ -202,6 +199,6 @@
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_PROCESS_REFERENCE_INIT )
-printk("\n[DBG] %s : thread %x / stdout open for process %x / cycle %d\n", 
-__FUNCTION__ , CURRENT_THREAD , pid , cycle );
+printk("\n[DBG] %s : thread %x in process %x / stdout open for process %x / cycle %d\n", 
+__FUNCTION__, CURRENT_THREAD->trdid, parent_pid, pid, cycle );
 #endif
 
@@ -220,6 +217,6 @@
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_PROCESS_REFERENCE_INIT )
-printk("\n[DBG] %s : thread %x / stderr open for process %x / cycle %d\n", 
-__FUNCTION__ , CURRENT_THREAD , pid , cycle );
+printk("\n[DBG] %s : thread %x in process %x / stderr open for process %x / cycle %d\n", 
+__FUNCTION__, CURRENT_THREAD->trdid, parent_pid, pid, cycle );
 #endif
 
@@ -227,8 +224,8 @@
     else                                            // normal user process 
     {
-        // get extended pointer on stdin pseudo file in model process
-        file_xp = (xptr_t)hal_remote_lwd( XPTR( model_cxy , &model_ptr->fd_array.array[0] ) );
-
-        // get extended pointer on model process TXT chdev
+        // get extended pointer on stdin pseudo file in parent process
+        file_xp = (xptr_t)hal_remote_lwd( XPTR( parent_cxy , &parent_ptr->fd_array.array[0] ) );
+
+        // get extended pointer on parent process TXT chdev
         chdev_xp = chdev_from_file( file_xp );
  
@@ -243,14 +240,14 @@
         process_txt_attach( process , txt_id ); 
 
-        // copy all open files from model process fd_array to this process
+        // copy all open files from parent process fd_array to this process
         process_fd_remote_copy( XPTR( local_cxy , &process->fd_array ),
-                                XPTR( model_cxy , &model_ptr->fd_array ) );
+                                XPTR( parent_cxy , &parent_ptr->fd_array ) );
     }
 
     // initialize specific inodes root and cwd
-    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_root_xp = (xptr_t)hal_remote_lwd( XPTR( parent_cxy,
+                                                         &parent_ptr->vfs_root_xp ) );
+    process->vfs_cwd_xp  = (xptr_t)hal_remote_lwd( XPTR( parent_cxy,
+                                                         &parent_ptr->vfs_cwd_xp ) );
     vfs_inode_remote_up( process->vfs_root_xp );
     vfs_inode_remote_up( process->vfs_cwd_xp );
@@ -469,5 +466,5 @@
 ////////////////////////////////////////
 void process_sigaction( pid_t       pid,
-                        uint32_t    action_type )
+                        uint32_t    type )
 {
     cxy_t              owner_cxy;         // owner cluster identifier
@@ -479,14 +476,23 @@
     xptr_t             process_xp;        // extended pointer on process copy
     cxy_t              process_cxy;       // process copy cluster identifier
+    process_t        * process_ptr;       // local pointer on process copy
     reg_t              save_sr;           // for critical section
     rpc_desc_t         rpc;               // shared RPC descriptor
-
-    thread_t * client = CURRENT_THREAD;
+    thread_t         * client;            // pointer on client thread
+    xptr_t             client_xp;         // extended pointer on client thread
+    process_t        * local;             // pointer on process copy in local cluster
+    uint32_t           remote_nr;         // number of remote process copies
+
+    client    = CURRENT_THREAD;
+    client_xp = XPTR( local_cxy , client );
+    local     = NULL;
+    remote_nr = 0;
 
 #if DEBUG_PROCESS_SIGACTION
 uint32_t cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_PROCESS_SIGACTION < cycle )
-printk("\n[DBG] %s : thread %x enter to %s process %x / cycle %d\n",
-__FUNCTION__ , client, process_action_str( action_type ) , pid , cycle );
+printk("\n[DBG] %s : thread %x in process %x enter to %s process %x / cycle %d\n",
+__FUNCTION__ , client->trdid, client->process->pid,
+process_action_str( type ) , pid , cycle );
 #endif
 
@@ -503,24 +509,21 @@
 
     // check action type
-    assert( ((action_type == DELETE_ALL_THREADS ) ||
-             (action_type == BLOCK_ALL_THREADS )  ||
-             (action_type == UNBLOCK_ALL_THREADS )), __FUNCTION__ , "illegal action type" );
+    assert( ((type == DELETE_ALL_THREADS ) ||
+             (type == BLOCK_ALL_THREADS )  ||
+             (type == UNBLOCK_ALL_THREADS )), __FUNCTION__ , "illegal action type" );
              
-    // allocate a - shared - RPC descriptor in client thread stack
-    // it can be shared because all parallel, non-blocking, server threads
-    // use the same input arguments, and use the shared RPC response field
-
-    // the client thread makes the following sequence:
-    // 1. mask interrupts
-    // 2. block itself
-    // 3. send RPC requests to all copies
-    // 4. unmask interrupts
-    // 5. deschedule
+
+    // The client thread send parallel RPCs to all remote clusters containing
+    // target process copies, wait all responses, and then handles directly the
+    // threads in local cluster, when required.
+    // The client thread allocates a - shared - RPC descriptor in the stack,
+    // because all parallel, non-blocking, server threads use the same input 
+    // arguments, and use the shared RPC response field
 
     // mask IRQs
     hal_disable_irq( &save_sr);
 
-    // client register blocking condition for itself
-    thread_block( XPTR( local_cxy , client ) , THREAD_BLOCKED_RPC );
+    // client thread blocks itself
+    thread_block( client_xp , THREAD_BLOCKED_RPC );
 
     // take the lock protecting the copies
@@ -533,25 +536,38 @@
     rpc.thread    = client;
     rpc.lid       = client->core->lid;
-    rpc.args[0]   = action_type;
+    rpc.args[0]   = type;
     rpc.args[1]   = pid;
 
-    // send RPCs to all clusters containing process copiess
+    // scan list of process copies
+    // to send RPCs to remote copies
     XLIST_FOREACH( root_xp , iter_xp )
     {
-        // atomically increment responses counter
-        hal_atomic_add( (void *)&rpc.responses , 1 );
-
+        // get extended pointers and cluster on process
         process_xp  = XLIST_ELEMENT( iter_xp , process_t , copies_list );
         process_cxy = GET_CXY( process_xp );
+        process_ptr = GET_PTR( process_xp );
+
+        if( process_cxy == local_cxy )    // process is local
+        { 
+            local = process_ptr;
+        }
+        else                              // process is remote
+        {
+            // update number of remote process copies
+            remote_nr++;
+
+            // atomically increment responses counter
+            hal_atomic_add( (void *)&rpc.responses , 1 );
 
 #if DEBUG_PROCESS_SIGACTION 
 if( DEBUG_PROCESS_SIGACTION < cycle )
-printk("\n[DBG] %s : send RPC to %s process %x in cluster %x\n",
-__FUNCTION__ , process_action_str( action_type ) , pid , process_cxy );
-#endif
-        // call RPC in target cluster
-        rpc_process_sigaction_client( process_cxy , &rpc );
-    }
-   
+printk("\n[DBG] %s : thread %x in process %x handles remote process %x in cluster %x\n",
+__FUNCTION__, client->trdid, client->process->pid, pid , process_cxy );
+#endif
+            // call RPC in target cluster
+            rpc_process_sigaction_client( process_cxy , &rpc );
+        }
+    }  // end list of copies
+
     // release the lock protecting process copies
     remote_spinlock_unlock( lock_xp );
@@ -560,12 +576,36 @@
     hal_restore_irq( save_sr);
 
-    // client thread deschedule : will be unblocked by the last RPC server thread 
-    sched_yield("blocked on rpc_process_sigaction");
+    // - if there is remote process copies, the client thread deschedules,
+    //   (it will be unblocked by the last RPC server thread). 
+    // - if there is no remote copies, the client thread unblock itself.
+    if( remote_nr )
+    {
+        sched_yield("blocked on rpc_process_sigaction");
+    } 
+    else
+    {
+        thread_unblock( client_xp , THREAD_BLOCKED_RPC );
+    }
+
+    // handle the local process copy if required
+    if( local != NULL )
+    {
+
+#if DEBUG_PROCESS_SIGACTION 
+if( DEBUG_PROCESS_SIGACTION < cycle )
+printk("\n[DBG] %s : thread %x in process %x handles local process %x in cluster %x\n",
+__FUNCTION__, client->trdid, client->process->pid, pid , local_cxy );
+#endif
+        if     (type == DELETE_ALL_THREADS  ) process_delete_threads ( local , client_xp ); 
+        else if(type == BLOCK_ALL_THREADS   ) process_block_threads  ( local , client_xp ); 
+        else if(type == UNBLOCK_ALL_THREADS ) process_unblock_threads( local );
+    }
 
 #if DEBUG_PROCESS_SIGACTION
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_PROCESS_SIGACTION < cycle )
-printk("\n[DBG] %s : thread %x exit after %s process %x in cluster %x / cycle %d\n",
-__FUNCTION__ , client, process_action_str( action_type ) , pid , local_cxy , cycle );
+printk("\n[DBG] %s : thread %x in process %x exit after %s process %x / cycle %d\n",
+__FUNCTION__, client->trdid, client->process->pid,
+process_action_str( type ), pid, cycle );
 #endif
 
@@ -1100,6 +1140,6 @@
 uint32_t cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_PROCESS_MAKE_FORK < cycle )
-printk("\n[DBG] %s : thread %x enter for process %x / cluster %x / cycle %d\n",
-__FUNCTION__, CURRENT_THREAD, parent_pid, local_cxy, cycle );
+printk("\n[DBG] %s : thread %x in process %x enter / cluster %x / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, local_cxy, cycle );
 #endif
 
@@ -1123,8 +1163,14 @@
     }
 
+#if DEBUG_PROCESS_MAKE_FORK
+cycle = (uint32_t)hal_get_cycles();
+if( DEBUG_PROCESS_MAKE_FORK < cycle )
+printk("\n[DBG] %s : thread %x in process %x allocated process %x / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, new_pid, cycle );
+#endif
+
     // initializes child process descriptor from parent process descriptor 
     process_reference_init( process,
                             new_pid,
-                            parent_process_xp,
                             parent_process_xp );
 
@@ -1132,7 +1178,10 @@
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_PROCESS_MAKE_FORK < cycle )
-printk("\n[DBG] %s : thread %x created child_process %x / child_pid %x / cycle %d\n",
-__FUNCTION__, CURRENT_THREAD, process, new_pid, cycle );
-#endif
+printk("\n[DBG] %s : thread %x in process %x initialized child_process %x / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, new_pid, cycle );
+#endif
+
+    // give TXT ownership to child process
+    process_txt_set_ownership( XPTR( local_cxy , process ) );
 
     // copy VMM from parent descriptor to child descriptor
@@ -1151,7 +1200,23 @@
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_PROCESS_MAKE_FORK < cycle )
-printk("\n[DBG] %s : thread %x copied VMM from parent %x to child %x / cycle %d\n",
-__FUNCTION__ , CURRENT_THREAD , parent_pid, new_pid, cycle );
-#endif
+printk("\n[DBG] %s : thread %x in process %x copied VMM from parent %x to child %x / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, 
+parent_pid, new_pid, cycle );
+#endif
+
+    // parent process gives TXT ownership to child process if required
+    if( process_txt_is_owner(parent_process_xp) ) 
+    {
+        process_txt_set_ownership( XPTR( local_cxy , process ) );
+
+#if( DEBUG_PROCESS_MAKE_FORK & 1 )
+cycle = (uint32_t)hal_get_cycles();
+if( DEBUG_PROCESS_MAKE_EXEC < cycle )
+printk("\n[DBG] %s : thread %x in process %x gives TXT from parent %x to child %x / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid,
+parent_pid, new_pid, cycle );
+#endif
+
+    }
 
     // update extended pointer on .elf file
@@ -1178,6 +1243,7 @@
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_PROCESS_MAKE_FORK < cycle )
-printk("\n[DBG] %s : thread %x created child thread %x on core[%x,%d] / cycle %d\n", 
-__FUNCTION__ , CURRENT_THREAD, thread, local_cxy, thread->core->lid, cycle );
+printk("\n[DBG] %s : thread %x in process %x created main thread %x on core[%x,%d] / cycle %d\n", 
+__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid,
+thread, local_cxy, thread->core->lid, cycle );
 #endif
 
@@ -1200,6 +1266,6 @@
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_PROCESS_MAKE_FORK < cycle )
-printk("\n[DBG] %s : thread %x set COW in parent and child / cycle %d\n",
-__FUNCTION__ , CURRENT_THREAD, cycle );
+printk("\n[DBG] %s : thread %x in process %x set COW in parent and child / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, cycle );
 #endif
 
@@ -1222,6 +1288,6 @@
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_PROCESS_MAKE_FORK < cycle )
-printk("\n[DBG] %s : thread %x exit / cycle %d\n",
-__FUNCTION__, CURRENT_THREAD, cycle );
+printk("\n[DBG] %s : thread %x in process %x exit / created process %x / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, new_pid, cycle );
 #endif
 
@@ -1229,119 +1295,93 @@
 
 }   // end process_make_fork()
-
 
 /////////////////////////////////////////////////////
 error_t process_make_exec( exec_info_t  * exec_info )
 {
-    char           * path;                    // pathname to .elf file
-    pid_t            pid;                     // old_process PID, given to new_process
-    pid_t            temp_pid;                // temporary PID / given to old_process 
-    process_t      * old_process;             // local pointer on old process
-    thread_t       * old_thread;              // local pointer on old thread
-    process_t      * new_process;             // local pointer on new process
-    thread_t       * new_thread;              // local pointer on new thread
-    xptr_t           parent_xp;               // extended pointer on parent process
-    process_t      * parent_ptr;              // local pointer on parent process
-    cxy_t            parent_cxy;              // parent process cluster identifier
-    xptr_t           children_lock_xp;        // extended pointer on children lock in parent
-    xptr_t           children_root_xp;        // extended pointer on children root in parent
-    xptr_t           children_nr_xp;          // extended pointer on children number in parent
-    thread_t       * parent_main_ptr;         // local pointer on parent main thread
-    xptr_t           parent_main_xp;          // extended pointer on parent main thread
-    pthread_attr_t   attr;                    // new thread attributes
-    lid_t            lid;                     // selected core local index
+    thread_t       * thread;                  // local pointer on this thread
+    process_t      * process;                 // local pointer on this process
+    pid_t            pid;                     // this process identifier
 	error_t          error;                   // value returned by called functions
-    
-    // get old_thread, old_process & PID 
-    old_thread  = CURRENT_THREAD;
-    old_process = old_thread->process;
-    pid         = old_process->pid;
-
-	// get .elf pathname from exec_info
-	path = exec_info->path;
-
-    // this function must be executed by a thread running in owner cluster
-    assert( (CXY_FROM_PID( pid ) == local_cxy), __FUNCTION__,
-    "local_cluster must be owner_cluster\n" );
-
-    assert( (LTID_FROM_TRDID( old_thread->trdid ) == 0) , __FUNCTION__,
-    "must be called by the main thread\n" );
- 
+    char           * path;                    // path to .elf file
+    xptr_t           file_xp;                 // extended pointer on .elf file descriptor
+    uint32_t         file_id;                 // file index in fd_array
+    uint32_t         args_nr;                 // number of main thread arguments
+    char          ** args_pointers;           // array of pointers on main thread arguments
+
+    // get thread, process & PID 
+    thread  = CURRENT_THREAD;
+    process = thread->process;
+    pid     = process->pid;
+
+	// get relevant infos from exec_info
+	path          = exec_info->path;
+    args_nr       = exec_info->args_nr;
+    args_pointers = exec_info->args_pointers;
+
 #if DEBUG_PROCESS_MAKE_EXEC
 uint32_t cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_PROCESS_MAKE_EXEC < cycle )
 printk("\n[DBG] %s : thread %x in process %x enters / path %s / cycle %d\n",
-__FUNCTION__, old_thread->trdid, pid, path, cycle );
-#endif
-
-    // get parent process pointers
-    parent_xp   = old_process->parent_xp;
-    parent_cxy  = GET_CXY( parent_xp );
-    parent_ptr  = GET_PTR( parent_xp );
-    
+__FUNCTION__, thread->trdid, pid, path, cycle );
+#endif
+
+    // open the file identified by <path>
+    file_xp = XPTR_NULL;
+    file_id = -1;
+	error   = vfs_open( process,
+	                    path,
+	                    O_RDONLY,
+	                    0,
+	                    &file_xp,
+	                    &file_id );
+	if( error )
+	{
+		printk("\n[ERROR] in %s : failed to open file <%s>\n", __FUNCTION__ , path );
+		return -1;
+	}
+
 #if (DEBUG_PROCESS_MAKE_EXEC & 1)
 if( DEBUG_PROCESS_MAKE_EXEC < cycle )
-printk("\n[DBG] %s : thread %x in process %x get parent process %x in cluster %x\n",
-__FUNCTION__, old_thread->trdid, pid, parent_ptr, parent_cxy );
-#endif
-
-    // get extended pointers on parent children_root, children_lock and children_nr
-    children_root_xp = XPTR( parent_cxy , &parent_ptr->children_root );
-    children_lock_xp = XPTR( parent_cxy , &parent_ptr->children_lock );
-    children_nr_xp   = XPTR( parent_cxy , &parent_ptr->children_nr   );
-
-    // get pointers on the parent process main thread
-    parent_main_ptr = hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->th_tbl[0] ) ); 
-    parent_main_xp  = XPTR( parent_cxy , parent_main_ptr );
-
-     // allocate memory for new_process descriptor
-    new_process = process_alloc();
-
-    if( new_process == NULL )
-    {
-        printk("\n[ERROR] in %s : cannot allocate process for %s\n", __FUNCTION__ , path );
+printk("\n[DBG] %s : open file <%s>\n", __FUNCTION__, path );
+#endif
+
+    // delete all threads other than this main thread in all clusters
+    process_sigaction( pid , DELETE_ALL_THREADS );
+
+    // reset local process VMM
+    vmm_destroy( process );
+
+#if( DEBUG_PROCESS_MAKE_EXEC & 1 )
+cycle = (uint32_t)hal_get_cycles();
+if( DEBUG_PROCESS_MAKE_EXEC < cycle )
+printk("\n[DBG] %s : thread %x in process %x / reset VMM / cycle %d\n",
+__FUNCTION__, thread->trdid, pid, cycle );
+#endif
+
+    // re-initialize the VMM (kentry/args/envs vsegs registration)
+    error = vmm_init( process );
+    if( error )
+    {
+        printk("\n[ERROR] in %s : cannot initialise VMM for %s\n", __FUNCTION__ , path );
+        vfs_close( file_xp , file_id );
+        // FIXME restore old process VMM
         return -1;
     }
-
-    // get a temporary PID for old_process
-    error = cluster_pid_alloc( old_process , &temp_pid );
-    if( error ) 
-    {
-        printk("\n[ERROR] in %s : cannot get PID in cluster %x\n", 
-        __FUNCTION__ , local_cxy ); 
-        process_free( new_process );
-        return -1;
-    }
-
-    // set temporary PID to old_process 
-    old_process->pid = temp_pid;
-
-    // initialize new process descriptor
-    process_reference_init( new_process,
-                            pid,
-                            parent_xp,                          // parent_process_xp
-                            XPTR(local_cxy , old_process) );    // model_process
-
-    // give TXT ownership to new_process
-    process_txt_set_ownership( XPTR( local_cxy , new_process) );
-
+    
 #if( DEBUG_PROCESS_MAKE_EXEC & 1 )
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_PROCESS_MAKE_EXEC < cycle )
-printk("\n[DBG] %s : thread %x in process %x created new process %x\n",
-__FUNCTION__ , old_thread->trdid, pid, new_process );
-#endif
-
-    // register code & data vsegs as well as entry-point in new process VMM,
+printk("\n[DBG] %s : thread %x in process %x / kentry/args/envs vsegs registered / cycle %d\n",
+__FUNCTION__, thread->trdid, pid, cycle );
+#endif
+
+    // register code & data vsegs as well as entry-point in process VMM,
     // and register extended pointer on .elf file in process descriptor
-	error = elf_load_process( path , new_process );
-
+	error = elf_load_process( file_xp , process );
     if( error )
 	{
 		printk("\n[ERROR] in %s : failed to access <%s>\n", __FUNCTION__ , path );
-        process_txt_set_ownership( XPTR( local_cxy , old_process) );
-        process_txt_detach( XPTR( local_cxy , new_process) );
-        process_destroy( new_process );
-        old_process->pid = pid;
+        vfs_close( file_xp , file_id );
+        // FIXME restore old process VMM 
         return -1;
 	}
@@ -1350,78 +1390,26 @@
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_PROCESS_MAKE_EXEC < cycle )
-printk("\n[DBG] %s : thread %x registered code/data vsegs in new process %x / cycle %d\n",
-__FUNCTION__, old_thread , new_process->pid , cycle );
-#endif
-
-    // select a core in local cluster to execute the main thread
-    lid  = cluster_select_local_core();
-
-    // initialize pthread attributes for main thread
-    attr.attributes = PT_ATTR_DETACH | PT_ATTR_CLUSTER_DEFINED | PT_ATTR_CORE_DEFINED;
-    attr.cxy        = local_cxy;
-    attr.lid        = lid;
-
-    // create and initialize main thread in local cluster
-	error = thread_user_create( pid,
-                                (void *)new_process->vmm.entry_point,
-                                exec_info->args_pointers,
-                                &attr,
-                                &new_thread );
-	if( error )
-	{
-		printk("\n[ERROR] in %s : cannot create thread for %s\n", __FUNCTION__ , path );
-        process_txt_set_ownership( XPTR( local_cxy , old_process) );
-        process_txt_detach( XPTR( local_cxy , new_process) );
-        process_destroy( new_process );
-        old_process->pid = pid;
+printk("\n[DBG] %s : thread %x in process %x / code/data vsegs registered / cycle %d\n",
+__FUNCTION__, thread->trdid, pid, cycle );
+#endif
+
+    // update the existing main thread descriptor... and jump to user code 
+    error = thread_user_exec( (void *)process->vmm.entry_point,
+                              args_nr,
+                              args_pointers );
+    if( error )
+    {
+        printk("\n[ERROR] in %s : cannot reset main thread for %s\n", __FUNCTION__ , path );
+        vfs_close( file_xp , file_id );
+        // FIXME restore old process VMM 
         return -1;
-	}
-
-    // check main thread LTID
-    assert( (LTID_FROM_TRDID(new_thread->trdid) == 0) , __FUNCTION__ ,
-    "main thread must have LTID == 0\n" );
-
-#if( DEBUG_PROCESS_MAKE_EXEC & 1 )
-cycle = (uint32_t)hal_get_cycles();
-if( DEBUG_PROCESS_MAKE_EXEC < cycle )
-printk("\n[DBG] %s : thread %x created new_process main thread %x / cycle %d\n",
-__FUNCTION__ , old_thread , new_thread , cycle );
-#endif
-
-    // register new_process in parent children list
-    remote_spinlock_lock( children_lock_xp );
-	xlist_add_last( children_root_xp , XPTR( local_cxy , &new_process->children_list ) );
-	hal_remote_atomic_add( children_nr_xp , 1 );
-    remote_spinlock_unlock( children_lock_xp );
-
-    // activate new thread
-	thread_unblock( XPTR( local_cxy , new_thread ) , THREAD_BLOCKED_GLOBAL );
-
-    // detach old_process from TXT
-    process_txt_detach( XPTR( local_cxy , old_process ) );
-
-    // block old_thread 
-    thread_block( XPTR( local_cxy , old_thread ) , THREAD_BLOCKED_GLOBAL );
-
-    // atomically update old_process termination state
-    hal_atomic_or( &old_process->term_state , PROCESS_TERM_EXIT );
-
-    // take the children lock and unblock the parent process main thread 
-    remote_spinlock_lock( children_lock_xp );
-    thread_unblock( parent_main_xp , THREAD_BLOCKED_WAIT );
-    remote_spinlock_unlock( children_lock_xp );
-
-    hal_fence();
-
-#if DEBUG_PROCESS_MAKE_EXEC
-cycle = (uint32_t)hal_get_cycles();
-if( DEBUG_PROCESS_MAKE_EXEC < cycle )
-printk("\n[DBG] %s : old thread %x blocked for delete / new thread %x activated / cycle %d\n",
-__FUNCTION__ , old_thread , new_thread , cycle );
-#endif
-   
+    }
+
+    assert( false, __FUNCTION__, "we should not execute this code");
+ 
 	return 0;
 
 }  // end process_make_exec()
+
 
 ///////////////////////////////////////////////
@@ -1474,4 +1462,6 @@
     pthread_attr_t   attr;          // main thread attributes
     lid_t            lid;           // selected core local index for main thread
+    xptr_t           file_xp;       // extended pointer on .elf file descriptor
+    uint32_t         file_id;       // file index in fd_array
     error_t          error;
 
@@ -1479,41 +1469,47 @@
 uint32_t cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_PROCESS_INIT_CREATE < cycle )
-printk("\n[DBG] %s : thread %x enter / cycle %d\n", __FUNCTION__, CURRENT_THREAD, cycle );
+printk("\n[DBG] %s : thread %x in process %x enter / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, cycle );
 #endif
 
     // 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  );
-    }
+	
+    assert( (process != NULL), __FUNCTION__,
+    "no memory for process descriptor in cluster %x\n", local_cxy  );
 
     // get PID from local cluster
     error = cluster_pid_alloc( process , &pid );
-    if( error )
-    {
-		printk("\n[PANIC] in %s : cannot allocate PID in cluster %x\n",
-		__FUNCTION__, local_cxy );
-        process_free( process );
-    }
-
-    // check allocated PID
-    assert( (pid == 1) , __FUNCTION__ , "process INIT must be first process in cluster 0\n" );
+
+    assert( (error == 0), __FUNCTION__,
+    "cannot allocate PID in cluster %x\n", local_cxy );
+
+    assert( (pid == 1) , __FUNCTION__,
+    "process INIT must be first process in cluster 0\n" );
 
     // initialize process descriptor / parent is local process_zero
     process_reference_init( process,
                             pid,
-                            XPTR( local_cxy , &process_zero ),     // parent
-                            XPTR( local_cxy , &process_zero ) );   // model
+                            XPTR( local_cxy , &process_zero ) );  
+
+    // open the file identified by CONFIG_PROCESS_INIT_PATH
+    file_xp = XPTR_NULL;
+    file_id = -1;
+	error   = vfs_open( process,
+	                    CONFIG_PROCESS_INIT_PATH,
+	                    O_RDONLY,
+	                    0,
+	                    &file_xp,
+	                    &file_id );
+
+	assert( (error == 0), __FUNCTION__,
+    "failed to open file <%s>\n", CONFIG_PROCESS_INIT_PATH );
 
     // register "code" and "data" vsegs as well as entry-point
     // in process VMM, using information contained in the elf file.
-	if( elf_load_process( CONFIG_PROCESS_INIT_PATH , process ) )
-	{
-		printk("\n[PANIC] in %s : cannot access .elf file / path = %s\n",
-		__FUNCTION__, CONFIG_PROCESS_INIT_PATH );
-        process_destroy( process );
-	}
+	error = elf_load_process( file_xp , process );
+
+	assert( (error == 0), __FUNCTION__,
+    "cannot access .elf file <%s>\n", CONFIG_PROCESS_INIT_PATH );
 
     // get extended pointers on process_zero children_root, children_lock
@@ -1541,13 +1537,10 @@
                                 &attr,
                                 &thread );
-	if( error )
-	{
-		printk("\n[PANIC] in %s : cannot create main thread / path = %s\n",
-		__FUNCTION__, CONFIG_PROCESS_INIT_PATH );
-        process_destroy( process );
-	}
-
-    // check main thread index
-    assert( (thread->trdid == 0) , __FUNCTION__ , "main thread must have index 0\n" );
+
+	assert( (error == 0), __FUNCTION__,
+    "cannot create main thread for <%s>\n", CONFIG_PROCESS_INIT_PATH );
+
+    assert( (thread->trdid == 0), __FUNCTION__,
+    "main thread must have index 0 for <%s>\n", CONFIG_PROCESS_INIT_PATH );
 
     // activate thread
@@ -1559,5 +1552,6 @@
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_PROCESS_INIT_CREATE < cycle )
-printk("\n[DBG] %s : thread %x exit / cycle %d\n", __FUNCTION__, CURRENT_THREAD, cycle );
+printk("\n[DBG] %s : thread %x in process %x exit / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, cycle );
 #endif
 
@@ -1702,11 +1696,4 @@
     xptr_t      lock_xp;      // extended pointer on list lock in chdev
 
-#if DEBUG_PROCESS_TXT
-uint32_t cycle = (uint32_t)hal_get_cycles();
-if( DEBUG_PROCESS_TXT < cycle )
-printk("\n[DBG] %s : thread %x enter for process %x / txt_id = %d  / cycle %d\n",
-__FUNCTION__, CURRENT_THREAD, process->pid, txt_id, cycle );
-#endif
-
     // check process is in owner cluster
     assert( (CXY_FROM_PID( process->pid ) == local_cxy) , __FUNCTION__ ,
@@ -1732,8 +1719,9 @@
 
 #if DEBUG_PROCESS_TXT
-cycle = (uint32_t)hal_get_cycles();
+uint32_t cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_PROCESS_TXT < cycle )
-printk("\n[DBG] %s : thread %x exit for process %x / txt_id = %d / cycle %d\n",
-__FUNCTION__, CURRENT_THREAD, process->pid, txt_id , cycle );
+printk("\n[DBG] %s : thread %x in process %x attached process %x to TXT %d / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid,
+process->pid, txt_id , cycle );
 #endif
 
@@ -1755,16 +1743,9 @@
     process_cxy = GET_CXY( process_xp );
     process_ptr = GET_PTR( process_xp );
+
+    // check process descriptor in owner cluster
     process_pid = hal_remote_lw( XPTR( process_cxy , &process_ptr->pid ) );
-
-    // check process descriptor in owner cluster
     assert( (CXY_FROM_PID( process_pid ) == process_cxy ) , __FUNCTION__ ,
     "process descriptor not in owner cluster" );
-
-#if DEBUG_PROCESS_TXT
-uint32_t cycle = (uint32_t)hal_get_cycles();
-if( DEBUG_PROCESS_TXT < cycle )
-printk("\n[DBG] %s : thread %x enter for process %x / cycle %d\n",
-__FUNCTION__, CURRENT_THREAD, process_pid, cycle );
-#endif
 
     // release TXT ownership (does nothing if not TXT owner)
@@ -1788,9 +1769,10 @@
 
 #if DEBUG_PROCESS_TXT
-cycle  = (uint32_t)hal_get_cycles();
+uint32_t cycle  = (uint32_t)hal_get_cycles();
 uint32_t txt_id = hal_remote_lw( XPTR( chdev_cxy , &chdev_ptr->channel ) );
 if( DEBUG_PROCESS_TXT < cycle )
-printk("\n[DBG] %s : thread %x exit / process %x detached from TXT %d / cycle %d\n",
-__FUNCTION__, CURRENT_THREAD, process_pid, txt_id, cycle );
+printk("\n[DBG] %s : thread %x in process %x detached process %x from TXT %d / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid,
+process_pid, txt_id, cycle );
 #endif
 
@@ -1811,6 +1793,4 @@
     process_cxy = GET_CXY( process_xp );
     process_ptr = GET_PTR( process_xp );
-
-    // get process PID
     process_pid = hal_remote_lw( XPTR( process_cxy , &process_ptr->pid ) );
 
@@ -1818,11 +1798,4 @@
     assert( (process_cxy == CXY_FROM_PID( process_pid )) , __FUNCTION__,
     "process descriptor not in owner cluster\n" );
-
-#if DEBUG_PROCESS_TXT
-uint32_t cycle = (uint32_t)hal_get_cycles();
-if( DEBUG_PROCESS_TXT < cycle )
-printk("\n[DBG] %s : thread %x enter for process %x / cycle %d\n",
-__FUNCTION__, CURRENT_THREAD, process_pid, cycle );
-#endif
 
     // get extended pointer on stdin pseudo file
@@ -1838,8 +1811,9 @@
 
 #if DEBUG_PROCESS_TXT
-cycle = (uint32_t)hal_get_cycles();
+uint32_t cycle  = (uint32_t)hal_get_cycles();
+uint32_t txt_id = hal_remote_lw( XPTR( txt_cxy , &txt_ptr->channel ) );
 if( DEBUG_PROCESS_TXT < cycle )
-printk("\n[DBG] %s : thread %x exit for process %x / cycle %d\n",
-__FUNCTION__, CURRENT_THREAD, process_pid, cycle );
+printk("\n[DBG] %s : thread %x in process %x give TXT %d to process %x / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, txt_id, process_pid, cycle );
 #endif
 
@@ -1865,9 +1839,11 @@
     cxy_t       current_cxy;     // cluster for current process
 
+#if DEBUG_PROCESS_TXT
+uint32_t cycle;
+#endif
+
     // get pointers on process in owner cluster
     process_cxy = GET_CXY( process_xp );
     process_ptr = GET_PTR( process_xp );
-
-    // get process PID
     process_pid = hal_remote_lw( XPTR( process_cxy , &process_ptr->pid ) );
 
@@ -1875,11 +1851,4 @@
     assert( (process_cxy == CXY_FROM_PID( process_pid )) , __FUNCTION__,
     "process descriptor not in owner cluster\n" );
-
-#if DEBUG_PROCESS_TXT
-uint32_t cycle = (uint32_t)hal_get_cycles();
-if( DEBUG_PROCESS_TXT < cycle )
-printk("\n[DBG] %s : thread %x enter / process %x / cycle %d\n",
-__FUNCTION__, CURRENT_THREAD, process_pid, cycle );
-#endif
 
     // get extended pointer on stdin pseudo file
@@ -1895,10 +1864,4 @@
     txt_id   = hal_remote_lw ( XPTR( txt_cxy , &txt_ptr->channel ) );
 
-#if( DEBUG_PROCESS_TXT & 1 )
-if( DEBUG_PROCESS_TXT < cycle )
-printk("\n[DBG] %s : file_ptr %x / txt_ptr %x / txt_id %d / owner_ptr = %x\n",
-__FUNCTION__, GET_PTR(file_xp), txt_ptr, txt_id, GET_PTR(owner_xp) );
-#endif
-
     // transfer ownership only if process is the TXT owner
     if( (owner_xp == process_xp) && (txt_id > 0) )  
@@ -1913,9 +1876,4 @@
         if( process_get_ppid( process_xp ) != 1 )           // process is not KSH
         {
-
-#if( DEBUG_PROCESS_TXT & 1 )
-if( DEBUG_PROCESS_TXT < cycle )
-printk("\n[DBG] %s : process is not the KSH process => search the KSH\n", __FUNCTION__ );
-#endif
             // scan attached process list to find KSH process
             XLIST_FOREACH( root_xp , iter_xp )
@@ -1934,9 +1892,10 @@
 
 #if DEBUG_PROCESS_TXT
-cycle = (uint32_t)hal_get_cycles();
+cycle   = (uint32_t)hal_get_cycles();
+uint32_t ksh_pid = hal_remote_lw( XPTR( current_cxy , &current_ptr->pid ) );
 if( DEBUG_PROCESS_TXT < cycle )
-printk("\n[DBG] %s : thread %x exit / process %x to KSH process %x / cycle %d\n",
-__FUNCTION__, CURRENT_THREAD, process_pid, 
-hal_remote_lw( XPTR( current_cxy , &current_ptr->pid ) ), cycle );
+printk("\n[DBG] %s : thread %x in process %x release TXT %d to KSH %x / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, txt_id, ksh_pid, cycle );
+process_txt_display( txt_id );
 #endif
                      return;
@@ -1954,10 +1913,4 @@
         else                                               // process is KSH
         {
-
-#if( DEBUG_PROCESS_TXT & 1 )
-if( DEBUG_PROCESS_TXT < cycle )
-printk("\n[DBG] %s : process is the KSH process => search another\n", __FUNCTION__ );
-#endif
-
             // scan attached process list to find another process 
             XLIST_FOREACH( root_xp , iter_xp )
@@ -1976,9 +1929,10 @@
 
 #if DEBUG_PROCESS_TXT
-cycle = (uint32_t)hal_get_cycles();
+cycle   = (uint32_t)hal_get_cycles();
+uint32_t new_pid = hal_remote_lw( XPTR( current_cxy , &current_ptr->pid ) );
 if( DEBUG_PROCESS_TXT < cycle )
-printk("\n[DBG] %s : thread %x exit / KSH process %x to process %x / cycle %d\n",
-__FUNCTION__, CURRENT_THREAD, process_pid,
-hal_remote_lw( XPTR( current_cxy , &current_ptr->pid ) ), cycle );
+printk("\n[DBG] %s : thread %x in process %x release TXT %d to process %x / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, txt_id, new_pid, cycle );
+process_txt_display( txt_id );
 #endif
                      return;
@@ -1995,6 +1949,7 @@
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_PROCESS_TXT < cycle )
-printk("\n[DBG] %s : thread %x exit / KSH process %x to nobody / cycle %d\n",
-__FUNCTION__, CURRENT_THREAD, process_pid, cycle );
+printk("\n[DBG] %s : thread %x in process %x release TXT %d to nobody / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, txt_id, cycle );
+process_txt_display( txt_id );
 #endif
             return;
@@ -2007,6 +1962,7 @@
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_PROCESS_TXT < cycle )
-printk("\n[DBG] %s : thread %x exit / process %x is not TXT owner / cycle %d\n",
-__FUNCTION__, CURRENT_THREAD, process_pid, cycle );
+printk("\n[DBG] %s : thread %x in process %d does nothing (not TXT owner) / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD->trdid, process_pid, cycle );
+process_txt_display( txt_id );
 #endif
 
@@ -2014,4 +1970,31 @@
 }  // end process_txt_transfer_ownership()
 
+
+//////////////////////////////////////////////////
+uint32_t process_txt_is_owner( xptr_t process_xp )
+{
+    // get local pointer and cluster of process in owner cluster
+    cxy_t       process_cxy = GET_CXY( process_xp );
+    process_t * process_ptr = GET_PTR( process_xp );
+
+    // check owner cluster
+    pid_t process_pid = hal_remote_lw( XPTR( process_cxy , &process_ptr->pid ) );
+    assert( (process_cxy == CXY_FROM_PID( process_pid )) , __FUNCTION__,
+    "process descriptor not in owner cluster\n" );
+
+    // get extended pointer on stdin pseudo file
+    xptr_t file_xp = hal_remote_lwd( XPTR( process_cxy , &process_ptr->fd_array.array[0] ) );
+
+    // get pointers on TXT chdev
+    xptr_t    txt_xp  = chdev_from_file( file_xp );
+    cxy_t     txt_cxy = GET_CXY( txt_xp );
+    chdev_t * txt_ptr = GET_PTR( txt_xp );
+
+    // get extended pointer on TXT_RX owner process 
+    xptr_t owner_xp = hal_remote_lwd( XPTR( txt_cxy , &txt_ptr->ext.txt.owner_xp ) );
+
+    return (process_xp == owner_xp);
+
+}   // end process_txt_is_owner()
 
 ////////////////////////////////////////////////     
@@ -2023,5 +2006,6 @@
 
     return (xptr_t)hal_remote_lwd( XPTR( txt_rx_cxy , &txt_rx_ptr->ext.txt.owner_xp ) );
-}
+
+}  // end process_txt_get_owner()
 
 ///////////////////////////////////////////
