Index: trunk/kernel/kern/process.c
===================================================================
--- trunk/kernel/kern/process.c	(revision 428)
+++ trunk/kernel/kern/process.c	(revision 433)
@@ -4,5 +4,5 @@
  * Authors  Ghassan Almaless (2008,2009,2010,2011,2012)
  *          Mohamed Lamine Karaoui (2015)
- *          Alain Greiner (2016,2017)
+ *          Alain Greiner (2016,2017,2018)
  *
  * Copyright (c) UPMC Sorbonne Universites
@@ -124,12 +124,16 @@
     model_pid  = hal_remote_lw( XPTR( model_cxy  , &model_ptr->pid ) );
 
-process_dmsg("\n[DBG] %s : core[%x,%d] enters / pid = %x / ppid = %x / model_pid = %x\n",
-__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid , parent_pid , model_pid );
+#if CONFIG_DEBUG_PROCESS_REFERENCE_INIT
+uint32_t cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_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 );
+#endif
 
     // initialize PID, REF_XP, PARENT_XP, and STATE
-	process->pid       = pid;
-    process->ref_xp    = XPTR( local_cxy , process );
-    process->parent_xp = parent_xp;
-    process->state     = PROCESS_STATE_RUNNING;
+	process->pid        = pid;
+    process->ref_xp     = XPTR( local_cxy , process );
+    process->parent_xp  = parent_xp;
+    process->term_state = 0;
 
     // initialize vmm as empty 
@@ -137,6 +141,10 @@
     assert( (error == 0) , __FUNCTION__ , "cannot initialize VMM\n" );
  
-process_dmsg("\n[DBG] %s : core[%x,%d] / vmm inialised as empty for process %x\n", 
-__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
+#if (CONFIG_DEBUG_PROCESS_REFERENCE_INIT & 1)
+cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_REFERENCE_INIT )
+printk("\n[DBG] %s : thread %x / vmm empty for process %x / cycle %d\n", 
+__FUNCTION__ , CURRENT_THREAD , pid , cycle );
+#endif
 
     // initialize fd_array as empty
@@ -224,6 +232,10 @@
     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 );
+#if (CONFIG_DEBUG_PROCESS_REFERENCE_INIT & 1)
+cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_REFERENCE_INIT )
+printk("\n[DBG] %s : thread %x / fd_array for process %x / cycle %d\n", 
+__FUNCTION__ , CURRENT_THREAD , pid , cycle );
+#endif
 
     // reset children list root 
@@ -260,6 +272,10 @@
 	hal_fence();
 
-process_dmsg("\n[DBG] %s : core[%x,%d] exit for process %x\n",
-__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
+#if (CONFIG_DEBUG_PROCESS_REFERENCE_INIT & 1)
+cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_REFERENCE_INIT )
+printk("\n[DBG] %s : thread %x exit / process %x / cycle %d\n", 
+__FUNCTION__ , CURRENT_THREAD , pid , cycle );
+#endif
 
 }  // process_reference_init()
@@ -276,11 +292,15 @@
 
     // initialize PID, REF_XP, PARENT_XP, and STATE
-    local_process->pid       = hal_remote_lw(  XPTR( ref_cxy , &ref_ptr->pid ) );
-    local_process->parent_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->parent_xp ) );
-    local_process->ref_xp    = reference_process_xp;
-    local_process->state     = PROCESS_STATE_RUNNING;
-
-process_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x\n",
-__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , local_process->pid );
+    local_process->pid        = hal_remote_lw(  XPTR( ref_cxy , &ref_ptr->pid ) );
+    local_process->parent_xp  = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->parent_xp ) );
+    local_process->ref_xp     = reference_process_xp;
+    local_process->term_state = 0;
+
+#if CONFIG_DEBUG_PROCESS_COPY_INIT 
+uint32_t cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_COPY_INIT )
+printk("\n[DBG] %s : thread %x enter for process %x\n",
+__FUNCTION__ , CURRENT_THREAD , local_process->pid );
+#endif
 
     // reset local process vmm
@@ -327,6 +347,10 @@
 	hal_fence();
 
-process_dmsg("\n[DBG] %s : core[%x,%d] exit for process %x\n",
-__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , local_process->pid );
+#if CONFIG_DEBUG_PROCESS_COPY_INIT 
+cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_COPY_INIT )
+printk("\n[DBG] %s : thread %x exit for process %x\n",
+__FUNCTION__ , CURRENT_THREAD , local_process->pid );
+#endif
 
     return 0;
@@ -347,6 +371,10 @@
     "process %x in cluster %x has still active threads", process->pid , local_cxy );
 
-process_dmsg("\n[DBG] %s : core[%x,%d] enter for process %x\n",
-__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , process->pid );
+#if CONFIG_DEBUG_PROCESS_DESTROY
+uint32_t cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_DESTROY )
+printk("\n[DBG] %s : thread %x enter to destroy process %x (pid = %x) / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD , process, process->pid , cycle );
+#endif
 
     // get local process manager pointer
@@ -386,11 +414,4 @@
         xlist_unlink( XPTR( local_cxy , &process->children_list ) );
         remote_spinlock_unlock( children_lock_xp );
-
-        // get extende pointer on parent main thread
-        parent_thread_xp = XPTR( parent_cxy ,
-                           hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->th_tbl[1] )));
-        
-        // unblock parent process main thread
-        thread_unblock( parent_thread_xp , THREAD_BLOCKED_WAIT );
     }
 
