Index: trunk/kernel/kern/rpc.c
===================================================================
--- trunk/kernel/kern/rpc.c	(revision 408)
+++ trunk/kernel/kern/rpc.c	(revision 409)
@@ -49,13 +49,13 @@
 {
     &rpc_pmem_get_pages_server,         // 0
-    &rpc_process_make_exec_server,      // 1
-    &rpc_process_make_fork_server,      // 2
-    &rpc_process_kill_server,           // 3
-    &rpc_thread_user_create_server,     // 4
-    &rpc_thread_kernel_create_server,   // 5
-    &rpc_signal_rise_server,            // 6                       
-    &rpc_undefined,                     // 7
-    &rpc_undefined,                     // 8
-    &rpc_undefined,                     // 9
+    &rpc_pmem_release_pages_server,     // 1
+    &rpc_process_make_exec_server,      // 2
+    &rpc_process_make_fork_server,      // 3
+    &rpc_process_make_exit_server,      // 4
+    &rpc_process_make_kill_server,      // 5
+    &rpc_thread_user_create_server,     // 6
+    &rpc_thread_kernel_create_server,   // 7
+    &rpc_thread_kill_server,            // 8                       
+    &rpc_process_sigaction_server,      // 9
 
     &rpc_vfs_inode_create_server,       // 10  
@@ -88,6 +88,297 @@
 }
 
