Index: trunk/kernel/kern/process.c
===================================================================
--- trunk/kernel/kern/process.c	(revision 415)
+++ trunk/kernel/kern/process.c	(revision 416)
@@ -337,11 +337,7 @@
     pmgr_t * pmgr = &LOCAL_CLUSTER->pmgr;
 
-    // get the lock protecting the list of local process descriptors
+    // remove the process descriptor from local_list in cluster manager
     remote_spinlock_lock( XPTR( local_cxy , &pmgr->local_lock ) );
-
-    // remove the process descriptor from local_list in local cluster manager
     xlist_unlink( XPTR( local_cxy , &process->local_list ) );
-
-    // release the lock protecting the list of local process descriptors
     remote_spinlock_unlock( XPTR( local_cxy , &pmgr->local_lock ) );
 
@@ -356,4 +352,7 @@
     remote_spinlock_unlock( copies_lock );
 
+    // release the process PID to cluster manager
+    cluster_pid_release( process->pid );
+
 	hal_fence();
 
@@ -370,6 +369,6 @@
     vmm_destroy( process );
 
-	process_dmsg("\n[DBG] %s for pid %d / page_faults = %d\n",
-	         __FUNCTION__ , process->pid, process->vmm.pgfault_nr );
+    // release memory allocated to process descriptor
+    process_free( process );
 
 }  // end process_destroy()
@@ -393,20 +392,21 @@
     xptr_t             root_xp;           // extended pointer on root of copies
     xptr_t             lock_xp;           // extended pointer on lock protecting copies
-    xptr_t             client_xp;         // extended pointer on client thread
-    uint32_t           rsp_count;         // number of expected responses
-    xptr_t             rsp_xp;            // extended pointer on responses counter
     xptr_t             iter_xp;           // iterator on copies list
     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
-
-sigaction_dmsg("\n[DBG] %s : enter for signal %s to process %x in cluster %x\n",
-__FUNCTION__ , process_action_str( action_type ) , process , local_cxy );
-
-    thread_t         * this = CURRENT_THREAD;
-
-    // get extended pointer on client thread and response counter
-    client_xp = XPTR( local_cxy , this );
-    rsp_xp    = XPTR( local_cxy , &rsp_count );
+    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
+
+sigaction_dmsg("\n[DBG] %s : enter to %s process %x in cluster %x\n",
+__FUNCTION__ , process_action_str( action_type ) , process->pid , local_cxy );
+
+    thread_t         * client = CURRENT_THREAD;
+    xptr_t             client_xp = XPTR( local_cxy , client );
+
+    // get local pointer on local cluster manager
+    cluster = LOCAL_CLUSTER;
 
     // get owner cluster identifier and process lpid
@@ -414,8 +414,23 @@
     lpid      = LPID_FROM_PID( process->pid );
 
-    assert( (owner_cxy == local_cxy) , __FUNCTION__ , "illegal cluster\n" ); 
+    // check owner cluster
+    assert( (owner_cxy == local_cxy) , __FUNCTION__ ,
+    "must be executed in the owner cluster\n" ); 
    
-    // get local pointer on local cluster manager
-    cluster = LOCAL_CLUSTER;
+    // get number of remote copies
+    responses = cluster->pmgr.copies_nr[lpid] - 1;
+    rsp_count = 0;
+
+    // check action type
+    assert( ((action_type == DELETE_ALL_THREADS ) ||
+             (action_type == BLOCK_ALL_THREADS )  ||
+             (action_type == UNBLOCK_ALL_THREADS )),
+             __FUNCTION__ , "illegal action type" );
+             
+    // initialise rpc descriptor
+    rpc.index    = RPC_PROCESS_SIGACTION;
+    rpc.response = responses;
+    rpc.blocking = false;
+    rpc.thread   = client;
 
     // get extended pointers on copies root, copies lock, and number of copies
@@ -423,11 +438,8 @@
     lock_xp   = XPTR( local_cxy , &cluster->pmgr.copies_lock[lpid] );
 
-    // initialize responses number 
-    rsp_count = cluster->pmgr.copies_nr[lpid];
-
     // take the lock protecting the copies
     remote_spinlock_lock( lock_xp );
 