@@ -411,6 +432,10 @@
     process_free( process );
 
-process_dmsg("\n[DBG] %s : core[%x,%d] exit for process %x\n",
-__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , process->pid );
+#if CONFIG_DEBUG_PROCESS_DESTROY
+cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_DESTROY )
+printk("\n[DBG] %s : thread %x exit / destroyed process %x (pid = %x) / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD , process, process->pid, cycle );
+#endif
 
 }  // end process_destroy()
@@ -440,12 +465,15 @@
     uint32_t           responses;         // number of remote process copies
     uint32_t           rsp_count;         // used to assert number of copies
-
     rpc_desc_t         rpc;               // rpc descriptor allocated in stack
 
-process_dmsg("\n[DBG] %s : enter to %s process %x in cluster %x\n",
-__FUNCTION__ , process_action_str( action_type ) , process->pid , local_cxy );
+#if CONFIG_DEBUG_PROCESS_SIGACTION
+uint32_t cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
+printk("\n[DBG] %s : thread %x enter to %s process %x in cluster %x / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD, process_action_str( action_type ) ,
+process->pid , local_cxy , cycle );
+#endif
 
     thread_t         * client = CURRENT_THREAD;
-    xptr_t             client_xp = XPTR( local_cxy , client );
 
     // get local pointer on local cluster manager
@@ -492,6 +520,8 @@
         {
 
-process_dmsg("\n[DBG] %s : send RPC to remote cluster %x\n",
-__FUNCTION__ , process_cxy );
+#if CONFIG_DEBUG_PROCESS_SIGACTION 
+if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
+printk("\n[DBG] %s : send RPC to remote cluster %x\n", __FUNCTION__ , process_cxy );
+#endif
 
             rpc.args[0] = (uint64_t)action_type;
@@ -517,33 +547,42 @@
     }
 
-process_dmsg("\n[DBG] %s : make action in owner cluster %x\n",
-__FUNCTION__ , local_cxy );
-
+#if CONFIG_DEBUG_PROCESS_SIGACTION
+if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
+printk("\n[DBG] %s : make action in owner cluster %x\n", __FUNCTION__ , local_cxy );
+#endif
 
     // call directly the relevant function in local owner cluster
-    if      (action_type == DELETE_ALL_THREADS  ) process_delete_threads ( process , client_xp ); 
-    else if (action_type == BLOCK_ALL_THREADS   ) process_block_threads  ( process , client_xp ); 
-    else if (action_type == UNBLOCK_ALL_THREADS ) process_unblock_threads( process             );
-
-process_dmsg("\n[DBG] %s : exit after %s process %x in cluster %x\n",
-__FUNCTION__ , process_action_str( action_type ) , process->pid , local_cxy );
+    if      (action_type == DELETE_ALL_THREADS  ) process_delete_threads ( process ); 
+    else if (action_type == BLOCK_ALL_THREADS   ) process_block_threads  ( process ); 
+    else if (action_type == UNBLOCK_ALL_THREADS ) process_unblock_threads( process );
+
+#if CONFIG_DEBUG_PROCESS_SIGACTION
+cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
+printk("\n[DBG] %s : thread %x exit after %s process %x in cluster %x / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD, process_action_str( action_type ) ,
+process->pid , local_cxy , cycle );
+#endif
 
 }  // end process_sigaction()
 