-/////////////////////////////////////////////////////////////////////////////////////////
-// [0]           Marshaling functions attached to RPC_PMEM_GET_PAGES 
+/***************************************************************************************/
+/************ Generic functions supporting RPCs : client side **************************/
+/***************************************************************************************/
+
+///////////////////////////////////////
+void rpc_send( cxy_t        server_cxy, 
+               rpc_desc_t * rpc,
+               bool_t       block )
+{
+    error_t    error;
+
+    thread_t * this = CURRENT_THREAD;
+    core_t   * core = this->core;
+
+    // register client thread pointer and core lid in RPC descriptor
+    rpc->thread    = this;
+    rpc->lid       = core->lid;
+
+    // build an extended pointer on the RPC descriptor
+	xptr_t   desc_xp = XPTR( local_cxy , rpc );
+
+    // get local pointer on rpc_fifo in remote cluster, with the 
+    // assumption that local pointers are identical in all clusters
+    remote_fifo_t * rpc_fifo = &LOCAL_CLUSTER->rpc_fifo;
+
+	// try to post an item in remote fifo
+    // deschedule and retry if remote fifo full
+    do
+    { 
+        error = remote_fifo_put_item( XPTR( server_cxy , rpc_fifo ),
+                                      (uint64_t )desc_xp );
+	    if ( error ) 
+        {
+            printk("\n[WARNING] %s : cluster %x cannot post RPC to cluster %x\n",
+            __FUNCTION__ , local_cxy , server_cxy );
+
+            if( thread_can_yield() ) sched_yield("RPC fifo full");
+        }
+    }
+    while( error );
+ 
+    hal_fence();
+	
+    // send IPI to the remote core corresponding to the client core
+	dev_pic_send_ipi( server_cxy , core->lid );
+
+    // wait RPC completion if blocking
+    // - busy waiting policy during kernel_init, or if threads cannot yield
+    // - block and deschedule in all other cases
+    if ( block )
+    {
+        if( (this->type == THREAD_IDLE) || (thread_can_yield() == false) ) // busy waiting
+        {
+
+grpc_dmsg("\n[DBG] %s : core[%x,%d] / thread %s busy waiting after registering RPC\n"
+"        rpc = %d / server = %x / cycle %d\n",
+__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , thread_type_str(this->type) ,
+rpc->index , server_cxy , hal_time_stamp() );
+
+            while( rpc->response ) hal_fixed_delay( 100 );
+    
+grpc_dmsg("\n[DBG] %s : core[%x,%d] / thread %s exit after RPC completion\n",
+__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , thread_type_str(this->type) );
+
+        } 
+        else                                                              // block & deschedule
+        {
+
+grpc_dmsg("\n[DBG] %s : core[%x,%d] / thread %s deschedule after registering RPC\n"
+"        rpc = %d / server = %x / cycle %d\n",
+__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , thread_type_str(this->type) ,
+rpc->index , server_cxy , hal_time_stamp() );
+
+            thread_block( this , THREAD_BLOCKED_RPC );
+            sched_yield("BLOCKED on RPC");
+
+grpc_dmsg("\n[DBG] %s : core[%x,%d] / thread %s resumes after RPC completion\n",
+__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , thread_type_str(this->type) );
+
+        }
+
+        // check response available
+        assert( (rpc->response == 0) , __FUNCTION__, "illegal RPC response\n" );
+
+        // acknowledge the IPI sent by the server
+        dev_pic_ack_ipi();
+    }
+    
+}  // end rpc_send()
+
+
+/***************************************************************************************/
+/************ Generic functions supporting RPCs : server side **************************/
+/***************************************************************************************/
+
+////////////////
+void rpc_check()
+{
+    error_t         error;
+    thread_t      * thread;  
+    uint32_t        sr_save;
+
+    bool_t          found    = false;
+	thread_t      * this     = CURRENT_THREAD;
+    core_t        * core     = this->core;
+    scheduler_t   * sched    = &core->scheduler;
+	remote_fifo_t * rpc_fifo = &LOCAL_CLUSTER->rpc_fifo;
+
+grpc_dmsg("\n[DBG] %s : core[%x,%d] / interrupted thread %s / cycle %d\n",
+__FUNCTION__, local_cxy, core->lid, thread_type_str(this->type), hal_time_stamp() );
+
+    // interrupted thread not preemptable during RPC chek
+	hal_disable_irq( &sr_save );
+
+    // check RPC FIFO not empty and no RPC thread handling it  
+	if( (rpc_fifo->owner == 0) && (local_fifo_is_empty(rpc_fifo) == false) )
+    {
+        // search one non blocked RPC thread   
+        list_entry_t * iter;
+        LIST_FOREACH( &sched->k_root , iter )
+        {
+            thread = LIST_ELEMENT( iter , thread_t , sched_list );
+            if( (thread->type == THREAD_RPC) && (thread->blocked == 0 ) ) 
+            {
+                found = true;
+                break;
+            }
+        }
+
+        // create new RPC thread if not found    
+        if( found == false )                    
+        {
+            error = thread_kernel_create( &thread,
+                                          THREAD_RPC, 
+			                              &rpc_thread_func, 
+                                          NULL,
+			                              this->core->lid );
+	        if( error ) 
+            {
+                printk("\n[WARNING] in %s : no memory for new RPC thread in cluster %x\n",
+                __FUNCTION__ , local_cxy );
+            }
+            else
+            {
+                // unblock created RPC thread
+                thread->blocked = 0;
+
+                // update core descriptor counter  
+	            hal_atomic_add( &LOCAL_CLUSTER->rpc_threads , 1 );
+
+grpc_dmsg("\n[DBG] %s : core [%x,%d] creates a new RPC thread %x / cycle %d\n", 
+__FUNCTION__ , local_cxy , core->lid , thread->trdid , hal_time_stamp() );
+
+            }
+        }
+    }
+
+grpc_dmsg("\n[DBG] %s : core[%x,%d] / interrupted thread %s deschedules / cycle %d\n", 
+__FUNCTION__, local_cxy, core->lid, thread_type_str(this->type), hal_time_stamp() );
+
+    // interrupted thread deschedule always           
+	sched_yield("IPI received");
+
+grpc_dmsg("\n[DBG] %s : core[%x,%d] / interrupted thread %s resume / cycle %d\n", 
+__FUNCTION__, local_cxy, core->lid, thread_type_str(this->type), hal_time_stamp() );
+
+    // interrupted thread restore IRQs after resume 
+	hal_restore_irq( sr_save );
+
+} // end rpc_check()
+
+
+//////////////////////
+void rpc_thread_func()
+{
+    uint32_t     count;       // handled RPC requests counter
+    error_t      empty;       // local RPC fifo state
+    xptr_t       desc_xp;     // extended pointer on RPC request
+    cxy_t        desc_cxy;    // RPC request cluster (client) 
+    rpc_desc_t * desc_ptr;    // RPC request local pointer 
+    uint32_t     index;       // RPC request index 
+    uint32_t     responses;   // number of responses received by client 
+    thread_t   * thread_ptr;  // local pointer on client thread
+    lid_t        core_lid;    // local index of client core
+ 
+    // makes RPC thread not preemptable
+	hal_disable_irq( NULL );
+  
+	thread_t      * this     = CURRENT_THREAD;
+	remote_fifo_t * rpc_fifo = &LOCAL_CLUSTER->rpc_fifo;
+
+    // two embedded loops:
+    // - external loop : "infinite" RPC thread
+    // - internal loop : handle up to CONFIG_RPC_PENDING_MAX RPC requests
+ 
+	while(1)  // external loop
+	{
+        // try to take RPC_FIFO ownership
+        if( hal_atomic_test_set( &rpc_fifo->owner , this->trdid ) )
+        {
+            // initializes RPC requests counter
+            count = 0;
+
+            // acknowledge local IPI 
+            dev_pic_ack_ipi();
+
+		    // exit internal loop in three cases:
+            // - RPC fifo is empty
+            // - ownership has been lost (because descheduling)
+            // - max number of RPCs is reached
+	        while( 1 )  // internal loop
+            {
+  	            empty = local_fifo_get_item( rpc_fifo , (uint64_t *)&desc_xp );
+
+	            if ( empty == 0 ) // one RPC request found
+                {
+                    // get client cluster and pointer on RPC descriptor
+                    desc_cxy = (cxy_t)GET_CXY( desc_xp );
+                    desc_ptr = (rpc_desc_t *)GET_PTR( desc_xp );
+
+                    // get rpc index from RPC descriptor
+	                index = hal_remote_lw( XPTR( desc_cxy , &desc_ptr->index ) );
+
+grpc_dmsg("\n[DBG] %s : core[%x,%d] / RPC thread %x / starts rpc %d / cycle %d\n",
+__FUNCTION__ , local_cxy , this->core->lid , this->trdid , index , hal_time_stamp() );
+
+                    // call the relevant server function
+                    rpc_server[index]( desc_xp );
+
+grpc_dmsg("\n[DBG] %s : core[%x,%d] / RPC thread %x / completes rpc %d / cycle %d\n",
+__FUNCTION__ , local_cxy , this->core->lid , this->trdid , index , hal_time_stamp() );
+
+                    // increment handled RPC counter
+  	                count++;
+
+                    // decrement response counter in RPC descriptor
+                    responses = hal_remote_atomic_add(XPTR( desc_cxy, &desc_ptr->response ), -1);
+
+                    // unblock client thread  and send IPI to client core if last response
+                    if( responses == 1 )
+                    { 
+                        // get pointer on client thread and unblock it
+                        thread_ptr = (thread_t *)hal_remote_lpt(XPTR(desc_cxy,&desc_ptr->thread));
+                        thread_unblock( XPTR(desc_cxy,thread_ptr) , THREAD_BLOCKED_RPC );
+
+                        hal_fence();
+
+                        // get client core lid and send IPI
+                        core_lid = hal_remote_lw(XPTR(desc_cxy, &desc_ptr->lid));
+	                    dev_pic_send_ipi( desc_cxy , core_lid );
+                    }
+		        }
+	
+                // chek exit condition
+  		        if( local_fifo_is_empty( rpc_fifo )  || 
+                    (rpc_fifo->owner != this->trdid) || 
+                    (count >= CONFIG_RPC_PENDING_MAX) ) break;
+         	} // end internal loop
+
+            // release rpc_fifo ownership if not lost
+            if( rpc_fifo->owner == this->trdid ) rpc_fifo->owner = 0;
+        }
+
+        // sucide if too many RPC threads in cluster
+        if( LOCAL_CLUSTER->rpc_threads >= CONFIG_RPC_THREADS_MAX )
+	    {
+
+grpc_dmsg("\n[DBG] %s : core[%x,%d] (RPC thread %x) suicide at cycle %d\n", 
+__FUNCTION__, local_cxy, this->core->lid, this->trdid, hal_time_stamp() );
+
+            // update RPC threads counter
+	        hal_atomic_add( &LOCAL_CLUSTER->rpc_threads , -1 );
+
+            // suicide
+	        thread_kill( this );
+	    }
+
+grpc_dmsg("\n[DBG] %s : core[%x,%d] (RPC thread %x) deschedules / cycle %d\n", 
+__FUNCTION__, local_cxy, this->core->lid, this->trdid, hal_time_stamp() );
+
+        // deschedule without blocking
+        sched_yield("RPC fifo empty or too much work");
+
+grpc_dmsg("\n[DBG] %s : core[%x,%d] (RPC thread %x) resumes / cycle %d\n", 
+__FUNCTION__, local_cxy, this->core->lid, this->trdid, hal_time_stamp() );
+
+	} // end external loop
+
+} // end rpc_thread_func()
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// [0]           Marshaling functions attached to RPC_PMEM_GET_PAGES (blocking)
 /////////////////////////////////////////////////////////////////////////////////////////
 