-    // send RPCs to all process copies
+    // send RPCs to remote clusters
     XLIST_FOREACH( root_xp , iter_xp )
     {
@@ -436,12 +448,16 @@
         process_ptr = (process_t *)GET_PTR( process_xp );
 
-sigaction_dmsg("\n[DBG] %s : process = %x / pid = %x / ppid = %x\n",
-__FUNCTION__ , process_ptr , process_ptr->pid , process_ptr->ppid );
-
-        rpc_process_sigaction_client( process_cxy, 
-                                      process_ptr,
-                                      action_type,
-                                      rsp_xp,
-                                      client_xp );
+        // send RPC to remote clusters
+        if( process_cxy != local_cxy )  
+        {
+
+sigaction_dmsg("\n[DBG] %s : send RPC to remote cluster %x\n",
+__FUNCTION__ , process_cxy );
+
+            rpc.args[0] = (uint64_t)action_type;
+            rpc.args[1] = (uint64_t)(intptr_t)process_ptr;
+            rpc_process_sigaction_client( process_cxy , &rpc );
+            rsp_count++;
+        }
     }
    
@@ -449,10 +465,27 @@
     remote_spinlock_unlock( lock_xp );
 
-    // block and deschedule to wait response
-    thread_block( CURRENT_THREAD , THREAD_BLOCKED_RPC );
-    sched_yield("BLOCKED on RPC");
-
-sigaction_dmsg("\n[DBG] %s : exit for signal %s to process %x in cluster %x\n",
-__FUNCTION__ , process_action_str( action_type ) , process , local_cxy );
+    // check number of copies...
+    assert( (rsp_count == responses) , __FUNCTION__ ,
+    "unconsistent number of process copies : rsp_count = %d / responses = %d",
+    rsp_count , responses );
+
+    // block and deschedule to wait RPC responses if required
+    if( responses )
+    {   
+        thread_block( CURRENT_THREAD , THREAD_BLOCKED_RPC );
+        sched_yield("BLOCKED on RPC_PROCESS_SIGACTION");
+    }
+
+sigaction_dmsg("\n[DBG] %s : make action in owner cluster %x\n",
+__FUNCTION__ , local_cxy );
+
+
+    // call directly the relevant function in local owner cluster
+    if      (action_type == DELETE_ALL_THREADS  ) process_delete ( process , client_xp ); 
+    else if (action_type == BLOCK_ALL_THREADS   ) process_block  ( process , client_xp ); 
+    else if (action_type == UNBLOCK_ALL_THREADS ) process_unblock( process             );
+
+sigaction_dmsg("\n[DBG] %s : exit after %s process %x in cluster %x\n",
+__FUNCTION__ , process_action_str( action_type ) , process->pid , local_cxy );
 
 }  // end process_sigaction()
@@ -460,18 +493,14 @@
 ////////////////////////////////////////
 void process_block( process_t * process,
-                    xptr_t      rsp_xp,
                     xptr_t      client_xp )
 {
     thread_t          * target;         // pointer on target thread 
     uint32_t            ltid;           // index in process th_tbl
-    thread_t          * killer;         // killer thread pointer
+    thread_t          * requester;      // requesting thread pointer
     uint32_t            count;          // requests counter
-    volatile uint32_t   sig_rsp_count;  // responses counter
-    cxy_t               client_cxy;     // client thread cluster identifier
-    thread_t          * client_ptr;     // client thread pointer
-    core_t            * client_core;    // client thread core pointer
-
-    // get local killer thread pointer
-    killer = CURRENT_THREAD;
+    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",
@@ -482,5 +511,5 @@
 
     // initialize local responses counter 
-    sig_rsp_count = process->th_nr;
+    rsp_count = process->th_nr;
 
     // loop on process threads to block and deschedule all threads in cluster
@@ -494,31 +523,48 @@
             count++;
 
-            // set signal in target thread descriptor
-            thread_set_signal( target , (uint32_t *)sig_rsp_count );
-
-            // set the global blocked bit in target thread descriptor.
-            thread_block( target , THREAD_BLOCKED_GLOBAL );
-
-            // - if the killer thread and the target thread are not on the same core
-            //   we want the scheduler of target thread to acknowlege the signal
-            //   to be sure that the target thread is descheduled
-            // - if the killer thread and the target thread are on the same core
-            //   we simply decrement the response counter.
-            if( killer->core->lid != target->core->lid )
+            // - if the target thread is the client thread, we do nothing,
+            //   and 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 ask ask anything to the scheduler,
+            //   and simply decrement the responses counter.
+            // - if the calling thread and the target thread are not running on the same
+            //   core, we ask the target scheduler to acknowlege the blocking
+            //   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 )
+            {
+                // set the global blocked bit in target thread descriptor.
+                thread_block( target , THREAD_BLOCKED_GLOBAL );
+
+                // decrement responses counter
+                hal_atomic_add( (void *)&rsp_count , -1 );
+            }
+            else
+            {
+                // set the global blocked bit in target thread descriptor.
+                thread_block( target , THREAD_BLOCKED_GLOBAL );
+
+                // set FLAG_REQ_ACK and &ack_rsp_count in target descriptor
+                thread_set_req_ack( target , (void *)&rsp_count );
+
+                // force scheduling on target thread
                 dev_pic_send_ipi( local_cxy , target->core->lid );
             }
-            else                                                         
-            {
-                hal_atomic_add( (void *)&sig_rsp_count , -1 );
-            }
         }
     }
 