-////////////////////////////////////////////////
-void process_block_threads( process_t * process,
-                            xptr_t      client_xp )
+/////////////////////////////////////////////////
+void process_block_threads( process_t * process )
 {
     thread_t          * target;         // pointer on target thread 
+    thread_t          * this;           // pointer on calling thread 
     uint32_t            ltid;           // index in process th_tbl
-    thread_t          * requester;      // requesting thread pointer
     uint32_t            count;          // requests counter
     volatile uint32_t   rsp_count;      // responses counter
 
     // get calling thread pointer
-    requester = CURRENT_THREAD;
-
-sigaction_dmsg("\n[DBG] %s : enter for process %x in cluster %x\n",
-__FUNCTION__ , process->pid , local_cxy );
+    this = CURRENT_THREAD;
+
+#if CONFIG_DEBUG_PROCESS_SIGACTION
+uint32_t cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
+printk("\n[DBG] %s : thread %x enter for process %x in cluster %x / cycle %d\n",
+__FUNCTION__ , this , process->pid , local_cxy , cycle );
+#endif
 
     // get lock protecting process th_tbl[]
@@ -559,10 +598,10 @@
         target = process->th_tbl[ltid];
 
+        assert( (target != this) , __FUNCTION__ , "calling thread cannot be a target\n" );
+
         if( target != NULL )             // thread found
         {
             count++;
 
-            // - if the target thread is the client thread, we do nothing,
-            //   and we simply decrement the responses counter.
             // - if the calling thread and the target thread are on the same core,
             //   we block the target thread, we don't need confirmation from scheduler,
@@ -572,10 +611,5 @@
             //   to be sure that the target thread is not running.
             
-            if( XPTR( local_cxy , target ) == client_xp )
-            {
-                // decrement responses counter
-                hal_atomic_add( (void *)&rsp_count , -1 );
-            }
-            else if( requester->core->lid == target->core->lid )
+            if( this->core->lid == target->core->lid )
             {
                 // set the global blocked bit in target thread descriptor.
@@ -612,6 +646,10 @@
     }
 
-sigaction_dmsg("\n[DBG] %s : exit for process %x in cluster %x / %d threads blocked\n",
-__FUNCTION__ , process->pid , local_cxy , count );
+#if CONFIG_DEBUG_PROCESS_SIGACTION
+cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
+printk("\n[DBG] %s : thread %x exit for process %x in cluster %x / cycle %d\n",
+__FUNCTION__ , this , process->pid , local_cxy , cycle );
+#endif
 
 }  // end process_block_threads()
@@ -621,9 +659,17 @@
 {
     thread_t          * target;        // pointer on target thead 
+    thread_t          * this;          // pointer on calling thread 
     uint32_t            ltid;          // index in process th_tbl
     uint32_t            count;         // requests counter
 
-sigaction_dmsg("\n[DBG] %s : enter for process %x in cluster %x\n",
-__FUNCTION__ , process->pid , local_cxy );
+    // get calling thread pointer
+    this = CURRENT_THREAD;
+
+#if CONFIG_DEBUG_PROCESS_SIGACTION
+uint32_t cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
+printk("\n[DBG] %s : thread %x enter for process %x in cluster %x / cycle %d\n",
+__FUNCTION__ , this , process->pid , local_cxy , cycle );
+#endif
 
     // get lock protecting process th_tbl[]
@@ -636,4 +682,6 @@
         target = process->th_tbl[ltid];
 
+        assert( (target != this) , __FUNCTION__ , "calling thread cannot be a target\n" );
+
         if( target != NULL )             // thread found
         {
@@ -648,19 +696,32 @@
     spinlock_unlock( &process->th_lock );
 
-sigaction_dmsg("\n[DBG] %s : exit for process %x in cluster %x / %d threads blocked\n",
-__FUNCTION__ , process->pid , local_cxy , count );
+#if CONFIG_DEBUG_PROCESS_SIGACTION
+cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
+printk("\n[DBG] %s : thread %x exit for process %x in cluster %x / cycle %d\n",
+__FUNCTION__ , this , process->pid , local_cxy , cycle );
+#endif
 
 }  // end process_unblock_threads()
 
-/////////////////////////////////////////////////
-void process_delete_threads( process_t * process,
-                             xptr_t      client_xp )
+//////////////////////////////////////////////////
+void process_delete_threads( process_t * process )
 {
     thread_t          * target;        // pointer on target thread 
+    thread_t          * this;          // pointer on calling thread 
     uint32_t            ltid;          // index in process th_tbl
     uint32_t            count;         // request counter
-
-sigaction_dmsg("\n[DBG] %s : enter for process %x in cluster %x at cycle %d\n",
-__FUNCTION__ , process->pid , local_cxy , (uint32_t)hal_get_cycles() );
+    cxy_t               owner_cxy;     // owner cluster identifier
+
+    // get calling thread pointer
+    this = CURRENT_THREAD;
+    owner_cxy = CXY_FROM_PID( process->pid );
+
+#if CONFIG_DEBUG_PROCESS_SIGACTION
+uint32_t cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
+printk("\n[DBG] %s : thread %x enter for process %x in cluster %x / cycle %d\n",
+__FUNCTION__ , this , process->pid , local_cxy , cycle );
+#endif
 
     // get lock protecting process th_tbl[]
@@ -673,11 +734,13 @@
         target = process->th_tbl[ltid];
 
-        if( target != NULL )             // thread found
+        assert( (target != this) , __FUNCTION__ , "calling thread cannot be a target\n" );
+
+        if( target != NULL )            // thread found
         {
             count++;
-
-            // delete only if the target is not the client
-            if( XPTR( local_cxy , target ) != client_xp ) 
-            { 
+            
+            // the main thread should not be deleted
+            if( (owner_cxy != local_cxy) || (ltid != 0) )   
+            {
                 hal_atomic_or( &target->flags , THREAD_FLAG_REQ_DELETE );
             }
@@ -688,6 +751,10 @@
     spinlock_unlock( &process->th_lock );
 
-sigaction_dmsg("\n[DBG] %s : exit for process %x in cluster %x at cycle %d\n",
-__FUNCTION__ , process->pid , local_cxy , (uint32_t)hal_get_cycles() );
+#if CONFIG_DEBUG_PROCESS_SIGACTION
+cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_SIGACTION < cycle )
+printk("\n[DBG] %s : thread %x exit for process %x in cluster %x / cycle %d\n",
+__FUNCTION__ , this , process->pid , local_cxy , cycle );
+#endif
 
 }  // end process_delete_threads()
@@ -988,6 +1055,10 @@
     "parent process must be the reference process\n" );
 
-fork_dmsg("\n[DBG] %s : core[%x,%d] enter at cycle %d\n",
-__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid , (uint32_t)hal_get_cycles() );
+#if CONFIG_DEBUG_PROCESS_MAKE_FORK
+uint32_t cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_MAKE_FORK < cycle )
+printk("\n[DBG] %s : thread %x enter for process %x / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD, parent_pid, cycle );
+#endif
 
     // allocate a process descriptor
@@ -999,7 +1070,4 @@
         return -1;
     }
-
-fork_dmsg("\n[DBG] %s : core[%x,%d] created child process %x at cycle %d\n",
- __FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, process, (uint32_t)hal_get_cycles() );
 
     // allocate a child PID from local cluster
@@ -1012,7 +1080,4 @@
         return -1;
     }