@@ -97,7 +388,7 @@
                                 page_t  ** page )      // out 
 {
-    rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
+rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
 
     assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
@@ -112,12 +403,12 @@
 
     // register RPC request in remote RPC fifo (blocking function)
-    rpc_send_sync( cxy , &rpc );
+    rpc_send( cxy , &rpc  , true );
 
     // get output arguments from RPC descriptor
     *page = (page_t *)(intptr_t)rpc.args[1];
 
-    rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
+rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
 }
 
@@ -125,7 +416,7 @@
 void rpc_pmem_get_pages_server( xptr_t xp )
 {
-    rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
+rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
 
     // get client cluster identifier and pointer on RPC descriptor
@@ -134,5 +425,5 @@
 
     // get input arguments from client RPC descriptor
-    uint32_t order = hal_remote_lw( XPTR( cxy , &desc->args[0] ) );
+    uint32_t order = (uint32_t)hal_remote_lwd( XPTR( cxy , &desc->args[0] ) );
     
     // call local pmem allocator
@@ -142,11 +433,66 @@
     hal_remote_swd( XPTR( cxy , &desc->args[1] ) , (uint64_t)(intptr_t)page );
 
-    rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// [1]           Marshaling functions attached to RPC_PROCESS_MAKE_EXEC
+rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// [1]       Marshaling functions attached to RPC_PMEM_RELEASE_PAGES (blocking)
+/////////////////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////
+void rpc_pmem_release_pages_client( cxy_t     cxy,
+                                    page_t  * page )      // out 
+{
+rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
+
+    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
+
+    // initialise RPC descriptor header 
+    rpc_desc_t  rpc;
+    rpc.index    = RPC_PMEM_RELEASE_PAGES;
+    rpc.response = 1;
+
+    // set input arguments in RPC descriptor 
+    rpc.args[0] = (uint64_t)(intptr_t)page;
+
+    // register RPC request in remote RPC fifo (blocking function)
+    rpc_send( cxy , &rpc  , true );
+
+rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
+}
+
+///////////////////////////////////////////////
+void rpc_pmem_release_pages_server( xptr_t xp )
+{
+rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
+
+    // get client cluster identifier and pointer on RPC descriptor
+    cxy_t        cxy  = (cxy_t)GET_CXY( xp );
+    rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp );
+
+    // get input arguments from client RPC descriptor
+    page_t * page = (page_t *)(intptr_t)hal_remote_lwd( XPTR( cxy , &desc->args[0] ) );
+    
+    // release memory to local pmem 
+    kmem_req_t req;
+    req.type = KMEM_PAGE;
+    req.ptr  = page;
+    kmem_free( &req );
+
+rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// [2]           Marshaling functions attached to RPC_PROCESS_MAKE_EXEC (blocking)
 /////////////////////////////////////////////////////////////////////////////////////////
 
@@ -156,7 +502,7 @@
                                    error_t     * error )   // out
 {
-    rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
+rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
 
     assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
@@ -171,12 +517,12 @@
 
     // register RPC request in remote RPC fifo (blocking function)
-    rpc_send_sync( cxy , &rpc );
+    rpc_send( cxy , &rpc  , true );
 
     // get output arguments from RPC descriptor
     *error  = (error_t)rpc.args[1];     
 
-    rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
+rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
 }
 
@@ -184,11 +530,11 @@
 void rpc_process_make_exec_server( xptr_t xp )
 {
+rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
+
     exec_info_t * ptr;       // local pointer on remote exec_info structure
     exec_info_t   info;      // local copy of exec_info structure
     error_t       error;     // local error error status
-
-    rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
 
     // get client cluster identifier and pointer on RPC descriptor
@@ -210,11 +556,11 @@
     hal_remote_swd( XPTR( client_cxy , &desc->args[1] ) , (uint64_t)error );
 
-    rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// [2]           Marshaling functions attached to RPC_PROCESS_MAKE_FORK 
+rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// [3]           Marshaling functions attached to RPC_PROCESS_MAKE_FORK (blocking)
 /////////////////////////////////////////////////////////////////////////////////////////
 
@@ -227,7 +573,7 @@
                                    error_t   * error )              // out
 {
-    rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
+rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
 
     assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
@@ -243,5 +589,5 @@
 
     // register RPC request in remote RPC fifo (blocking function)
-    rpc_send_sync( cxy , &rpc );
+    rpc_send( cxy , &rpc  , true );
 
     // get output arguments from RPC descriptor
@@ -250,7 +596,7 @@
     *error             = (error_t)rpc.args[4];     
 
-    rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
+rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
 }
 