-    // poll the reponses counter 
+    // get lock protecting process th_tbl[]
+    spinlock_unlock( &process->th_lock );
+
+    // wait all responses from schedulers 
     while( 1 )
     {
-        // exit loop when all responses received
-        if ( sig_rsp_count == 0 ) break;
+        // exit loop when all local responses received
+        if ( rsp_count == 0 ) break;
     
         // wait 1000 cycles before retry
@@ -526,14 +572,4 @@
     }
 
-    // acknowledge client thread & unblock client thread if last response
-    client_cxy  = GET_CXY( client_xp );
-    client_ptr  = (thread_t *)GET_PTR( client_xp );
-    client_core = (core_t *)hal_remote_lpt( XPTR( client_cxy , &client_ptr->core ) );
-    if( hal_remote_atomic_add( rsp_xp , -1 ) == 1 ) 
-    {
-        thread_unblock( client_xp , THREAD_BLOCKED_RPC);
-        dev_pic_send_ipi( client_cxy , client_core->lid );
-    }
-
 sigaction_dmsg("\n[DBG] %s : exit for process %x in cluster %x / %d threads blocked\n",
 __FUNCTION__ , process->pid , local_cxy , count );
@@ -541,19 +577,10 @@
 }  // end process_block()
 
-//////////////////////////////////////////
-void process_unblock( process_t * process,
-                      xptr_t      rsp_xp,
-                      xptr_t      client_xp )
+///////////////////////////////////////////
+void process_unblock( process_t * process )
 {
     thread_t          * target;        // pointer on target thead 
     uint32_t            ltid;          // index in process th_tbl
-    thread_t          * killer;        // killer thread pointer
-    uint32_t            req_count;     // requests counter
-    cxy_t               client_cxy;    // client thread cluster identifier
-    thread_t          * client_ptr;    // client thread pointer
-    core_t            * client_core;   // client thread core pointer
-
-    // get local killer thread pointer
-    killer = CURRENT_THREAD;
+    uint32_t            count;         // requests counter
 
 sigaction_dmsg("\n[DBG] %s : enter for process %x in cluster %x\n",
@@ -564,8 +591,6 @@
 
     // loop on process threads to unblock all threads in cluster
-    // we use both "ltid" and "req_count" because it can exist "holes" in th_tbl
-    for( ltid = 0 , req_count = 0 ;
-         req_count < process->th_nr ;
-         ltid++ )
+    // we use both "ltid" and "count" because it can exist "holes" in th_tbl
+    for( ltid = 0 , count = 0 ; count < process->th_nr ; ltid++ )
     {
         target = process->th_tbl[ltid];
@@ -573,5 +598,5 @@
         if( target != NULL )             // thread found
         {
-            req_count++;
+            count++;
 
             // reset the global blocked bit in target thread descriptor.
@@ -580,16 +605,9 @@
     }
 
-    // acknowledge client thread & unblock client thread if last response
-    client_cxy  = GET_CXY( client_xp );
-    client_ptr  = (thread_t *)GET_PTR( client_xp );
-    client_core = (core_t *)hal_remote_lpt( XPTR( client_cxy , &client_ptr->core ) );
-    if( hal_remote_atomic_add( rsp_xp , -1 ) == 1 ) 
-    {
-        thread_unblock( client_xp , THREAD_BLOCKED_RPC);
-        dev_pic_send_ipi( client_cxy , client_core->lid );
-    }
+    // get lock protecting process th_tbl[]
+    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 , req_count );
+__FUNCTION__ , process->pid , local_cxy , count );
 
 }  // end process_unblock()