-
-fork_dmsg("\n[DBG] %s : core[%x, %d] child process PID = %x at cycle %d\n",
- __FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, new_pid , (uint32_t)hal_get_cycles() );
 
     // initializes child process descriptor from parent process descriptor 
@@ -1022,6 +1087,10 @@
                             parent_process_xp );
 
-fork_dmsg("\n[DBG] %s : core[%x, %d] child process initialised at cycle %d\n",
-__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, hal_get_cycles() );
+#if CONFIG_DEBUG_PROCESS_MAKE_FORK
+cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_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
 
     // copy VMM from parent descriptor to child descriptor
@@ -1037,6 +1106,10 @@
     }
 
-fork_dmsg("\n[DBG] %s : core[%x, %d] child process VMM copied at cycle %d\n",
-__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, (uint32_t)hal_get_cycles() );
+#if CONFIG_DEBUG_PROCESS_MAKE_FORK
+cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_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
 
     // update extended pointer on .elf file
@@ -1059,8 +1132,12 @@
     assert( (thread->trdid == 0) , __FUNCTION__ , "main thread must have index 0\n" );
 
-fork_dmsg("\n[DBG] %s : core[%x,%d] child thread created at cycle %d\n", 
-__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, (uint32_t)hal_get_cycles() );
-
-    // update parent process GPT to set Copy_On_Write for shared data vsegs 
+#if CONFIG_DEBUG_PROCESS_MAKE_FORK
+cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_MAKE_FORK < cycle )
+printk("\n[DBG] %s : thread %x created child thread %x / cycle %d\n", 
+__FUNCTION__ , CURRENT_THREAD, thread, cycle );
+#endif
+
+    // set Copy_On_Write flag in parent process GPT 
     // this includes all replicated GPT copies
     if( parent_process_cxy == local_cxy )   // reference is local
@@ -1074,6 +1151,13 @@
     }
 
-fork_dmsg("\n[DBG] %s : core[%x,%d] COW set in parent_process at cycle %d\n",
-__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, (uint32_t)hal_get_cycles() );
+    // set Copy_On_Write flag in child process GPT 
+    vmm_set_cow( process );
+ 
+#if CONFIG_DEBUG_PROCESS_MAKE_FORK
+cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_MAKE_FORK < cycle )
+printk("\n[DBG] %s : thread %x set COW in parent and child / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD, cycle );
+#endif
 
     // get extended pointers on parent children_root, children_lock and children_nr
@@ -1092,7 +1176,10 @@
     *child_pid    = new_pid;
 
-
-fork_dmsg("\n[DBG] %s : core[%x,%d] exit at cycle %d\n",
-__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, (uint32_t)hal_get_cycles() );
+#if CONFIG_DEBUG_PROCESS_MAKE_FORK
+cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_MAKE_FORK < cycle )
+printk("\n[DBG] %s : thread %x exit / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD, cycle );
+#endif
 
     return 0;
@@ -1105,32 +1192,37 @@
 {
     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 
+    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 main thread
-    pthread_attr_t   attr;                    // main thread attributes
+    thread_t       * new_thread;              // local pointer on new thread
+    xptr_t           parent_xp;               // extended pointer on parent process
+    pthread_attr_t   attr;                    // new thread attributes
     lid_t            lid;                     // selected core local index
 	error_t          error;
 
-	// get .elf pathname and PID from exec_info
+    // get old_thread / old_process / PID / parent_xp
+    old_thread  = CURRENT_THREAD;
+    old_process = old_thread->process;
+    pid         = old_process->pid;
+    parent_xp   = old_process->parent_xp;
+    
+	// get .elf pathname from exec_info
 	path     = exec_info->path;
-    pid      = exec_info->pid;
 
     // this function must be executed by a thread running in owner cluster
     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 / %s / cycle %d\n",
-__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid, path, (uint32_t)hal_get_cycles() );
-
-    // get old_process local pointer
-    old_process = (process_t *)cluster_get_local_process_from_pid( pid );
-    
-    if( old_process == NULL )
-    {
-        printk("\n[ERROR] in %s : cannot get old process descriptor\n", __FUNCTION__ );
-        return -1;
-    }
+    "local_cluster must be owner_cluster\n" );
+
+    assert( (LTID_FROM_TRDID( old_thread->trdid ) == 0) , __FUNCTION__,
+    "must be called by the main thread\n" );
+ 
+#if CONFIG_DEBUG_PROCESS_MAKE_EXEC
+uint32_t cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_MAKE_EXEC < cycle )
+printk("\n[DBG] %s : thread %x enters for process %x / %s / cycle %d\n",
+__FUNCTION__, old_thread, pid, path, cycle );
+#endif
 
      // allocate memory for new_process descriptor