@@ -258,4 +604,8 @@
 void rpc_process_make_fork_server( xptr_t xp )
 {
+rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
+
     xptr_t     ref_process_xp;     // extended pointer on reference parent process
     xptr_t     parent_thread_xp;   // extended pointer on parent thread
@@ -264,8 +614,4 @@
     error_t    error;              // local error status
 
-    rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
-
     // get client cluster identifier and pointer on RPC descriptor
     cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
@@ -287,64 +633,50 @@
     hal_remote_swd( XPTR( client_cxy , &desc->args[4] ) , (uint64_t)error );
 
-    rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// [3]           Marshaling functions attached to RPC_PROCESS_KILL 
+rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// [4]      Marshaling functions attached to RPC_PROCESS_MAKE_EXIT (blocking)
 /////////////////////////////////////////////////////////////////////////////////////////
 
 ///////////////////////////////////////////////////
-void rpc_process_kill_client( process_t * process ) 
-{
-    rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
-
-    // only reference cluster can send this RPC
-    assert( (GET_CXY( process->ref_xp ) == local_cxy) , __FUNCTION__ ,
-            "caller must be reference process cluster\n");
-
-    // get local process index in reference cluster
-    lpid_t lpid = LPID_FROM_PID( process->pid );
-
-    // get local process manager pointer
-    pmgr_t * pmgr = &LOCAL_CLUSTER->pmgr;
-
-    // get number of copies
-    uint32_t copies = pmgr->copies_nr[lpid];
-
-    // initialise RPC descriptor 
-    rpc_desc_t  rpc;
-    rpc.index    = RPC_PROCESS_KILL;
-    rpc.response = copies;
-    rpc.args[0]  = (uint64_t)process->pid;
-
-    // loop on list of copies to send RPC
-    xptr_t  iter;
-    XLIST_FOREACH( XPTR( local_cxy , &pmgr->copies_root[lpid] ) , iter )
-    {
-        // get cluster_identifier for current copy
-        cxy_t  target_cxy = GET_CXY( iter );
-
-        // register RPC request in remote RPC fifo ... but the reference
-        if( target_cxy != local_cxy ) rpc_send_sync( target_cxy , &rpc );
-    }
-
-    rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
+void rpc_process_make_exit_client( cxy_t       cxy,
+                                   process_t * process,
+                                   uint32_t    status ) 
+{
+rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
+
+    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
+
+    // initialise RPC descriptor header 
+    rpc_desc_t  rpc;
+    rpc.index    = RPC_PROCESS_MAKE_EXIT;
+    rpc.response = 1;
+
+    // set input arguments in RPC descriptor  
+    rpc.args[0] = (uint64_t)(intptr_t)process;
+    rpc.args[1] = (uint64_t)status;
+
+    // register RPC request in remote RPC fifo (blocking function)
+    rpc_send( cxy , &rpc , true );
+
+rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
 }  
 
-/////////////////////////////////////////
-void rpc_process_kill_server( xptr_t xp )
-{
-    pid_t       pid;
-    process_t * process;  
-
-    rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
+//////////////////////////////////////////////
+void rpc_process_make_exit_server( xptr_t xp )
+{
+rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
+
+    process_t * process;
+    uint32_t    status;  
 
     // get client cluster identifier and pointer on RPC descriptor
@@ -352,28 +684,76 @@
     rpc_desc_t * desc        = (rpc_desc_t *)GET_PTR( xp );
 
-    // get pid argument from RPC descriptor
-    pid = (pid_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
-
-    // get process pointer to call local kernel function
-    process = cluster_get_local_process_from_pid( pid );
-
-    if( process == NULL )  // process not found => do nothing
-    {
-        printk("\n[WARNING] in %s : process %x not found in cluster %x\n",
-               __FUNCTION__ , pid , local_cxy );
-    }
-    else                   // destroy process 
-    {
-        process_kill( process ); 
-    }
-
-    rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
+    // get arguments from RPC descriptor
+    process = (process_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
+    status  = (uint32_t)             hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
+
+    // call local kernel function
+    process_make_exit( process , status ); 
+
+rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
 } 
 
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// [4]           Marshaling functions attached to RPC_THREAD_USER_CREATE               
+/////////////////////////////////////////////////////////////////////////////////////////
+// [5]      Marshaling functions attached to RPC_PROCESS_MAKE_KILL (blocking)
+/////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////
+void rpc_process_make_kill_client( cxy_t       cxy,
+                                   process_t * process,
+                                   uint32_t    sig_id ) 
+{
+rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
+
+    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
+
+    // initialise RPC descriptor header 
+    rpc_desc_t  rpc;
+    rpc.index    = RPC_PROCESS_MAKE_KILL;
+    rpc.response = 1;
+
+    // set input arguments in RPC descriptor  
+    rpc.args[0] = (uint64_t)(intptr_t)process;
+    rpc.args[1] = (uint64_t)sig_id;
+
+    // register RPC request in remote RPC fifo (blocking function)
+    rpc_send( cxy , &rpc , true );
+
+rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
+}  
+
+//////////////////////////////////////////////
+void rpc_process_make_kill_server( xptr_t xp )
+{
+rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
+
+    process_t * process;
+    uint32_t    sig_id;
+
+    // get client cluster identifier and pointer on RPC descriptor
+    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
+    rpc_desc_t * desc        = (rpc_desc_t *)GET_PTR( xp );
+
+    // get arguments from RPC descriptor
+    process = (process_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
+    sig_id  = (uint32_t)             hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
+
+    // call local kernel function
+    process_make_exit( process , sig_id ); 
+
+rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
+} 
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// [6]           Marshaling functions attached to RPC_THREAD_USER_CREATE (blocking)               
 /////////////////////////////////////////////////////////////////////////////////////////
 
@@ -387,7 +767,7 @@
                                     error_t        * error )      // out 
 {
-    rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
+rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
 
     assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
@@ -404,6 +784,6 @@
     rpc.args[3] = (uint64_t)(intptr_t)attr;
 
-    // register RPC request in remote RPC fifo 
-    rpc_send_sync( cxy , &rpc );
+    // register RPC request in remote RPC fifo (blocking function)
+    rpc_send( cxy , &rpc , true );
 
     // get output arguments from RPC descriptor
@@ -411,7 +791,7 @@
     *error     = (error_t)rpc.args[5];
 
-    rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
+rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
 }
 
@@ -419,4 +799,8 @@
 void rpc_thread_user_create_server( xptr_t xp )
 {
+rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
+
     pthread_attr_t * attr_ptr;   // pointer on attributes structure in client cluster 
     pthread_attr_t   attr_copy;  // attributes structure  copy in server cluster
@@ -428,8 +812,4 @@
     void           * start_arg;
     error_t          error;
-
-    rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
 
     // get client cluster identifier and pointer on RPC descriptor
@@ -462,11 +842,11 @@
     hal_remote_swd( XPTR( client_cxy , &desc->args[5] ) , (uint64_t)error );
 
-    rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// [5]           Marshaling functions attached to RPC_THREAD_KERNEL_CREATE
+rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// [7]           Marshaling functions attached to RPC_THREAD_KERNEL_CREATE (blocking)
 /////////////////////////////////////////////////////////////////////////////////////////
 
@@ -479,7 +859,7 @@
                                       error_t * error )      // out
 {
-    rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
+rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
 
     assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
@@ -495,6 +875,6 @@
     rpc.args[2] = (uint64_t)(intptr_t)args;
     
-    // register RPC request in remote RPC fifo 
-    rpc_send_sync( cxy , &rpc );
+    // register RPC request in remote RPC fifo (blocking function)
+    rpc_send( cxy , &rpc , true );
 
     // get output arguments from RPC descriptor
@@ -502,7 +882,7 @@
     *error     = (error_t)rpc.args[4];
 
-    rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
+rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
 }
 
@@ -510,4 +890,8 @@
 void rpc_thread_kernel_create_server( xptr_t xp )
 {
+rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
+
     thread_t       * thread_ptr;  // local pointer on thread descriptor
     xptr_t           thread_xp;   // extended pointer on thread descriptor
@@ -515,8 +899,4 @@
     error_t          error;    
 
-    rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
-
     // get client cluster identifier and pointer on RPC descriptor
     cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
@@ -539,50 +919,47 @@
     hal_remote_swd( XPTR( client_cxy , &desc->args[2] ) , (uint64_t)thread_xp );
 
-    rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// [6]           Marshaling functions attached to RPC_SIGNAL_RISE
+rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// [8]           Marshaling functions attached to RPC_THREAD_KILL (blocking)
 /////////////////////////////////////////////////////////////////////////////////////////
 
 /////////////////////////////////////////////
-void rpc_signal_rise_client( cxy_t       cxy,
-                             process_t * process,    // in
-                             uint32_t    sig_id )    // in
-{
-    rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
-
-    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
-
-    // initialise RPC descriptor header 
-    rpc_desc_t  rpc;
-    rpc.index    = RPC_SIGNAL_RISE;
+void rpc_thread_kill_client( cxy_t       cxy,
+                             thread_t  * thread )    // in
+{
+rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
+
+    // this RPC can be called in local cluster
+
+    // initialise RPC descriptor header 
+    rpc_desc_t  rpc;
+    rpc.index    = RPC_THREAD_KILL;
     rpc.response = 1;
 
     // set input arguments in RPC descriptor 
-    rpc.args[0] = (uint64_t)(intptr_t)process;
-    rpc.args[1] = (uint64_t)sig_id;
+    rpc.args[0] = (uint64_t)(intptr_t)thread;
     
-    // register RPC request in remote RPC fifo 
-    rpc_send_sync( cxy , &rpc );
-
-    rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
+    // register RPC request in remote RPC fifo (blocking function)
+    rpc_send( cxy , &rpc , true );
+
+rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
 }
 
 ////////////////////////////////////////                             
-void rpc_signal_rise_server( xptr_t xp )
-{
-    process_t  * process;  // local pointer on process descriptor
-    uint32_t     sig_id;   // signal index
-
-    rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
+void rpc_thread_kill_server( xptr_t xp )
+{
+rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
+
+    thread_t  * thread;  // local pointer on process descriptor
 
     // get client cluster identifier and pointer on RPC descriptor
@@ -591,17 +968,82 @@
 
     // get attributes from RPC descriptor
-    process = (process_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
-    sig_id  = (uint32_t)             hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
+    thread = (thread_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
 
     // call local kernel function
-    signal_rise( process , sig_id );
-
-    rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
-    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
-    CURRENT_THREAD->core->lid , hal_time_stamp() );
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// [10]          Marshaling functions attached to RPC_VFS_INODE_CREATE 
+    thread_kill( thread );
+
+rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
+CURRENT_THREAD->core->lid , hal_time_stamp() );
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// [9]     Marshaling functions attached to RPC_PROCESS_KILL  (multicast / non blocking)
+/////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////
+void rpc_process_sigaction_client( cxy_t       cxy,
+                                   process_t * process,        // in
+                                   uint32_t    sigaction,      // in
+                                   xptr_t      rsp_xp,         // in
+                                   xptr_t      client_xp )     // in
+{
+signal_dmsg("\n[DBG] %s : enter for %s / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , process_action_str( sigaction ) , CURRENT_THREAD ,
+local_cxy , CURRENT_THREAD->core->lid , hal_time_stamp() );
+
+    // initialise RPC descriptor header 
+    rpc_desc_t  rpc;
+    rpc.index    = RPC_PROCESS_SIGACTION;
+
+    // set input arguments in RPC descriptor  
+    rpc.args[0] = (uint64_t)(intptr_t)process;
+    rpc.args[1] = (uint64_t)sigaction;
+    rpc.args[2] = (uint64_t)rsp_xp;
+    rpc.args[3] = (uint64_t)client_xp;
+
+    // register RPC request in remote RPC fifo (non blocking)
+    rpc_send( cxy , &rpc , false );
+
+signal_dmsg("\n[DBG] %s : exit for %s / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , process_action_str( sigaction ) , CURRENT_THREAD ,
+local_cxy , CURRENT_THREAD->core->lid , hal_time_stamp() );
+}  
+
+//////////////////////////////////////////////
+void rpc_process_sigaction_server( xptr_t xp )
+{
+    process_t * process;
+    uint32_t    action;  
+    xptr_t      rsp_xp;
+    xptr_t      client_xp;
+
+    // get client cluster identifier and pointer on RPC descriptor
+    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
+    rpc_desc_t * desc        = (rpc_desc_t *)GET_PTR( xp );
+
+    // get arguments from RPC descriptor
+    process   = (process_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
+    action    = (uint32_t)             hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
+    rsp_xp    = (xptr_t)               hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) );
+    client_xp = (xptr_t)               hal_remote_lwd( XPTR( client_cxy , &desc->args[3] ) );
+    
+signal_dmsg("\n[DBG] %s : enter for %s / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , process_action_str( action ) , CURRENT_THREAD ,
+local_cxy , CURRENT_THREAD->core->lid , hal_time_stamp() );
+
+    // call relevant kernel function
+    if      (action == DELETE_ALL_THREADS  ) process_delete ( process , rsp_xp , client_xp ); 
+    else if (action == BLOCK_ALL_THREADS   ) process_block  ( process , rsp_xp , client_xp ); 
+    else if (action == UNBLOCK_ALL_THREADS ) process_unblock( process , rsp_xp , client_xp );
+
+signal_dmsg("\n[DBG] %s : exit for %s / thread %x on core[%x,%d] / cycle %d\n",
+__FUNCTION__ , process_action_str( action ) , CURRENT_THREAD ,
+local_cxy , CURRENT_THREAD->core->lid , hal_time_stamp() );
+} 
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// [10]          Marshaling functions attached to RPC_VFS_INODE_CREATE  (blocking)
 /////////////////////////////////////////////////////////////////////////////////////////
 
@@ -641,5 +1083,5 @@
 
     // register RPC request in remote RPC fifo (blocking function)
-    rpc_send_sync( cxy , &rpc );
+    rpc_send( cxy , &rpc , true );
 
     // get output values from RPC descriptor
@@ -705,5 +1147,5 @@
 
 /////////////////////////////////////////////////////////////////////////////////////////
-// [11]          Marshaling functions attached to RPC_VFS_INODE_DESTROY 
+// [11]          Marshaling functions attached to RPC_VFS_INODE_DESTROY  (blocking)
 /////////////////////////////////////////////////////////////////////////////////////////
 
@@ -727,5 +1169,5 @@
     
     // register RPC request in remote RPC fifo (blocking function)
-    rpc_send_sync( cxy , &rpc );
+    rpc_send( cxy , &rpc , true );
 
     rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
@@ -759,5 +1201,5 @@
 
 /////////////////////////////////////////////////////////////////////////////////////////
-// [12]          Marshaling functions attached to RPC_VFS_DENTRY_CREATE
+// [12]          Marshaling functions attached to RPC_VFS_DENTRY_CREATE  (blocking)
 /////////////////////////////////////////////////////////////////////////////////////////
 
@@ -787,5 +1229,5 @@
 
     // register RPC request in remote RPC fifo (blocking function)
-    rpc_send_sync( cxy , &rpc );
+    rpc_send( cxy , &rpc , true );
 
     // get output values from RPC descriptor
@@ -841,5 +1283,5 @@
 
 /////////////////////////////////////////////////////////////////////////////////////////
-// [13]          Marshaling functions attached to RPC_VFS_DENTRY_DESTROY 
+// [13]          Marshaling functions attached to RPC_VFS_DENTRY_DESTROY  (blocking)
 /////////////////////////////////////////////////////////////////////////////////////////
 
@@ -864,5 +1306,5 @@
     
     // register RPC request in remote RPC fifo (blocking function)
-    rpc_send_sync( cxy , &rpc );
+    rpc_send( cxy , &rpc , true );
 
     rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
@@ -897,5 +1339,5 @@
 
 /////////////////////////////////////////////////////////////////////////////////////////
-// [14]          Marshaling functions attached to RPC_VFS_FILE_CREATE
+// [14]          Marshaling functions attached to RPC_VFS_FILE_CREATE  (blocking)
 /////////////////////////////////////////////////////////////////////////////////////////
 
@@ -923,5 +1365,5 @@
 
     // register RPC request in remote RPC fifo (blocking function)
-    rpc_send_sync( cxy , &rpc );
+    rpc_send( cxy , &rpc , true );
 
     // get output values from RPC descriptor
@@ -969,5 +1411,5 @@
 
 /////////////////////////////////////////////////////////////////////////////////////////
-// [15]          Marshaling functions attached to RPC_VFS_FILE_DESTROY 
+// [15]          Marshaling functions attached to RPC_VFS_FILE_DESTROY  (blocking)
 /////////////////////////////////////////////////////////////////////////////////////////
 
@@ -991,5 +1433,5 @@
     
     // register RPC request in remote RPC fifo (blocking function)
-    rpc_send_sync( cxy , &rpc );
+    rpc_send( cxy , &rpc , true );
 
     rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
@@ -1023,5 +1465,5 @@
 
 /////////////////////////////////////////////////////////////////////////////////////////
-// [16]          Marshaling functions attached to RPC_VFS_INODE_LOAD  
+// [16]          Marshaling functions attached to RPC_VFS_INODE_LOAD   (blocking)
 /////////////////////////////////////////////////////////////////////////////////////////
 
@@ -1050,5 +1492,5 @@
 
     // register RPC request in remote RPC fifo (blocking function)
-    rpc_send_sync( cxy , &rpc );
+    rpc_send( cxy , &rpc , true );
 
     // get output values from RPC descriptor
@@ -1099,5 +1541,5 @@
 
 /////////////////////////////////////////////////////////////////////////////////////////
-// [17]          Marshaling functions attached to RPC_VFS_MAPPER_LOAD_ALL
+// [17]          Marshaling functions attached to RPC_VFS_MAPPER_LOAD_ALL  (blocking)
 /////////////////////////////////////////////////////////////////////////////////////////
 
@@ -1122,5 +1564,5 @@
 
     // register RPC request in remote RPC fifo (blocking function)
-    rpc_send_sync( cxy , &rpc );
+    rpc_send( cxy , &rpc , true );
 
     // get output values from RPC descriptor
@@ -1161,5 +1603,5 @@
 
 /////////////////////////////////////////////////////////////////////////////////////////
-// [18]          Marshaling functions attached to RPC_FATFS_GET_CLUSTER 
+// [18]          Marshaling functions attached to RPC_FATFS_GET_CLUSTER  (blocking)
 /////////////////////////////////////////////////////////////////////////////////////////
 
@@ -1189,5 +1631,5 @@
 
     // register RPC request in remote RPC fifo 
-    rpc_send_sync( cxy , &rpc );
+    rpc_send( cxy , &rpc , true );
 
     // get output argument from rpc descriptor
@@ -1235,5 +1677,5 @@
 
 /////////////////////////////////////////////////////////////////////////////////////////
-// [20]          Marshaling functions attached to RPC_VMM_GET_VSEG
+// [20]          Marshaling functions attached to RPC_VMM_GET_VSEG  (blocking)
 /////////////////////////////////////////////////////////////////////////////////////////
 
@@ -1261,5 +1703,5 @@
 
     // register RPC request in remote RPC fifo (blocking function)
-    rpc_send_sync( cxy , &rpc );
+    rpc_send( cxy , &rpc , true );
 
     // get output argument from rpc descriptor
@@ -1308,5 +1750,5 @@
 
 /////////////////////////////////////////////////////////////////////////////////////////
-// [21]          Marshaling functions attached to RPC_VMM_GET_PTE 
+// [21]          Marshaling functions attached to RPC_VMM_GET_PTE  (blocking)
 /////////////////////////////////////////////////////////////////////////////////////////
 
@@ -1337,5 +1779,5 @@
 
     // register RPC request in remote RPC fifo (blocking function)
-    rpc_send_sync( cxy , &rpc );
+    rpc_send( cxy , &rpc , true );
 
     // get output argument from rpc descriptor
@@ -1386,5 +1828,5 @@
 
 /////////////////////////////////////////////////////////////////////////////////////////
-// [22]          Marshaling functions attached to RPC_KCM_ALLOC 
+// [22]          Marshaling functions attached to RPC_KCM_ALLOC  (blocking)
 /////////////////////////////////////////////////////////////////////////////////////////
 
@@ -1408,6 +1850,6 @@
     rpc.args[0] = (uint64_t)kmem_type;
 
-    // register RPC request in remote RPC fifo 
-    rpc_send_sync( cxy , &rpc );
+    // register RPC request in remote RPC fifo (blocking function)
+    rpc_send( cxy , &rpc , true );
 
     // get output arguments from RPC descriptor
@@ -1449,5 +1891,5 @@
 
 /////////////////////////////////////////////////////////////////////////////////////////
-// [23]          Marshaling functions attached to RPC_KCM_FREE 
+// [23]          Marshaling functions attached to RPC_KCM_FREE  (blocking)
 /////////////////////////////////////////////////////////////////////////////////////////
 
@@ -1472,6 +1914,6 @@
     rpc.args[1] = (uint64_t)kmem_type;
 
-    // register RPC request in remote RPC fifo 
-    rpc_send_sync( cxy , &rpc );
+    // register RPC request in remote RPC fifo (blocking function)
+    rpc_send( cxy , &rpc , true );
 
     rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
@@ -1540,5 +1982,5 @@
 
     // register RPC request in remote RPC fifo (blocking function)
-    rpc_send_sync( cxy , &rpc );
+    rpc_send( cxy , &rpc , true );
 
     // get output values from RPC descriptor
@@ -1608,5 +2050,5 @@
 
 /////////////////////////////////////////////////////////////////////////////////////////
-// [25]          Marshaling functions attached to RPC_MAPPER_GET_PAGE
+// [25]          Marshaling functions attached to RPC_MAPPER_GET_PAGE (blocking)
 /////////////////////////////////////////////////////////////////////////////////////////
 
@@ -1633,5 +2075,5 @@
 
     // register RPC request in remote RPC fifo (blocking function)
-    rpc_send_sync( cxy , &rpc );
+    rpc_send( cxy , &rpc , true );
 
     // get output values from RPC descriptor
@@ -1670,5 +2112,5 @@
 
 /////////////////////////////////////////////////////////////////////////////////////////
-// [26]          Marshaling functions attached to RPC_VMM_CREATE_VSEG
+// [26]          Marshaling functions attached to RPC_VMM_CREATE_VSEG (blocking)
 /////////////////////////////////////////////////////////////////////////////////////////
 
@@ -1707,5 +2149,5 @@
 
     // register RPC request in remote RPC fifo (blocking function)
-    rpc_send_sync( cxy , &rpc );
+    rpc_send( cxy , &rpc , true );
 
     // get output values from RPC descriptor
@@ -1757,5 +2199,5 @@
 
 /////////////////////////////////////////////////////////////////////////////////////////
-// [27]          Marshaling functions attached to RPC_SCHED_DISPLAY
+// [27]          Marshaling functions attached to RPC_SCHED_DISPLAY (blocking)
 /////////////////////////////////////////////////////////////////////////////////////////
 
@@ -1779,5 +2221,5 @@
 
     // register RPC request in remote RPC fifo (blocking function)
-    rpc_send_sync( cxy , &rpc );
+    rpc_send( cxy , &rpc , true );
 
     rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
@@ -1809,5 +2251,5 @@
 
 /////////////////////////////////////////////////////////////////////////////////////////
-// [28]          Marshaling functions attached to RPC_VMM_SET_COW
+// [28]          Marshaling functions attached to RPC_VMM_SET_COW (blocking)
 /////////////////////////////////////////////////////////////////////////////////////////
 
@@ -1831,5 +2273,5 @@
 
     // register RPC request in remote RPC fifo (blocking function)
-    rpc_send_sync( cxy , &rpc );
+    rpc_send( cxy , &rpc , true );
 
     rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
@@ -1862,291 +2304,3 @@
 }
 
-/***************************************************************************************/
-/************ Generic functions supporting RPCs : client side **************************/
-/***************************************************************************************/
-
-////////////////////////////////////////////
-void rpc_send_sync( cxy_t        server_cxy, 
-                    rpc_desc_t * rpc )
-{
-    error_t    error;
-
-    thread_t * this = CURRENT_THREAD;
-    core_t   * core = this->core;
-
-    // register client thread pointer and core lid in RPC descriptor
-    rpc->thread    = this;
-    rpc->lid       = core->lid;
-
-    // build an extended pointer on the RPC descriptor
-	xptr_t   desc_xp = XPTR( local_cxy , rpc );
-
-    // get local pointer on rpc_fifo in remote cluster, with the 
-    // assumption that local pointers are identical in all clusters
-    remote_fifo_t * rpc_fifo = &LOCAL_CLUSTER->rpc_fifo;
-
-	// try to post an item in remote fifo
-    // deschedule and retry if remote fifo full
-    do
-    { 
-        error = remote_fifo_put_item( XPTR( server_cxy , rpc_fifo ),
-                                      (uint64_t )desc_xp );
-	    if ( error ) 
-        {
-            printk("\n[WARNING] %s : cluster %x cannot post RPC to cluster %x\n",
-            __FUNCTION__ , local_cxy , server_cxy );
-
-            if( thread_can_yield() ) sched_yield("RPC fifo full");
-        }
-    }
-    while( error );
- 
-    hal_fence();
-	
-    // send IPI to the remote core corresponding to the client core
-	dev_pic_send_ipi( server_cxy , core->lid );
-
-    // wait RPC completion:
-    // - busy waiting policy during kernel_init, or if threads cannot yield
-    // - block and deschedule in all other cases
-
-    if( (this->type == THREAD_IDLE) || (thread_can_yield() == false) ) // busy waiting
-    {
-
-grpc_dmsg("\n[DBG] %s : core[%x,%d] / thread %s busy waiting after registering RPC\n"
-"        rpc = %d / server = %x / cycle %d\n",
-__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , thread_type_str(this->type) ,
-rpc->index , server_cxy , hal_time_stamp() );
-
-        while( rpc->response ) hal_fixed_delay( 100 );
-    
-grpc_dmsg("\n[DBG] %s : core[%x,%d] / thread %s exit after RPC completion\n",
-__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , thread_type_str(this->type) );
-
-    } 
-    else                                                              // block & deschedule
-    {
-
-grpc_dmsg("\n[DBG] %s : core[%x,%d] / thread %s deschedule after registering RPC\n"
-"        rpc = %d / server = %x / cycle %d\n",
-__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , thread_type_str(this->type) ,
-rpc->index , server_cxy , hal_time_stamp() );
-
-        thread_block( this , THREAD_BLOCKED_RPC );
-        sched_yield("client blocked on RPC");
-
-grpc_dmsg("\n[DBG] %s : core[%x,%d] / thread %s resumes after RPC completion\n",
-__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , thread_type_str(this->type) );
-
-    }
-
-    // check response available
-    assert( (rpc->response == 0) , __FUNCTION__, "illegal RPC response\n" );
-
-    // acknowledge the IPI sent by the server
-    dev_pic_ack_ipi();
-    
-}  // end rpc_send_sync()
-
-
-
-/***************************************************************************************/
-/************ Generic functions supporting RPCs : server side **************************/
-/***************************************************************************************/
-
-////////////////
-void rpc_check()
-{
-    error_t         error;
-    thread_t      * thread;  
-    uint32_t        sr_save;
-
-    bool_t          found    = false;
-	thread_t      * this     = CURRENT_THREAD;
-    core_t        * core     = this->core;
-    scheduler_t   * sched    = &core->scheduler;
-	remote_fifo_t * rpc_fifo = &LOCAL_CLUSTER->rpc_fifo;
-
-grpc_dmsg("\n[DBG] %s : core[%x,%d] / interrupted thread %s / cycle %d\n",
-__FUNCTION__, local_cxy, core->lid, thread_type_str(this->type), hal_time_stamp() );
-
-    // interrupted thread not preemptable during RPC chek
-	hal_disable_irq( &sr_save );
-
-    // check RPC FIFO not empty and no RPC thread handling it  
-	if( (rpc_fifo->owner == 0) && (local_fifo_is_empty(rpc_fifo) == false) )
-    {
-        // search one non blocked RPC thread   
-        list_entry_t * iter;
-        LIST_FOREACH( &sched->k_root , iter )
-        {
-            thread = LIST_ELEMENT( iter , thread_t , sched_list );
-            if( (thread->type == THREAD_RPC) && (thread->blocked == 0 ) ) 
-            {
-                found = true;
-                break;
-            }
-        }
-
-        // create new RPC thread if not found    
-        if( found == false )                    
-        {
-            error = thread_kernel_create( &thread,
-                                          THREAD_RPC, 
-			                              &rpc_thread_func, 
-                                          NULL,
-			                              this->core->lid );
-	        if( error ) 
-            {
-                printk("\n[WARNING] in %s : no memory for new RPC thread in cluster %x\n",
-                __FUNCTION__ , local_cxy );
-            }
-            else
-            {
-                // unblock created RPC thread
-                thread->blocked = 0;
-
-                // update core descriptor counter  
-	            hal_atomic_add( &LOCAL_CLUSTER->rpc_threads , 1 );
-
-grpc_dmsg("\n[DBG] %s : core [%x,%d] creates a new RPC thread %x / cycle %d\n", 
-__FUNCTION__ , local_cxy , core->lid , thread->trdid , hal_time_stamp() );
-
-            }
-        }
-    }
-
-grpc_dmsg("\n[DBG] %s : core[%x,%d] / interrupted thread %s deschedules / cycle %d\n", 
-__FUNCTION__, local_cxy, core->lid, thread_type_str(this->type), hal_time_stamp() );
-
-    // interrupted thread deschedule always           
-	sched_yield("IPI received");
-
-grpc_dmsg("\n[DBG] %s : core[%x,%d] / interrupted thread %s resume / cycle %d\n", 
-__FUNCTION__, local_cxy, core->lid, thread_type_str(this->type), hal_time_stamp() );
-
-    // interrupted thread restore IRQs after resume 
-	hal_restore_irq( sr_save );
-
-} // end rpc_check()
-
-
-//////////////////////
-void rpc_thread_func()
-{
-    uint32_t     count;       // handled RPC requests counter
-    error_t      empty;       // local RPC fifo state
-    xptr_t       desc_xp;     // extended pointer on RPC request
-    cxy_t        desc_cxy;    // RPC request cluster (client) 
-    rpc_desc_t * desc_ptr;    // RPC request local pointer 
-    uint32_t     index;       // RPC request index 
-    uint32_t     responses;   // number of responses received by client 
-    thread_t   * thread_ptr;  // local pointer on client thread
-    lid_t        core_lid;    // local index of client core
- 
-    // makes RPC thread not preemptable
-	hal_disable_irq( NULL );
-  
-	thread_t      * this     = CURRENT_THREAD;
-	remote_fifo_t * rpc_fifo = &LOCAL_CLUSTER->rpc_fifo;
-
-    // two embedded loops:
-    // - external loop : "infinite" RPC thread
-    // - internal loop : handle up to CONFIG_RPC_PENDING_MAX RPC requests
- 
-	while(1)  // external loop
-	{
-        // try to take RPC_FIFO ownership
-        if( hal_atomic_test_set( &rpc_fifo->owner , this->trdid ) )
-        {
-            // initializes RPC requests counter
-            count = 0;
-
-            // acknowledge local IPI 
-            dev_pic_ack_ipi();
-
-		    // exit internal loop in three cases:
-            // - RPC fifo is empty
-            // - ownership has been lost (because descheduling)
-            // - max number of RPCs is reached
-	        while( 1 )  // internal loop
-            {
-  	            empty = local_fifo_get_item( rpc_fifo , (uint64_t *)&desc_xp );
-
-	            if ( empty == 0 ) // one RPC request found
-                {
-                    // get client cluster and pointer on RPC descriptor
-                    desc_cxy = (cxy_t)GET_CXY( desc_xp );
-                    desc_ptr = (rpc_desc_t *)GET_PTR( desc_xp );
-
-                    // get rpc index from RPC descriptor
-	                index = hal_remote_lw( XPTR( desc_cxy , &desc_ptr->index ) );
-
-grpc_dmsg("\n[DBG] %s : core[%x,%d] / RPC thread %x / starts rpc %d / cycle %d\n",
-__FUNCTION__ , local_cxy , this->core->lid , this->trdid , index , hal_time_stamp() );
-
-                    // call the relevant server function
-                    rpc_server[index]( desc_xp );
-
-grpc_dmsg("\n[DBG] %s : core[%x,%d] / RPC thread %x / completes rpc %d / cycle %d\n",
-__FUNCTION__ , local_cxy , this->core->lid , this->trdid , index , hal_time_stamp() );
-
-                    // increment handled RPC counter
-  	                count++;
-
-                    // decrement response counter in RPC descriptor
-                    responses = hal_remote_atomic_add(XPTR( desc_cxy, &desc_ptr->response ), -1);
-
-                    // unblock client thread  and send IPI to client core if last response
-                    if( responses == 1 )
-                    { 
-                        // get pointer on client thread and unblock it
-                        thread_ptr = (thread_t *)hal_remote_lpt(XPTR(desc_cxy,&desc_ptr->thread));
-                        thread_unblock( XPTR(desc_cxy,thread_ptr) , THREAD_BLOCKED_RPC );
-
-                        hal_fence();
-
-                        // get client core lid and send IPI
-                        core_lid = hal_remote_lw(XPTR(desc_cxy, &desc_ptr->lid));
-	                    dev_pic_send_ipi( desc_cxy , core_lid );
-                    }
-		        }
-	
-                // chek exit condition
-  		        if( local_fifo_is_empty( rpc_fifo )  || 
-                    (rpc_fifo->owner != this->trdid) || 
-                    (count >= CONFIG_RPC_PENDING_MAX) ) break;
-         	} // end internal loop
-
-            // release rpc_fifo ownership if not lost
-            if( rpc_fifo->owner == this->trdid ) rpc_fifo->owner = 0;
-        }
-
-        // sucide if too many RPC threads in cluster
-        if( LOCAL_CLUSTER->rpc_threads >= CONFIG_RPC_THREADS_MAX )
-	    {
-
-grpc_dmsg("\n[DBG] %s : core[%x,%d] (RPC thread %x) suicide at cycle %d\n", 
-__FUNCTION__, local_cxy, this->core->lid, this->trdid, hal_time_stamp() );
-
-            // update RPC threads counter
-	        hal_atomic_add( &LOCAL_CLUSTER->rpc_threads , -1 );
-
-            // suicide
-	        thread_exit();
-	    }
-
-grpc_dmsg("\n[DBG] %s : core[%x,%d] (RPC thread %x) deschedules / cycle %d\n", 
-__FUNCTION__, local_cxy, this->core->lid, this->trdid, hal_time_stamp() );
-
-        // deschedule without blocking
-        sched_yield("RPC fifo empty or too much work");
-
-grpc_dmsg("\n[DBG] %s : core[%x,%d] (RPC thread %x) resumes / cycle %d\n", 
-__FUNCTION__, local_cxy, this->core->lid, this->trdid, hal_time_stamp() );
-
-	} // end external loop
-
-} // end rpc_thread_func()
-
-
+