@@ -597,61 +615,43 @@
 /////////////////////////////////////////
 void process_delete( process_t * process,
-                     xptr_t      rsp_xp,
                      xptr_t      client_xp )
 {
-    thread_t          * thread;        // pointer on target thread 
+    thread_t          * target;        // pointer on target thread 
     uint32_t            ltid;          // index in process th_tbl
     uint32_t            count;         // request counter
-    pid_t               pid;           // process PID
-    cxy_t               client_cxy;    // client thread cluster identifier
-    thread_t          * client_ptr;    // client thread pointer
-    core_t            * client_core;   // client thread core pointer
-
-    // get process PID
-    pid = process->pid;
+    thread_t          * requester;     // pointer on calling thread 
 
 sigaction_dmsg("\n[DBG] %s : enter for process %x in cluster %x at cycle %d\n",
-__FUNCTION__ , pid , local_cxy , (uint32_t)hal_get_cycles() );
-
-    // loop on threads to release memory allocated to threads
+__FUNCTION__ , process->pid , local_cxy , (uint32_t)hal_get_cycles() );
+
+    // get calling thread pointer
+    requester = CURRENT_THREAD;
+
+    // get lock protecting process th_tbl[]
+    spinlock_lock( &process->th_lock );
+
+    // loop on threads to set the REQ_DELETE flag
+    // we use both "ltid" and "count" because it can exist "holes" in th_tbl
     for( ltid = 0 , count = 0  ; count < process->th_nr ; ltid++ )
     {
-        thread = process->th_tbl[ltid];
-
-        if( thread != NULL )             // thread found
+        target = process->th_tbl[ltid];
+
+        if( target != NULL )             // thread found
         {
             count++;
 
-            // detach thread from parent if attached
-            if( (thread->flags & THREAD_FLAG_DETACHED) == 0 ) 
-            thread_child_parent_unlink( thread->parent , XPTR( local_cxy , thread ) );
-
-            // detach thread from process
-            process_remove_thread( thread );
-
-            // remove thread from scheduler
-            sched_remove_thread( thread );
-
-            // release memory allocated to thread
-            thread_destroy( thread );
+            // delete only if the target is not the client
+            if( XPTR( local_cxy , target ) != client_xp ) 
+            { 
+                hal_atomic_or( &target->flags , THREAD_FLAG_REQ_DELETE );
+            }
         }
     }
 
-    // release memory allocated to process descriptors
-    // for all clusters other than the owner cluster 
-    if( local_cxy != CXY_FROM_PID( process->pid ) ) process_destroy( process );
-
-    // acknowledge client thread & unblock client thread if last response
-    client_cxy  = GET_CXY( client_xp );
-    client_ptr  = (thread_t *)GET_PTR( client_xp );
-    client_core = (core_t *)hal_remote_lpt( XPTR( client_cxy , &client_ptr->core ) );
-    if( hal_remote_atomic_add( rsp_xp , -1 ) == 1 ) 
-    {
-        thread_unblock( client_xp , THREAD_BLOCKED_RPC);
-        dev_pic_send_ipi( client_cxy , client_core->lid );
-    }
+    // get lock protecting process th_tbl[]
+    spinlock_unlock( &process->th_lock );
 
 sigaction_dmsg("\n[DBG] %s : exit for process %x in cluster %x at cycle %d\n",
-__FUNCTION__ , pid , local_cxy , (uint32_t)hal_get_cycles() );
+__FUNCTION__ , process->pid , local_cxy , (uint32_t)hal_get_cycles() );
 
 }  // end process_delete()
@@ -951,5 +951,5 @@
 
     // allocate a child PID from local cluster