@@ -1144,5 +1236,5 @@
     }
 
-    // get a new PID for old_process
+    // get a temporary PID for old_process
     error = cluster_pid_alloc( old_process , &temp_pid );
     if( error ) 
@@ -1154,14 +1246,5 @@
     }
 
-    // request blocking for all threads in old_process (but the calling thread)
-    process_sigaction( old_process , BLOCK_ALL_THREADS );
-
-    // request destruction for all threads in old_process (but the calling thread)
-    process_sigaction( old_process , DELETE_ALL_THREADS );
-
-exec_dmsg("\n[DBG] %s : core[%x,%d] marked old threads for destruction / cycle %d\n",
-__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid , (uint32_t)hal_get_cycles() );
-
-    // set new PID to old_process 
+    // set temporary PID to old_process 
     old_process->pid = temp_pid;
 
@@ -1169,12 +1252,16 @@
     process_reference_init( new_process,
                             pid,
-                            old_process->parent_xp,             // parent_process_xp
-                            XPTR(local_cxy , old_process) );    // model_process_xp
+                            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 ) );
 
-exec_dmsg("\n[DBG] %s : core[%x,%d] initialised new process %x / cycle %d \n",
-__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, new_process, (uint32_t)hal_get_cycles() );
+#if CONFIG_DEBUG_PROCESS_MAKE_EXEC
+cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_MAKE_EXEC < cycle )
+printk("\n[DBG] %s : thread %x created new process %x / cycle %d \n",
+__FUNCTION__ , old_thread , new_process , cycle );
+#endif
 
     // register code & data vsegs as well as entry-point in new process VMM,
@@ -1188,6 +1275,10 @@
 	}
 
-exec_dmsg("\n[DBG] %s : core[%x,%d] vsegs registered in new process %x / cycle %d\n",
-__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, new_process, (uint32_t)hal_get_cycles() );
+#if CONFIG_DEBUG_PROCESS_MAKE_EXEC
+cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_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
@@ -1216,9 +1307,12 @@
     assert( (new_thread->trdid == 0) , __FUNCTION__ , "main thread must have index 0\n" );
 
-exec_dmsg("\n[DBG] %s : core[%x,%d] created new_process main thread / cycle %d\n",
-__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, (uint32_t)hal_get_cycles() );
-
-    // get pointers on parent process
-    xptr_t      parent_xp  = new_process->parent_xp;
+#if CONFIG_DEBUG_PROCESS_MAKE_EXEC
+cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_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
+
+    // get cluster and local pointer on parent process
     process_t * parent_ptr = GET_PTR( parent_xp );
     cxy_t       parent_cxy = GET_CXY( parent_xp );
@@ -1235,130 +1329,82 @@
     remote_spinlock_unlock( lock_xp );
 
-exec_dmsg("\n[DBG] %s : core[%x,%d] updated parent process children list / cycle %d\n",
-__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, (uint32_t)hal_get_cycles() );
-   
-    // block and mark calling thread for deletion
-    // only when it is an user thread
-    thread_t * this = CURRENT_THREAD;
-    if( this->type == THREAD_USER )
-    {
-        thread_block( this , THREAD_BLOCKED_GLOBAL );
-        hal_atomic_or( &this->flags , THREAD_FLAG_REQ_DELETE );
-    }
-
     // activate new thread
 	thread_unblock( XPTR( local_cxy , new_thread ) , THREAD_BLOCKED_GLOBAL );
 
+    // request old_thread destruction => old_process destruction
+    thread_block( old_thread , THREAD_BLOCKED_GLOBAL );
+    hal_atomic_or( &old_thread->flags , THREAD_FLAG_REQ_DELETE );
+
     hal_fence();
 
-exec_dmsg("\n[DBG] %s : core[%x,%d] exit for path = %s / cycle %d\n",
-__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path , (uint32_t)hal_get_cycles() );
-
+#if CONFIG_DEBUG_PROCESS_MAKE_EXEC
+cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_MAKE_EXEC < cycle )
+printk("\n[DBG] %s : old_thread %x blocked / new_thread %x activated / cycle %d\n",
+__FUNCTION__ , old_thread , new_thread , cycle );
+#endif
+   
 	return 0;
 
 }  // end process_make_exec()
 