-    error = cluster_pid_alloc( XPTR( local_cxy , process ) , &new_pid );
+    error = cluster_pid_alloc( process , &new_pid );
     if( (error != 0) || (new_pid == 0) )
     {
@@ -1037,7 +1037,6 @@
     return 0;
 
-}  // end process_make_fork()
-
-/*  deprecated because we don't wand to destroy the existing process descriptor
+}   // end process_make_fork()
+
 
 /////////////////////////////////////////////////////
@@ -1045,8 +1044,10 @@
 {
     char           * path;                    // pathname to .elf file
-    process_t      * old;                     // local pointer on old process
-    process_t      * new;                     // local pointer on new process
-    pid_t            pid;                     // old process identifier
-    thread_t       * thread;                  // pointer on new thread
+    process_t      * old_process;             // local pointer on old process
+    process_t      * new_process;             // local pointer on new process
+    pid_t            old_pid;                 // old process identifier
+    pid_t            new_pid;                 // new (temporary) process identifier
+    thread_t       * old_thread;              // pointer on new thread
+    thread_t       * new_thread;              // pointer on new thread
     pthread_attr_t   attr;                    // main thread attributes
     lid_t            lid;                     // selected core local index
@@ -1054,39 +1055,60 @@
 
 	// get .elf pathname and PID from exec_info
-	path = exec_info->path;
-    pid  = exec_info->pid;
-
-    // check local cluster is process owner
-    assert( (CXY_FROM_PID( pid ) == local_cxy), __FUNCTION__,
-    "local cluster %x is not owner for process %x\n", local_cxy, pid );
+	path     = exec_info->path;
+    old_pid  = exec_info->pid;
+
+    // this function must be executed by a thread running in owner cluster
+    assert( (CXY_FROM_PID( old_pid ) == local_cxy), __FUNCTION__,
+    "local cluster %x is not owner for process %x\n", local_cxy, old_pid );
 
 exec_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x / path = %s\n",
-__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid , path );
-
-    // get old process local pointer
-    old = (process_t *)cluster_get_local_process_from_pid( pid );
+__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, old_pid , path );
+
+    // get old process and thread local pointers
+    old_process = (process_t *)cluster_get_local_process_from_pid( old_pid );
+    old_thread  = CURRENT_THREAD;
     
-    assert( (old != NULL ) , __FUNCTION__ , 
-    "process %x not found in cluster %x\n", pid , local_cxy ); 
+    if( old_process == NULL )
+    {
+        printk("\n[ERROR] in %s : cannot get old process descriptor\n", __FUNCTION__ );
+        return -1;
+    }
 
     // allocate memory for new process descriptor
-    new = process_alloc();
+    new_process = process_alloc();
+
+    if( new_process == NULL )
+    {
+        printk("\n[ERROR] in %s : cannot allocate new process descriptor\n", __FUNCTION__ );
+        return -1;
+    }
+
+    // get a (temporary) PID for new process
+    error = cluster_pid_alloc( new_process , &new_pid );
+
+    if( error )
+    {
+        printk("\n[ERROR] in %s : cannot allocate a temporary PID\n", __FUNCTION__ );
+        process_destroy( new_process );
+        return -1;
+    }
 
     // initialize new process descriptor
-    process_reference_init( new,
-                            old->pid,                   // same as old
-                            old->ppid,                  // same as old
-                            XPTR( local_cxy , old ) );
+    process_reference_init( new_process,
+                            new_pid,                            // temporary PID
+                            old_process->ppid,                  // same parent
+                            XPTR( local_cxy , old_process ) );
 
 exec_dmsg("\n[DBG] %s : core[%x,%d] created new process %x / path = %s\n",
-__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid, path );
+__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, new_pid, path );
 
     // register "code" and "data" vsegs as well as entry-point
     // in new process VMM, using information contained in the elf file.
-	if( elf_load_process( path , new ) )
+	if( elf_load_process( path , new_process ) )
 	{
 		printk("\n[ERROR] in %s : failed to access .elf file for process %x / path = %s\n",
-		__FUNCTION__, pid , path );
-        process_destroy( new );
+		__FUNCTION__, new_pid , path );
+        cluster_pid_release( new_pid );
+        process_destroy( new_process );
         return -1;
 	}
@@ -1104,167 +1126,89 @@
 
     // create and initialize thread descriptor
-	error = thread_user_create( pid,
-                                (void *)new->vmm.entry_point,
+	error = thread_user_create( new_pid,
+                                (void *)new_process->vmm.entry_point,
                                 exec_info->args_pointers,
                                 &attr,
-                                &thread );
+                                &new_thread );
 	if( error )
 	{
 		printk("\n[ERROR] in %s : cannot create thread for process %x / path = %s\n",
-		       __FUNCTION__, pid , path );
-        process_destroy( new );
+	    __FUNCTION__, new_pid , path );
+        cluster_pid_release( new_pid );
+        process_destroy( new_process );
         return -1;
 	}
 
-exec_dmsg("\n[DBG] %s : core[%x,%d] created main thread %x for new process %x\n",
-__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, thread->trdid, pid );
-
-    // update children list (rooted in parent process)
-	xlist_replace( XPTR( local_cxy , &old->brothers_list ) ,
-                   XPTR( local_cxy , &new->brothers_list ) );
-
-    // request destruction of old process copies and threads in all clusters
-    process_sigaction( old , SIGKILL );
-
+exec_dmsg("\n[DBG] %s : core[%x,%d] created main thread %x\n",
+__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, new_thread->trdid );
+
+    // update children list rooted in parent process
+	xlist_replace( XPTR( local_cxy , &old_process->brothers_list ) ,
+                   XPTR( local_cxy , &new_process->brothers_list ) );
+
+    // 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 );
+
+    // update PID for both processes 
+    new_process->pid = old_pid;
+    old_process->pid = 0xFFFFFFFF;
+
+    // release temporary PID
+    cluster_pid_release( new_pid );
+    
     // activate new thread
-	thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL );
+	thread_unblock( XPTR( local_cxy , new_thread ) , THREAD_BLOCKED_GLOBAL );
 
 exec_dmsg("\n[DBG] %s : core[%x,%d] exit for path = %s\n",
 __FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path  );
 
+    // set BLOCKED_GLOBAL bit
+    thread_block( old_thread , THREAD_BLOCKED_GLOBAL );
+
+    // set REQ_DELETE flag
+    hal_atomic_or( &old_thread->flags , THREAD_FLAG_REQ_DELETE );
+
+    // deschedule
+    sched_yield("suicide after exec"); 
+
+    // never executed but required by compiler
 	return 0;
 
 }  // end process_make_exec()
 
-*/
-
-/////////////////////////////////////////////////////
-error_t process_make_exec( exec_info_t  * exec_info )
-{
-    char           * path;                    // pathname to .elf file
-    process_t      * process;                 // local pointer on old process
-    pid_t            pid;                     // old process identifier
-    thread_t       * thread;                  // pointer on new main thread
-    pthread_attr_t   attr;                    // main thread attributes
-    lid_t            lid;                     // selected core local index
-	error_t          error;
-
-	// get .elf pathname and PID from exec_info
-	path = exec_info->path;
-    pid  = exec_info->pid;
-
-    // check local cluster is process owner
-    assert( (CXY_FROM_PID( pid ) == local_cxy), __FUNCTION__,
-    "local cluster %x is not owner for process %x\n", local_cxy, pid );
-
-exec_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x / path = %s\n",
-__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid , path );
-
-    // get process local pointer
-    process = (process_t *)cluster_get_local_process_from_pid( pid );
-    
-    assert( (process != NULL ) , __FUNCTION__ , 
-    "process %x not found in cluster %x\n", pid , local_cxy ); 
-
-    // reset the existing vmm
-    vmm_destroy( process );
-
-exec_dmsg("\n[DBG] %s : core[%x,%d] VMM cleared\n",
-__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid );
-
-    // block all existing process threads
-    process_sigaction( process , BLOCK_ALL_THREADS );
-
-    // kill all existing threads and process descriptors (other than owner)
-    process_sigaction( process , DELETE_ALL_THREADS );
-
-    // check no threads
-    assert( (process->th_nr == 0) , __FUNCTION__ , "no threads at this point" );
-
-exec_dmsg("\n[DBG] %s : core[%x,%d] all threads deleted\n",
-__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid );
-
-    // initialize VMM 
-    error = vmm_init( process );
-	{
-		printk("\n[ERROR] in %s : cannot initialize VMM for process %x / path = %s\n",
-		__FUNCTION__, pid , path );
-        process_destroy( process );
-        return -1;
-	}
-
-    if( error )
-
-    // register "code" and "data" vsegs as well as entry-point and vfs_bin_xp
-    // in VMM, using information contained in the elf file.
-	error = elf_load_process( path , process );
-
-    if( error )
-	{
-		printk("\n[ERROR] in %s : failed to access .elf file for process %x / path = %s\n",
-		__FUNCTION__, pid , path );
-        process_destroy( process );
-        return -1;
-	}
-
-exec_dmsg("\n[DBG] %s : core[%x,%d] new vsegs registered / path = %s\n",
-__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path );
-
-// @@@
-vmm_display( process , true );
-// @@@
-
-    // select a core in local cluster to execute the new main thread
-    lid  = cluster_select_local_core();
-
-    // initialize pthread attributes for new 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 thread descriptor
-	error = thread_user_create( pid,
-                                (void *)process->vmm.entry_point,
-                                exec_info->args_pointers,
-                                &attr,
-                                &thread );
-	if( error )
-	{
-		printk("\n[ERROR] in %s : cannot create thread for process %x / path = %s\n",
-		       __FUNCTION__, pid , path );
-        process_destroy( process );
-        return -1;
-	}
-
-exec_dmsg("\n[DBG] %s : core[%x,%d] created main thread %x for new process %x\n",
-__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, thread->trdid, pid );
-
-    // activate new thread
-	thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL );
-
-exec_dmsg("\n[DBG] %s : core[%x,%d] exit for path = %s\n",
-__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path  );
-
-	return 0;
-
-}  // end process_make_exec()
-
-////////////////////////////////////////////
-void process_make_kill( process_t * process,
-                        uint32_t    sig_id )
+///////////////////////////////////////
+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( process->pid ) == local_cxy) , __FUNCTION__ ,
+    assert( (CXY_FROM_PID( pid ) == local_cxy) , __FUNCTION__ ,
     "must execute in owner cluster" );