-///////////////////////////////////////
-void process_make_kill( pid_t      pid,
-                        uint32_t   sig_id )
-{
-    // this function must be executed by a thread running in owner cluster
-    assert( (CXY_FROM_PID( pid ) == local_cxy) , __FUNCTION__ ,
-    "must execute in owner cluster" );
-
+////////////////////////////////////////////
+void process_make_kill( process_t * process,
+                        bool_t      is_exit,
+                        uint32_t    exit_status )
+{
     thread_t * this = CURRENT_THREAD;
 
-kill_dmsg("\n[DBG] %s : core[%x,%d] enter / process %x / sig %d\n",
-__FUNCTION__, local_cxy, this->core->lid, pid , sig_id );
-
-    // get pointer on local target process descriptor
-    process_t * process = process_get_local_copy( pid );
-
-    // does nothing if process does not exist
-    if( process == NULL )
-    {
-        printk("\n[WARNING] %s : process %x does not exist => do nothing\n",
-        __FUNCTION__ , pid );
-        return;
-    }
-
-    // analyse signal type
-    switch( sig_id )
-    {
-        case SIGSTOP:     
-        {
-            // block all threads in all clusters
-            process_sigaction( process , BLOCK_ALL_THREADS );
-
-            // remove TXT ownership to target process 
-            process_txt_reset_ownership( XPTR( local_cxy , process ) );
-        }
-        break;
-        case SIGCONT:     // unblock all threads in all clusters
-        {
-            process_sigaction( process , UNBLOCK_ALL_THREADS );
-        }
-        break;
-        case SIGKILL:  // block all threads, then delete all threads
-        {
-            // block all threads in all clusters
-            process_sigaction( process , BLOCK_ALL_THREADS );
-
-            // remove TXT ownership to target process 
-            process_txt_reset_ownership( XPTR( local_cxy , process ) );
-
-            // delete all threads (but the calling thread)
-            process_sigaction( process , DELETE_ALL_THREADS );
-
-            // delete the calling thread if required
-            if( CURRENT_THREAD->process == process )
-            {
-                // set REQ_DELETE flag
-                hal_atomic_or( &this->flags , THREAD_FLAG_REQ_DELETE );
-
-                // deschedule
-                sched_yield( "suicide after kill" ); 
-            }
-        }
-        break;
-    }
-
-kill_dmsg("\n[DBG] %s : core[%x,%d] exit / process %x / sig %d \n",
-__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid , sig_id );
+    assert( (CXY_FROM_PID( process->pid ) == local_cxy) , __FUNCTION__ ,
+    "must be executed in process owner cluster\n" );
+
+    assert( ( this->type == THREAD_RPC ) , __FUNCTION__ ,
+    "must be executed by an RPC thread\n" );
+
+#if CONFIG_DEBUG_PROCESS_MAKE_KILL
+uint32_t cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_MAKE_KILL < cycle )
+printk("\n[DBG] %s : thread %x enter for process %x / cycle %d\n",
+__FUNCTION__, this , process->pid , cycle );
+#endif
+
+    // register exit_status in owner process descriptor
+    if( is_exit ) process->term_state = exit_status;
+
+    // atomically update owner process descriptor flags
+    if( is_exit ) hal_atomic_or( &process->term_state , PROCESS_FLAG_EXIT );
+    else          hal_atomic_or( &process->term_state , PROCESS_FLAG_KILL );
+
+    // remove TXT ownership from owner process descriptor
+    process_txt_reset_ownership( XPTR( local_cxy , process ) );
+
+    // block all process threads in all clusters
+    process_sigaction( process , BLOCK_ALL_THREADS );
+
+    // mark all process threads in all clusters for delete 
+    process_sigaction( process , DELETE_ALL_THREADS );
+
+/* unused if sys_wait deschedules without blocking [AG]
+
+    // get cluster and pointers on reference parent process
+    xptr_t      parent_xp  = process->parent_xp;
+    process_t * parent_ptr = GET_PTR( parent_xp );
+    cxy_t       parent_cxy = GET_CXY( parent_xp );
+
+    // get loal pointer on parent main thread
+    thread_t * main_ptr = hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->th_tbl[0] ) );
+ 
+    // reset THREAD_BLOCKED_WAIT bit in parent process main thread
+    thread_unblock( XPTR( parent_cxy , main_ptr ) , THREAD_BLOCKED_WAIT );
+*/
+
+#if CONFIG_DEBUG_PROCESS_MAKE_KILL
+cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_MAKE_KILL < cycle )
+printk("\n[DBG] %s : thread %x exit for process %x / cycle %d\n",
+__FUNCTION__, this, process->pid , cycle );
+#endif
 
 }  // end process_make_kill()
-
-/////////////////////////////////////////
-void process_make_exit( pid_t       pid,
-                        uint32_t    status )
-{
-    // this function must be executed by a thread running in owner cluster
-    assert( (CXY_FROM_PID( pid ) == local_cxy) , __FUNCTION__ ,
-    "must execute in owner cluster" );
-
-    // get pointer on local process descriptor
-    process_t * process = process_get_local_copy( pid );
-
-    // does nothing if process does not exist
-    if( process == NULL )
-    {
-        printk("\n[WARNING] %s : process %x does not exist => do nothing\n",
-        __FUNCTION__ , pid );
-        return;
-    }
-
-    // block all threads in all clusters (but the calling thread)
-    process_sigaction( process , BLOCK_ALL_THREADS );
-
-    // delete all threads in all clusters (but the calling thread)
-    process_sigaction( process , DELETE_ALL_THREADS );
-
-    // delete the calling thread 
-    hal_atomic_or( &CURRENT_THREAD->flags , THREAD_FLAG_REQ_DELETE );
-
-    // deschedule
-    sched_yield( "suicide after exit" ); 
-
-}  // end process_make_exit()
 
 ///////////////////////////////////////////////
@@ -1366,12 +1412,15 @@
 {
 
-process_dmsg("\n[DBG] %s : core[%x,%d] enter at cycle %d\n",
-__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, (uint32_t)hal_get_cycles() );
+#if CONFIG_DEBUG_PROCESS_ZERO_CREATE
+uint32_t cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_ZERO_CREATE < cycle )
+printk("\n[DBG] %s : thread %x enter / cycle %d\n", __FUNCTION__, CURRENT_THREAD, cycle );
+#endif
 
     // initialize PID, REF_XP, PARENT_XP, and STATE
-    process->pid       = 0;
-    process->ref_xp    = XPTR( local_cxy , process );
-    process->parent_xp = XPTR_NULL;
-    process->state     = PROCESS_STATE_RUNNING;
+    process->pid        = 0;
+    process->ref_xp     = XPTR( local_cxy , process );
+    process->parent_xp  = XPTR_NULL;
+    process->term_state = 0;
 
     // reset th_tbl[] array as empty
@@ -1391,6 +1440,9 @@
 	hal_fence();
 
-process_dmsg("\n[DBG] %s : core[%x,%d] exit at cycle %d\n",
-__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , (uint32_t)hal_get_cycles() );
+#if CONFIG_DEBUG_PROCESS_ZERO_CREATE
+cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_ZERO_CREATE < cycle )
+printk("\n[DBG] %s : thread %x exit / cycle %d\n", __FUNCTION__, CURRENT_THREAD, cycle );
+#endif
 
 }  // end process_zero_init()
@@ -1406,6 +1458,9 @@
     error_t          error;
 
-process_dmsg("\n[DBG] %s :  core[%x,%d] enters at cycle %d\n", 
-__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid );
+#if CONFIG_DEBUG_PROCESS_INIT_CREATE
+uint32_t cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_INIT_CREATE < cycle )
+printk("\n[DBG] %s : thread %x enter / cycle %d\n", __FUNCTION__, CURRENT_THREAD, cycle );
+#endif
 
     // allocates memory for process descriptor from local cluster
@@ -1434,7 +1489,4 @@
                             XPTR( local_cxy , &process_zero ),     // parent
                             XPTR( local_cxy , &process_zero ) );   // model
-
-process_dmsg("\n[DBG] %s : core[%x,%d] / initialisation done\n", 
-__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid );
 
     // register "code" and "data" vsegs as well as entry-point
@@ -1446,7 +1498,4 @@
         process_destroy( process );
 	}
-
-process_dmsg("\n[DBG] %s : core[%x,%d] vsegs registered / path = %s\n",
-__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, CONFIG_PROCESS_INIT_PATH );
 
     // get extended pointers on process_zero children_root, children_lock
@@ -1489,17 +1538,11 @@
     hal_fence();
 
-process_dmsg("\n[DBG] %s : core[%x,%d] exit / main thread = %x\n",
-__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, thread );
+#if CONFIG_DEBUG_PROCESS_INIT_CREATE
+cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_INIT_CREATE < cycle )
+printk("\n[DBG] %s : thread %x exit / cycle %d\n", __FUNCTION__, CURRENT_THREAD, cycle );
+#endif
 
 }  // end process_init_create()
-
-//////////////////////////////////////////
-char * process_state_str( uint32_t state )
-{
-    if     ( state == PROCESS_STATE_RUNNING ) return "RUNNING";
-    else if( state == PROCESS_STATE_KILLED  ) return "KILLED";
-    else if( state == PROCESS_STATE_EXITED  ) return "EXITED";
-    else                                      return "undefined";
-}
 
 /////////////////////////////////////////
@@ -1542,5 +1585,5 @@
     // get PID and state
     pid   = hal_remote_lw( XPTR( process_cxy , &process_ptr->pid ) );
-    state = hal_remote_lw( XPTR( process_cxy , &process_ptr->state ) );
+    state = hal_remote_lw( XPTR( process_cxy , &process_ptr->term_state ) );
 
     // get PPID