+
+kill_dmsg("\n[DBG] %s : core[%x,%d] enter / process %x / sig %d\n",
+__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid , sig_id );
+
+    // 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;
+    }
 
     // analyse signal type
     switch( sig_id )
     {
-        case SIGSTOP:     // block all threads
+        case SIGSTOP:     // block all threads in all clusters
         {
             process_sigaction( process , BLOCK_ALL_THREADS );
         }
         break;
-        case SIGCONT:     // unblock all threads
+        case SIGCONT:     // unblock all threads in all clusters
         {
             process_sigaction( process , UNBLOCK_ALL_THREADS );
@@ -1273,28 +1217,64 @@
         case SIGKILL:  // block all threads, then delete all threads
         {
+            // block all threads (but the calling thread)
             process_sigaction( process , BLOCK_ALL_THREADS );
+
+            // delete all threads (but the calling thread)
             process_sigaction( process , DELETE_ALL_THREADS );
-            process_destroy( process );
+
+            // delete the calling thread if required
+            thread_t * this = CURRENT_THREAD;
+
+            if( this->process == process )
+            {
+                // set REQ_DELETE flag
+                hal_atomic_or( &this->flags , THREAD_FLAG_REQ_DELETE );
+
+                // deschedule
+                sched_yield( "suicide after kill" ); 
+            }
         }
         break;
     }
+
+//@@@
+sched_display( 0 );
+//@@@
+
+kill_dmsg("\n[DBG] %s : core[%x,%d] exit / process %x / sig %d \n",
+__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid , sig_id );
+
 }  // end process_make_kill()
 
-////////////////////////////////////////////
-void process_make_exit( process_t * process,
+/////////////////////////////////////////
+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( process->pid ) == local_cxy) , __FUNCTION__ ,
+    assert( (CXY_FROM_PID( pid ) == local_cxy) , __FUNCTION__ ,
     "must execute in owner cluster" );
 
-    // block all threads in all clusters
+    // 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
+    // delete all threads in all clusters (but the calling thread)
     process_sigaction( process , DELETE_ALL_THREADS );
 
-    // delete local process descriptor
-    process_destroy( process ); 
+    // delete the calling thread 
+    hal_atomic_or( &CURRENT_THREAD->flags , THREAD_FLAG_REQ_DELETE );
+
+    // deschedule
+    sched_yield( "suicide after exit" ); 
 
 }  // end process_make_exit()
@@ -1322,5 +1302,5 @@
 
     // get PID from local cluster
-    error = cluster_pid_alloc( XPTR( local_cxy , process ) , &pid );
+    error = cluster_pid_alloc( process , &pid );
     if( error )
     {