@@ -1577,11 +1620,11 @@
     if( owner_xp == process_xp )
     {
-        printk("PID %X | PPID %X | %s\t| %s (FG) | %X | %d | %s\n", 
-        pid, ppid, process_state_str(state), txt_name, process_ptr, th_nr, elf_name );
+        printk("PID %X | PPID %X | STS %X | %s (FG) | %X | %d | %s\n", 
+        pid, ppid, state, txt_name, process_ptr, th_nr, elf_name );
     }
     else
     {
-        printk("PID %X | PPID %X | %s\t| %s (BG) | %X | %d | %s\n", 
-        pid, ppid, process_state_str(state), txt_name, process_ptr, th_nr, elf_name );
+        printk("PID %X | PPID %X | STS %X | %s (BG) | %X | %d | %s\n", 
+        pid, ppid, state, txt_name, process_ptr, th_nr, elf_name );
     }
 }  // end process_display() 
@@ -1632,6 +1675,10 @@
     xptr_t      lock_xp;      // extended pointer on list lock in chdev
 
-process_dmsg("\n[DBG] %s : core[%x,%d] enter for process %x at cycle\n",
-__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, process->pid, (uint32_t)hal_get_cycles() );
+#if CONFIG_DEBUG_PROCESS_TXT_ATTACH
+uint32_t cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_TXT_ATTACH < 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 reference
@@ -1657,6 +1704,10 @@
     remote_spinlock_unlock( lock_xp );
 
-process_dmsg("\n[DBG] %s : core[%x,%d] exit for process %x at cycle\n",
-__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, process->pid, (uint32_t)hal_get_cycles() );
+#if CONFIG_DEBUG_PROCESS_TXT_ATTACH
+cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_TXT_ATTACH < 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 );
+#endif
 
 } // end process_txt_attach()
@@ -1670,6 +1721,10 @@
     xptr_t      lock_xp;      // extended pointer on list lock in chdev
 
-process_dmsg("\n[DBG] %s : core[%x,%d] enter for process %x at cycle\n",
-__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, process->pid, (uint32_t)hal_get_cycles() );
+#if CONFIG_DEBUG_PROCESS_TXT_DETACH
+uint32_t cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_TXT_DETACH < cycle )
+printk("\n[DBG] %s : thread %x enter for process %x / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD, process->pid , cycle );
+#endif
 
     // check process is reference
@@ -1690,6 +1745,10 @@
     remote_spinlock_unlock( lock_xp );
    
-process_dmsg("\n[DBG] %s : core[%x,%d] exit for process %x at cycle %d\n",
-__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, process->pid, (uint32_t)hal_get_cycles() );
+#if CONFIG_DEBUG_PROCESS_TXT_DETACH
+cycle = (uint32_t)hal_get_cycles();
+if( CONFIG_DEBUG_PROCESS_TXT_DETACH < cycle )
+printk("\n[DBG] %s : thread %x exit for process %x / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD, process->pid, cycle );
+#endif
 
 } // end process_txt_detach()
@@ -1732,13 +1791,14 @@
     xptr_t      file_xp;         // extended pointer on TXT_RX pseudo file
     xptr_t      txt_xp;          // extended pointer on TXT_RX chdev
-    chdev_t   * txt_ptr;
-    cxy_t       txt_cxy;
+    chdev_t   * txt_ptr;         // local pointer on TXT_RX chdev
+    cxy_t       txt_cxy;         // cluster of TXT_RX chdev
+    uint32_t    txt_id;          // TXT_RX channel 
     xptr_t      owner_xp;        // extended pointer on current TXT_RX owner
     xptr_t      root_xp;         // extended pointer on root of attached process list
     xptr_t      iter_xp;         // iterator for xlist
     xptr_t      current_xp;      // extended pointer on current process
-    process_t * current_ptr;
-    cxy_t       current_cxy;
-    pid_t       ppid;
+    process_t * current_ptr;     // local pointer on current process
+    cxy_t       current_cxy;     // cluster for current process
+    pid_t       ppid;            // parent process identifier for current process
 
     // get cluster and local pointer on process
@@ -1752,11 +1812,12 @@
     txt_xp  = chdev_from_file( file_xp );
     txt_cxy = GET_CXY( txt_xp );
-    txt_ptr = (chdev_t *)GET_PTR( txt_xp );
-
-    // get extended pointer on TXT_RX owner
+    txt_ptr = GET_PTR( txt_xp );
+
+    // get extended pointer on TXT_RX owner and TXT channel
     owner_xp = hal_remote_lwd( XPTR( txt_cxy , &txt_ptr->ext.txt.owner_xp ) );
+    txt_id   = hal_remote_lw ( XPTR( txt_cxy , &txt_ptr->channel ) );
 
     // transfer ownership to KSH if required
-    if( owner_xp == process_xp )   
+    if( (owner_xp == process_xp) && (txt_id > 0) )   
     {
         // get extended pointer on root of list of attached processes
@@ -1782,8 +1843,7 @@
             }
         }
-    }
-
-    assert( false , __FUNCTION__ , "KSH process not found" ); 
-
+
+        assert( false , __FUNCTION__ , "KSH process not found" ); 
+    }
 }  // end process_txt_reset_ownership()
 
