source: trunk/kernel/kern/rpc.c @ 466

Last change on this file since 466 was 459, checked in by alain, 6 years ago

Introduce the math library, to support the floating point
data used by the multi-thread fft application.
Fix several bugs regarding the FPU context save/restore.
Introduce support for the %f format in printf.

File size: 81.5 KB
Line 
1/*
2 * rpc.c - RPC operations implementation.
3 *
4 * Author    Alain Greiner (2016,2017,2018)
5 *
6 * Copyright (c)  UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <kernel_config.h>
25#include <hal_kernel_types.h>
26#include <hal_atomic.h>
27#include <hal_remote.h>
28#include <hal_irqmask.h>
29#include <hal_special.h>
30#include <printk.h>
31#include <remote_sem.h>
32#include <core.h>
33#include <mapper.h>
34#include <chdev.h>
35#include <bits.h>
36#include <thread.h>
37#include <cluster.h>
38#include <process.h>
39#include <vfs.h>
40#include <fatfs.h>
41#include <rpc.h>
42
43
44/////////////////////////////////////////////////////////////////////////////////////////
45//      array of function pointers  (must be consistent with enum in rpc.h)
46/////////////////////////////////////////////////////////////////////////////////////////
47
48rpc_server_t * rpc_server[RPC_MAX_INDEX] =
49{
50    &rpc_pmem_get_pages_server,         // 0
51    &rpc_pmem_release_pages_server,     // 1
52    &rpc_undefined,                     // 2    unused slot
53    &rpc_process_make_fork_server,      // 3
54    &rpc_undefined,                     // 4    unused slot
55    &rpc_undefined,                     // 5    unused slot
56    &rpc_thread_user_create_server,     // 6
57    &rpc_thread_kernel_create_server,   // 7
58    &rpc_undefined,                     // 8    unused slot       
59    &rpc_process_sigaction_server,      // 9
60
61    &rpc_vfs_inode_create_server,       // 10 
62    &rpc_vfs_inode_destroy_server,      // 11 
63    &rpc_vfs_dentry_create_server,      // 12 
64    &rpc_vfs_dentry_destroy_server,     // 13 
65    &rpc_vfs_file_create_server,        // 14
66    &rpc_vfs_file_destroy_server,       // 15
67    &rpc_vfs_inode_load_server,         // 16
68    &rpc_vfs_mapper_load_all_server,    // 17
69    &rpc_fatfs_get_cluster_server,      // 18
70    &rpc_undefined,                     // 19   unused slot
71
72    &rpc_vmm_get_vseg_server,           // 20
73    &rpc_vmm_get_pte_server,            // 21
74    &rpc_kcm_alloc_server,              // 22
75    &rpc_kcm_free_server,               // 23
76    &rpc_mapper_move_buffer_server,     // 24
77    &rpc_mapper_get_page_server,        // 25
78    &rpc_vmm_create_vseg_server,        // 26
79    &rpc_undefined,                     // 27   unused slot
80    &rpc_vmm_set_cow_server,            // 28
81    &rpc_vmm_display_server,            // 29
82};
83
84//////////////////////////////////////////////
85void __attribute__((noinline)) rpc_undefined()
86{
87        assert( false , __FUNCTION__ , "called in cluster %x", local_cxy );
88}
89
90/***************************************************************************************/
91/************ Generic functions supporting RPCs : client side **************************/
92/***************************************************************************************/
93
94///////////////////////////////////////
95void rpc_send( cxy_t        server_cxy, 
96               rpc_desc_t * rpc )
97{
98    lid_t              server_core_lid;
99    lid_t              client_core_lid;
100    volatile error_t   full;
101    thread_t         * this;
102
103    full            = 0;
104    this            = CURRENT_THREAD;
105    client_core_lid = this->core->lid;
106
107#if DEBUG_RPC_CLIENT_GENERIC
108uint32_t cycle = (uint32_t)hal_get_cycles();
109if( DEBUG_RPC_CLIENT_GENERIC < cycle ) 
110printk("\n[DBG] %s : thread %x in process %x enter for rpc[%d] / cycle %d\n",
111__FUNCTION__, this->trdid, this->process->pid, rpc->index, cycle );
112#endif
113
114    // select a server_core : use client core index if possible / core 0 otherwise
115    if( client_core_lid < hal_remote_lw( XPTR( server_cxy , &LOCAL_CLUSTER->cores_nr ) ) )
116    {
117        server_core_lid = client_core_lid;
118    }
119    else
120    {   
121        server_core_lid = 0;
122    }
123
124    // register client_thread pointer and client_core lid in RPC descriptor
125    rpc->thread = this;
126    rpc->lid    = client_core_lid;
127
128    // build extended pointer on the RPC descriptor
129        xptr_t   desc_xp = XPTR( local_cxy , rpc );
130
131    // get local pointer on rpc_fifo in remote cluster,
132    remote_fifo_t * rpc_fifo = &LOCAL_CLUSTER->rpc_fifo[server_core_lid];
133
134        // post RPC in remote fifo / deschedule and retry if fifo full
135    do
136    { 
137        full = remote_fifo_put_item( XPTR( server_cxy , rpc_fifo ), (uint64_t )desc_xp );
138            if ( full ) 
139        {
140            printk("\n[WARNING] %s : cluster %x cannot post RPC to cluster %x\n",
141            __FUNCTION__ , local_cxy , server_cxy );
142
143            // deschedule without blocking
144            sched_yield("RPC fifo full");
145        }
146    }
147    while( full );
148 
149    hal_fence();
150
151#if DEBUG_RPC_CLIENT_GENERIC
152cycle = (uint32_t)hal_get_cycles();
153if( DEBUG_RPC_CLIENT_GENERIC < cycle ) 
154printk("\n[DBG] %s : thread %x in process %x / rpc[%d] / rpc_ptr %x / cycle %d\n",
155__FUNCTION__, this->trdid, this->process->pid, rpc->index, rpc, cycle );
156#endif
157       
158   // send IPI to the selected server core
159   dev_pic_send_ipi( server_cxy , server_core_lid );
160
161    // wait RPC completion before returning if blocking RPC
162    // - busy waiting policy during kernel_init, or if threads cannot yield
163    // - block and deschedule in all other cases
164    if ( rpc->blocking )
165    {
166        if( (this->type == THREAD_IDLE) || (thread_can_yield() == false) ) // busy waiting
167        {
168
169#if DEBUG_RPC_CLIENT_GENERIC
170cycle = (uint32_t)hal_get_cycles();
171if( DEBUG_RPC_CLIENT_GENERIC < cycle ) 
172printk("\n[DBG] %s : thread %x in process %x busy waiting for rpc[%d] / cycle %d\n",
173__FUNCTION__, this->trdid, this->process->pid, rpc->index , cycle );
174#endif
175
176            while( rpc->responses ) hal_fixed_delay( 100 );
177   
178#if DEBUG_RPC_CLIENT_GENERIC
179cycle = (uint32_t)hal_get_cycles();
180if( DEBUG_RPC_CLIENT_GENERIC < cycle ) 
181printk("\n[DBG] %s : thread %x in process %x resumes for rpc[%d] / cycle %d\n",
182__FUNCTION__, this->trdid, this->process->pid, rpc->index, cycle );
183#endif
184        } 
185        else                                                         // block & deschedule
186        {
187
188#if DEBUG_RPC_CLIENT_GENERIC
189cycle = (uint32_t)hal_get_cycles();
190if( DEBUG_RPC_CLIENT_GENERIC < cycle ) 
191printk("\n[DBG] %s : thread %x in process %x blocks & deschedules for rpc[%d] / cycle %d\n",
192__FUNCTION__, this->trdid, this->process->pid, rpc->index , cycle );
193#endif
194            thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_RPC );
195            sched_yield("blocked on RPC");
196
197#if DEBUG_RPC_CLIENT_GENERIC
198cycle = (uint32_t)hal_get_cycles();
199if( DEBUG_RPC_CLIENT_GENERIC < cycle ) 
200printk("\n[DBG] %s : thread %x in process %x resumes for rpc[%d] / cycle %d\n",
201__FUNCTION__, this->trdid, this->process->pid, rpc->index, cycle );
202#endif
203        }
204
205        // check response available
206        assert( (rpc->responses == 0) , __FUNCTION__, "illegal RPC response\n" );
207    }
208    else  // non blocking RPC
209    {
210
211#if DEBUG_RPC_CLIENT_GENERIC
212cycle = (uint32_t)hal_get_cycles();
213if( DEBUG_RPC_CLIENT_GENERIC < cycle ) 
214printk("\n[DBG] %s : thread %x in process %x returns for non blocking rpc[%d] / cycle %d\n",
215__FUNCTION__, this->trdid, this->process->pid, rpc->index, cycle );
216#endif
217
218    }
219}  // end rpc_send()
220
221
222/***************************************************************************************/
223/************ Generic functions supporting RPCs : server side **************************/
224/***************************************************************************************/
225
226////////////////
227void rpc_check()
228{
229    error_t         error;
230    thread_t      * thread; 
231    uint32_t        sr_save;
232
233#if DEBUG_RPC_SERVER_GENERIC
234uint32_t cycle;
235#endif
236
237    bool_t          found    = false;
238        thread_t      * this     = CURRENT_THREAD;
239    core_t        * core     = this->core;
240    scheduler_t   * sched    = &core->scheduler;
241        remote_fifo_t * rpc_fifo = &LOCAL_CLUSTER->rpc_fifo[core->lid];
242
243    // interrupted thread not preemptable during RPC chek
244        hal_disable_irq( &sr_save );
245
246    // activate (or create) RPC thread if RPC FIFO not empty and no acive RPC thread 
247        if( (rpc_fifo->owner == 0) && (local_fifo_is_empty(rpc_fifo) == false) )
248    {
249
250#if DEBUG_RPC_SERVER_GENERIC
251cycle = (uint32_t)hal_get_cycles();
252if( DEBUG_RPC_SERVER_GENERIC < cycle ) 
253printk("\n[DBG] %s : RPC FIFO non empty for core[%x,%d] / cycle %d\n",
254__FUNCTION__, local_cxy, core->lid, cycle );
255#endif
256
257        // search one IDLE RPC thread associated to the selected core   
258        list_entry_t * iter;
259        LIST_FOREACH( &sched->k_root , iter )
260        {
261            thread = LIST_ELEMENT( iter , thread_t , sched_list );
262            if( (thread->type == THREAD_RPC) && (thread->blocked == THREAD_BLOCKED_IDLE ) ) 
263            {
264                // unblock found RPC thread
265                thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_IDLE );
266
267                // exit loop
268                found = true;
269                break;
270            }
271        }
272
273        // create new RPC thread for the selected core if not found   
274        if( found == false )                   
275        {
276            error = thread_kernel_create( &thread,
277                                          THREAD_RPC, 
278                                                      &rpc_thread_func, 
279                                          NULL,
280                                                      core->lid );
281                 
282            assert( (error == 0), __FUNCTION__ ,
283            "no memory to allocate a new RPC thread in cluster %x", local_cxy );
284
285            // unblock created RPC thread
286            thread->blocked = 0;
287
288            // update RRPC threads counter 
289            hal_atomic_add( &LOCAL_CLUSTER->rpc_threads[core->lid] , 1 );
290
291#if DEBUG_RPC_SERVER_GENERIC
292cycle = (uint32_t)hal_get_cycles();
293if( DEBUG_RPC_SERVER_GENERIC < cycle ) 
294printk("\n[DBG] %s : new RPC thread %x created for core[%x,%d] / cycle %d\n",
295__FUNCTION__, thread, local_cxy, core->lid, cycle );
296#endif
297        }
298    }
299
300#if DEBUG_RPC_SERVER_GENERIC
301cycle = (uint32_t)hal_get_cycles();
302if( DEBUG_RPC_SERVER_GENERIC < cycle ) 
303printk("\n[DBG] %s : interrupted thread %x deschedules on core[%x,%d] / cycle %d\n",
304__FUNCTION__, this, local_cxy, core->lid, cycle );
305#endif
306
307    // interrupted thread always deschedule         
308        sched_yield("IPI received");
309
310#if DEBUG_RPC_SERVER_GENERIC
311cycle = (uint32_t)hal_get_cycles();
312if( DEBUG_RPC_SERVER_GENERIC < cycle ) 
313printk("\n[DBG] %s : interrupted thread %x resumes on core[%x,%d] / cycle %d\n",
314__FUNCTION__, this, local_cxy, core->lid, cycle );
315#endif
316
317    // interrupted thread restore IRQs after resume
318        hal_restore_irq( sr_save );
319
320} // end rpc_check()
321
322
323//////////////////////
324void rpc_thread_func()
325{
326    error_t         empty;              // local RPC fifo state
327    xptr_t          desc_xp;            // extended pointer on RPC request
328    cxy_t           desc_cxy;           // RPC request cluster (client)
329    rpc_desc_t    * desc_ptr;           // RPC request local pointer
330    uint32_t        index;              // RPC request index
331    thread_t      * client_ptr;         // local pointer on client thread
332        thread_t      * server_ptr;         // local pointer on server thread
333    xptr_t          server_xp;          // extended pointer on server thread
334    lid_t           client_core_lid;    // local index of client core
335    lid_t           server_core_lid;    // local index of server core
336    bool_t          blocking;           // blocking RPC when true
337        remote_fifo_t * rpc_fifo;           // local pointer on RPC fifo
338 
339    // makes RPC thread not preemptable
340        hal_disable_irq( NULL );
341 
342        server_ptr      = CURRENT_THREAD;
343    server_xp       = XPTR( local_cxy , server_ptr );
344    server_core_lid = server_ptr->core->lid;
345        rpc_fifo        = &LOCAL_CLUSTER->rpc_fifo[server_core_lid];
346
347    // two embedded loops:
348    // - external loop : "infinite" RPC thread
349    // - internal loop : handle one RPC request per iteration
350 
351        while(1)  // infinite loop
352        {
353        // try to take RPC_FIFO ownership
354        if( hal_atomic_test_set( &rpc_fifo->owner , server_ptr->trdid ) )
355        {
356
357#if DEBUG_RPC_SERVER_GENERIC
358uint32_t cycle = (uint32_t)hal_get_cycles();
359if( DEBUG_RPC_SERVER_GENERIC < cycle ) 
360printk("\n[DBG] %s : RPC thread %x in cluster %x takes RPC fifo ownership / cycle %d\n",
361__FUNCTION__, server_ptr, local_cxy, cycle );
362#endif
363                while( 1 )  //  one RPC request per iteration
364            {
365                    empty = local_fifo_get_item( rpc_fifo , (uint64_t *)&desc_xp );
366
367                // exit when FIFO empty or FIFO ownership lost (in case of descheduling)
368                    if ( (empty == 0) && (rpc_fifo->owner == server_ptr->trdid) )
369                {
370                    // get client cluster and pointer on RPC descriptor
371                    desc_cxy = GET_CXY( desc_xp );
372                    desc_ptr = GET_PTR( desc_xp );
373
374                        index    = hal_remote_lw( XPTR( desc_cxy , &desc_ptr->index ) );
375                    blocking = hal_remote_lw( XPTR( desc_cxy , &desc_ptr->blocking ) );
376
377#if DEBUG_RPC_SERVER_GENERIC
378cycle = (uint32_t)hal_get_cycles();
379if( DEBUG_RPC_SERVER_GENERIC < cycle ) 
380printk("\n[DBG] %s : RPC thread %x in cluster %x got rpc[%d] / rpc_cxy %x / rpc_ptr %x\n",
381__FUNCTION__, server_ptr, local_cxy, index, desc_cxy, desc_ptr );
382#endif
383                    // call the relevant server function
384                    rpc_server[index]( desc_xp );
385
386#if DEBUG_RPC_SERVER_GENERIC
387cycle = (uint32_t)hal_get_cycles();
388if( DEBUG_RPC_SERVER_GENERIC < cycle ) 
389printk("\n[DBG] %s : RPC thread %x in cluster %x completes rpc[%d] / rpc_ptr %x / cycle %d\n",
390__FUNCTION__, server_ptr, local_cxy, index, desc_ptr, cycle );
391#endif
392                    // decrement response counter in RPC descriptor if blocking
393                    if( blocking )
394                    {
395                        // decrement responses counter in RPC descriptor
396                        hal_remote_atomic_add( XPTR( desc_cxy, &desc_ptr->responses ), -1 );
397
398                        // get client thread pointer and client core lid from RPC descriptor
399                        client_ptr      = hal_remote_lpt( XPTR( desc_cxy , &desc_ptr->thread ) );
400                        client_core_lid = hal_remote_lw ( XPTR( desc_cxy , &desc_ptr->lid ) );
401
402                        // unblock client thread
403                        thread_unblock( XPTR( desc_cxy , client_ptr ) , THREAD_BLOCKED_RPC );
404
405                        hal_fence();
406
407#if DEBUG_RPC_SERVER_GENERIC
408cycle = (uint32_t)hal_get_cycles();
409if( DEBUG_RPC_SERVER_GENERIC < cycle ) 
410printk("\n[DBG] %s : RPC thread %x (cluster %x) unblocked client thread %x (cluster %x)\n",
411__FUNCTION__, server_ptr, local_cxy, client_ptr, desc_cxy, cycle );
412#endif
413                        // send IPI to client core
414                            // dev_pic_send_ipi( desc_cxy , client_core_lid );
415                    }
416                        }
417                else
418                {
419                    break;
420                }
421                } // end internal loop
422
423            // release rpc_fifo ownership if not lost
424            if( rpc_fifo->owner == server_ptr->trdid ) rpc_fifo->owner = 0;
425
426        }  // end if RPC fifo
427
428        // RPC thread blocks on IDLE
429        thread_block( server_xp , THREAD_BLOCKED_IDLE );
430
431        // sucide if too many RPC threads / simply deschedule otherwise
432        if( LOCAL_CLUSTER->rpc_threads[server_core_lid] >= CONFIG_RPC_THREADS_MAX )
433            {
434
435#if DEBUG_RPC_SERVER_GENERIC
436uint32_t cycle = (uint32_t)hal_get_cycles();
437if( DEBUG_RPC_SERVER_GENERIC < cycle ) 
438printk("\n[DBG] %s : RPC thread %x in cluster %x suicides / cycle %d\n",
439__FUNCTION__, server_ptr, local_cxy, cycle );
440#endif
441            // update RPC threads counter
442                hal_atomic_add( &LOCAL_CLUSTER->rpc_threads , -1 );
443
444            // RPC thread blocks on GLOBAL
445                thread_block( server_xp , THREAD_BLOCKED_GLOBAL );
446
447            // RPC thread set the REQ_DELETE flag to suicide
448            hal_remote_atomic_or( server_xp , THREAD_FLAG_REQ_DELETE );
449            }
450        else
451        {
452
453#if DEBUG_RPC_SERVER_GENERIC
454uint32_t cycle = (uint32_t)hal_get_cycles();
455if( DEBUG_RPC_SERVER_GENERIC < cycle ) 
456printk("\n[DBG] %s : RPC thread %x in cluster %x block & deschedules / cycle %d\n",
457__FUNCTION__, server_ptr, local_cxy, cycle );
458#endif
459
460            // RPC thread deschedules
461            assert( thread_can_yield( server_ptr ) , __FUNCTION__, "illegal sched_yield\n" );
462            sched_yield("RPC fifo empty");
463        }
464
465        } // end infinite loop
466
467} // end rpc_thread_func()
468
469
470/////////////////////////////////////////////////////////////////////////////////////////
471// [0]           Marshaling functions attached to RPC_PMEM_GET_PAGES (blocking)
472/////////////////////////////////////////////////////////////////////////////////////////
473
474///////////////////////////////////////////////
475void rpc_pmem_get_pages_client( cxy_t      cxy,
476                                uint32_t   order,      // in
477                                page_t  ** page )      // out
478{
479#if DEBUG_RPC_PMEM_GET_PAGES
480uint32_t cycle = (uint32_t)hal_get_cycles();
481if( cycle > DEBUG_RPC_PMEM_GET_PAGES )
482printk("\n[DBG] %s : thread %x enter on core[%x,%d] / cycle %d\n",
483__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
484#endif
485
486    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
487
488    // initialise RPC descriptor header
489    rpc_desc_t  rpc;
490    rpc.index     = RPC_PMEM_GET_PAGES;
491    rpc.blocking  = true;
492    rpc.responses = 1;
493
494    // set input arguments in RPC descriptor
495    rpc.args[0] = (uint64_t)order;
496
497    // register RPC request in remote RPC fifo
498    rpc_send( cxy , &rpc );
499
500    // get output arguments from RPC descriptor
501    *page = (page_t *)(intptr_t)rpc.args[1];
502
503#if DEBUG_RPC_PMEM_GET_PAGES
504cycle = (uint32_t)hal_get_cycles();
505if( cycle > DEBUG_RPC_PMEM_GET_PAGES )
506printk("\n[DBG] %s : thread %x exit / cycle %d\n",
507__FUNCTION__ , CURRENT_THREAD , cycle );
508#endif
509}
510
511///////////////////////////////////////////
512void rpc_pmem_get_pages_server( xptr_t xp )
513{
514#if DEBUG_RPC_PMEM_GET_PAGES
515uint32_t cycle = (uint32_t)hal_get_cycles();
516if( cycle > DEBUG_RPC_PMEM_GET_PAGES )
517printk("\n[DBG] %s : thread %x enter on core[%x,%d] / cycle %d\n",
518__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
519#endif
520
521    // get client cluster identifier and pointer on RPC descriptor
522    cxy_t        cxy  = GET_CXY( xp );
523    rpc_desc_t * desc = GET_PTR( xp );
524
525    // get input arguments from client RPC descriptor
526    uint32_t order = (uint32_t)hal_remote_lwd( XPTR( cxy , &desc->args[0] ) );
527   
528    // call local pmem allocator
529    page_t * page = ppm_alloc_pages( order ); 
530
531    // set output arguments into client RPC descriptor
532    hal_remote_swd( XPTR( cxy , &desc->args[1] ) , (uint64_t)(intptr_t)page );
533
534#if DEBUG_RPC_PMEM_GET_PAGES
535cycle = (uint32_t)hal_get_cycles();
536if( cycle > DEBUG_RPC_PMEM_GET_PAGES )
537printk("\n[DBG] %s : thread %x exit / cycle %d\n",
538__FUNCTION__ , CURRENT_THREAD , cycle );
539#endif
540}
541
542/////////////////////////////////////////////////////////////////////////////////////////
543// [1]       Marshaling functions attached to RPC_PMEM_RELEASE_PAGES (blocking)
544/////////////////////////////////////////////////////////////////////////////////////////
545
546//////////////////////////////////////////////////
547void rpc_pmem_release_pages_client( cxy_t     cxy,
548                                    page_t  * page )      // out
549{
550#if DEBUG_RPC_PMEM_RELEASE_PAGES
551uint32_t cycle = (uint32_t)hal_get_cycles();
552if( cycle > DEBUG_RPC_PMEM_RELEASE_PAGES )
553printk("\n[DBG] %s : thread %x enter on core[%x,%d] / cycle %d\n",
554__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
555#endif
556
557    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
558
559    // initialise RPC descriptor header
560    rpc_desc_t  rpc;
561    rpc.index    = RPC_PMEM_RELEASE_PAGES;
562    rpc.blocking = true;
563    rpc.responses = 1;
564
565    // set input arguments in RPC descriptor
566    rpc.args[0] = (uint64_t)(intptr_t)page;
567
568    // register RPC request in remote RPC fifo
569    rpc_send( cxy , &rpc );
570
571#if DEBUG_RPC_PMEM_RELEASE_PAGES
572cycle = (uint32_t)hal_get_cycles();
573if( cycle > DEBUG_RPC_PMEM_RELEASE_PAGES )
574printk("\n[DBG] %s : thread %x exit / cycle %d\n",
575__FUNCTION__ , CURRENT_THREAD , cycle );
576#endif
577}
578
579///////////////////////////////////////////////
580void rpc_pmem_release_pages_server( xptr_t xp )
581{
582#if DEBUG_RPC_PMEM_RELEASE_PAGES
583uint32_t cycle = (uint32_t)hal_get_cycles();
584if( cycle > DEBUG_RPC_PMEM_RELEASE_PAGES )
585printk("\n[DBG] %s : thread %x enter on core[%x,%d] / cycle %d\n",
586__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
587#endif
588
589    // get client cluster identifier and pointer on RPC descriptor
590    cxy_t        cxy  = GET_CXY( xp );
591    rpc_desc_t * desc = GET_PTR( xp );
592
593    // get input arguments from client RPC descriptor
594    page_t * page = (page_t *)(intptr_t)hal_remote_lwd( XPTR( cxy , &desc->args[0] ) );
595   
596    // release memory to local pmem
597    kmem_req_t req;
598    req.type = KMEM_PAGE;
599    req.ptr  = page;
600    kmem_free( &req );
601
602#if DEBUG_RPC_PMEM_RELEASE_PAGES
603cycle = (uint32_t)hal_get_cycles();
604if( cycle > DEBUG_RPC_PMEM_RELEASE_PAGES )
605printk("\n[DBG] %s : thread %x exit / cycle %d\n",
606__FUNCTION__ , CURRENT_THREAD , cycle );
607#endif
608}
609
610/////////////////////////////////////////////////////////////////////////////////////////
611// [2]      undefined slot
612/////////////////////////////////////////////////////////////////////////////////////////
613
614/////////////////////////////////////////////////////////////////////////////////////////
615// [3]           Marshaling functions attached to RPC_PROCESS_MAKE_FORK (blocking)
616/////////////////////////////////////////////////////////////////////////////////////////
617
618///////////////////////////////////////////////////
619void rpc_process_make_fork_client( cxy_t       cxy,
620                                   xptr_t      ref_process_xp,      // in
621                                   xptr_t      parent_thread_xp,    // in
622                                   pid_t     * child_pid,           // out
623                                   thread_t ** child_thread_ptr,    // out     
624                                   error_t   * error )              // out
625{
626#if DEBUG_RPC_PROCESS_MAKE_FORK
627uint32_t cycle = (uint32_t)hal_get_cycles();
628if( cycle > DEBUG_RPC_PROCESS_MAKE_FORK )
629printk("\n[DBG] %s : thread %x enter on core[%x,%d] / cycle %d\n",
630__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
631#endif
632
633    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
634
635    // initialise RPC descriptor header
636    rpc_desc_t  rpc;
637    rpc.index    = RPC_PROCESS_MAKE_FORK;
638    rpc.blocking = true;
639    rpc.responses = 1;
640
641    // set input arguments in RPC descriptor 
642    rpc.args[0] = (uint64_t)ref_process_xp;
643    rpc.args[1] = (uint64_t)parent_thread_xp;
644
645    // register RPC request in remote RPC fifo
646    rpc_send( cxy , &rpc );
647
648    // get output arguments from RPC descriptor
649    *child_pid         = (pid_t)rpc.args[2];
650    *child_thread_ptr  = (thread_t *)(intptr_t)rpc.args[3];
651    *error             = (error_t)rpc.args[4];     
652
653#if DEBUG_RPC_PROCESS_MAKE_FORK
654cycle = (uint32_t)hal_get_cycles();
655if( cycle > DEBUG_RPC_PROCESS_MAKE_FORK )
656printk("\n[DBG] %s : thread %x exit / cycle %d\n",
657__FUNCTION__ , CURRENT_THREAD , cycle );
658#endif
659}
660
661//////////////////////////////////////////////
662void rpc_process_make_fork_server( xptr_t xp )
663{
664#if DEBUG_RPC_PROCESS_MAKE_FORK
665uint32_t cycle = (uint32_t)hal_get_cycles();
666if( cycle > DEBUG_RPC_PROCESS_MAKE_FORK )
667printk("\n[DBG] %s : thread %x enter on core[%x,%d] / cycle %d\n",
668__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
669#endif
670
671    xptr_t     ref_process_xp;     // extended pointer on reference parent process
672    xptr_t     parent_thread_xp;   // extended pointer on parent thread
673    pid_t      child_pid;          // child process identifier
674    thread_t * child_thread_ptr;   // local copy of exec_info structure
675    error_t    error;              // local error status
676
677    // get client cluster identifier and pointer on RPC descriptor
678    cxy_t        client_cxy  = GET_CXY( xp );
679    rpc_desc_t * desc        = GET_PTR( xp );
680
681    // get input arguments from cient RPC descriptor
682    ref_process_xp   = (xptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
683    parent_thread_xp = (xptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
684
685    // call local kernel function
686    error = process_make_fork( ref_process_xp,
687                               parent_thread_xp,
688                               &child_pid,
689                               &child_thread_ptr ); 
690
691    // set output argument into client RPC descriptor
692    hal_remote_swd( XPTR( client_cxy , &desc->args[2] ) , (uint64_t)child_pid );
693    hal_remote_swd( XPTR( client_cxy , &desc->args[3] ) , (uint64_t)(intptr_t)child_thread_ptr );
694    hal_remote_swd( XPTR( client_cxy , &desc->args[4] ) , (uint64_t)error );
695
696#if DEBUG_RPC_PROCESS_MAKE_FORK
697cycle = (uint32_t)hal_get_cycles();
698if( cycle > DEBUG_RPC_PROCESS_MAKE_FORK )
699printk("\n[DBG] %s : thread %x exit / cycle %d\n",
700__FUNCTION__ , CURRENT_THREAD , cycle );
701#endif
702}
703
704/////////////////////////////////////////////////////////////////////////////////////////
705// [4]      undefined slot
706/////////////////////////////////////////////////////////////////////////////////////////
707
708/////////////////////////////////////////////////////////////////////////////////////////
709// [5]      undefined slot
710/////////////////////////////////////////////////////////////////////////////////////////
711
712/////////////////////////////////////////////////////////////////////////////////////////
713// [6]      Marshaling functions attached to RPC_THREAD_USER_CREATE (blocking) 
714/////////////////////////////////////////////////////////////////////////////////////////
715
716/////////////////////////////////////////////////////////
717void rpc_thread_user_create_client( cxy_t            cxy, 
718                                    pid_t            pid,         // in
719                                    void           * start_func,  // in
720                                    void           * start_arg,   // in
721                                    pthread_attr_t * attr,        // in
722                                    xptr_t         * thread_xp,   // out
723                                    error_t        * error )      // out
724{
725    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
726
727    // initialise RPC descriptor header
728    rpc_desc_t  rpc;
729    rpc.index    = RPC_THREAD_USER_CREATE;
730    rpc.blocking = true;
731    rpc.responses = 1;
732
733    // set input arguments in RPC descriptor
734    rpc.args[0] = (uint64_t)pid;
735    rpc.args[1] = (uint64_t)(intptr_t)start_func;
736    rpc.args[2] = (uint64_t)(intptr_t)start_arg;
737    rpc.args[3] = (uint64_t)(intptr_t)attr;
738
739    // register RPC request in remote RPC fifo
740    rpc_send( cxy , &rpc );
741
742    // get output arguments from RPC descriptor
743    *thread_xp = (xptr_t)rpc.args[4];
744    *error     = (error_t)rpc.args[5];
745
746}
747
748///////////////////////////////////////////////
749void rpc_thread_user_create_server( xptr_t xp )
750{
751
752    pthread_attr_t * attr_ptr;   // pointer on attributes structure in client cluster
753    pthread_attr_t   attr_copy;  // attributes structure  copy in server cluster
754    thread_t       * thread_ptr; // local pointer on thread descriptor
755    xptr_t           thread_xp;  // extended pointer on thread descriptor
756
757    pid_t            pid;        // process identifier
758    void           * start_func;
759    void           * start_arg;
760    error_t          error;
761
762    // get client cluster identifier and pointer on RPC descriptor
763    cxy_t        client_cxy  = GET_CXY( xp );
764    rpc_desc_t * desc        = GET_PTR( xp );
765
766    // get pointer on attributes structure in client cluster from RPC descriptor
767
768    // get input arguments from RPC descriptor
769    pid        = (pid_t)                     hal_remote_lwd(XPTR(client_cxy , &desc->args[0]));
770    start_func = (void *)(intptr_t)          hal_remote_lwd(XPTR(client_cxy , &desc->args[1]));
771    start_arg  = (void *)(intptr_t)          hal_remote_lwd(XPTR(client_cxy , &desc->args[2]));
772    attr_ptr   = (pthread_attr_t *)(intptr_t)hal_remote_lwd(XPTR(client_cxy , &desc->args[3]));
773
774    // makes a local copy of attributes structure
775    hal_remote_memcpy( XPTR( local_cxy , &attr_copy ),
776                       XPTR( client_cxy , attr_ptr ), 
777                       sizeof(pthread_attr_t) );
778   
779    // call kernel function
780    error = thread_user_create( pid,
781                                start_func,
782                                start_arg,
783                                &attr_copy,
784                                &thread_ptr );
785
786    // set output arguments
787    thread_xp = XPTR( local_cxy , thread_ptr );
788    hal_remote_swd( XPTR( client_cxy , &desc->args[4] ) , (uint64_t)thread_xp );
789    hal_remote_swd( XPTR( client_cxy , &desc->args[5] ) , (uint64_t)error );
790
791}
792
793/////////////////////////////////////////////////////////////////////////////////////////
794// [7]      Marshaling functions attached to RPC_THREAD_KERNEL_CREATE (blocking)
795/////////////////////////////////////////////////////////////////////////////////////////
796
797////////////////////////////////////////////////////
798void rpc_thread_kernel_create_client( cxy_t     cxy,
799                                      uint32_t  type,        // in
800                                      void    * func,        // in
801                                      void    * args,        // in
802                                      xptr_t  * thread_xp,   // out
803                                      error_t * error )      // out
804{
805    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
806
807    // initialise RPC descriptor header
808    rpc_desc_t  rpc;
809    rpc.index    = RPC_THREAD_KERNEL_CREATE;
810    rpc.blocking = true;
811    rpc.responses = 1;
812
813    // set input arguments in RPC descriptor
814    rpc.args[0] = (uint64_t)type;
815    rpc.args[1] = (uint64_t)(intptr_t)func;
816    rpc.args[2] = (uint64_t)(intptr_t)args;
817   
818    // register RPC request in remote RPC fifo
819    rpc_send( cxy , &rpc );
820
821    // get output arguments from RPC descriptor
822    *thread_xp = (xptr_t)rpc.args[3];
823    *error     = (error_t)rpc.args[4];
824
825}
826
827/////////////////////////////////////////////////
828void rpc_thread_kernel_create_server( xptr_t xp )
829{
830    thread_t       * thread_ptr;  // local pointer on thread descriptor
831    xptr_t           thread_xp;   // extended pointer on thread descriptor
832    lid_t            core_lid;    // core local index
833    error_t          error;   
834
835    // get client cluster identifier and pointer on RPC descriptor
836    cxy_t        client_cxy  = GET_CXY( xp );
837    rpc_desc_t * desc        = GET_PTR( xp );
838
839    // get attributes from RPC descriptor
840    uint32_t  type = (uint32_t)       hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
841    void    * func = (void*)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
842    void    * args = (void*)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) );
843
844    // select one core
845    core_lid = cluster_select_local_core();
846
847    // call local kernel function
848    error = thread_kernel_create( &thread_ptr , type , func , args , core_lid );
849
850    // set output arguments
851    thread_xp = XPTR( local_cxy , thread_ptr );
852    hal_remote_swd( XPTR( client_cxy , &desc->args[1] ) , (uint64_t)error );
853    hal_remote_swd( XPTR( client_cxy , &desc->args[2] ) , (uint64_t)thread_xp );
854
855}
856
857/////////////////////////////////////////////////////////////////////////////////////////
858// [8]   undefined slot
859/////////////////////////////////////////////////////////////////////////////////////////
860
861
862/////////////////////////////////////////////////////////////////////////////////////////
863// [9] Marshaling functions attached to RPC_PROCESS_SIGACTION (multicast / non blocking)
864/////////////////////////////////////////////////////////////////////////////////////////
865
866////////////////////////////////////////////////////
867void rpc_process_sigaction_client( cxy_t        cxy,
868                                   rpc_desc_t * rpc )
869{
870
871#if DEBUG_RPC_PROCESS_SIGACTION
872uint32_t  cycle  = (uint32_t)hal_get_cycles();
873uint32_t  action = rpc->args[0];
874pid_t     pid    = rpc->args[1];
875if( DEBUG_RPC_PROCESS_SIGACTION < cycle )
876printk("\n[DBG] %s : enter to request %s of process %x in cluster %x / cycle %d\n",
877__FUNCTION__ , process_action_str( action ) , pid , cxy , cycle );
878#endif
879
880    // check some RPC arguments
881    assert( (rpc->blocking == false) , __FUNCTION__ , "must be non-blocking\n");
882    assert( (rpc->index == RPC_PROCESS_SIGACTION ) , __FUNCTION__ , "bad RPC index\n" );
883
884    // register RPC request in remote RPC fifo and return
885    rpc_send( cxy , rpc );
886
887#if DEBUG_RPC_PROCESS_SIGACTION
888cycle = (uint32_t)hal_get_cycles();
889if( DEBUG_RPC_PROCESS_SIGACTION < cycle )
890printk("\n[DBG] %s : exit after requesting to %s process %x in cluster %x / cycle %d\n",
891__FUNCTION__ , process_action_str( action ) , pid , cxy , cycle );
892#endif
893
894}  // end rpc_process_sigaction_client()
895
896//////////////////////////////////////////////
897void rpc_process_sigaction_server( xptr_t xp )
898{
899    pid_t        pid;             // target process identifier
900    process_t  * process;         // pointer on local target process descriptor
901    uint32_t     action;          // sigaction index
902    thread_t   * client_ptr;      // pointer on client thread in client cluster
903    xptr_t       client_xp;       // extended pointer client thread
904    cxy_t        client_cxy;      // client cluster identifier
905    rpc_desc_t * rpc;             // pointer on rpc descriptor in client cluster
906    xptr_t       count_xp;        // extended pointer on responses counter
907    uint32_t     count_value;     // responses counter value
908    lid_t        client_lid;      // client core local index
909
910    // get client cluster identifier and pointer on RPC descriptor
911    client_cxy = GET_CXY( xp );
912    rpc        = GET_PTR( xp );
913
914    // get arguments from RPC descriptor
915    action   = (uint32_t)hal_remote_lwd( XPTR(client_cxy , &rpc->args[0]) );
916    pid      = (pid_t)   hal_remote_lwd( XPTR(client_cxy , &rpc->args[1]) );
917
918#if DEBUG_RPC_PROCESS_SIGACTION
919uint32_t cycle = (uint32_t)hal_get_cycles();
920if( DEBUG_RPC_PROCESS_SIGACTION < cycle )
921printk("\n[DBG] %s : enter to %s process %x in cluster %x / cycle %d\n",
922__FUNCTION__ , process_action_str( action ) , pid , local_cxy , cycle );
923#endif
924
925    // get client thread pointers
926    client_ptr = (thread_t *)hal_remote_lpt( XPTR( client_cxy , &rpc->thread ) );
927    client_xp  = XPTR( client_cxy , client_ptr );
928
929    // get local process descriptor
930    process = cluster_get_local_process_from_pid( pid );
931
932    // call relevant kernel function
933    if      ( action == DELETE_ALL_THREADS  ) process_delete_threads ( process , client_xp ); 
934    else if ( action == BLOCK_ALL_THREADS   ) process_block_threads  ( process , client_xp ); 
935    else if ( action == UNBLOCK_ALL_THREADS ) process_unblock_threads( process );
936
937    // build extended pointer on response counter in RPC
938    count_xp = XPTR( client_cxy , &rpc->responses );
939
940    // decrement the responses counter in RPC descriptor,
941    count_value = hal_remote_atomic_add( count_xp , -1 );
942
943    // unblock the client thread only if it is the last response.
944    if( count_value == 1 )
945    {
946        // get client core lid
947        client_lid    = (lid_t)     hal_remote_lw ( XPTR( client_cxy , &rpc->lid    ) );
948
949        // unblock client thread
950        thread_unblock( client_xp , THREAD_BLOCKED_RPC );
951
952        // send an IPI to client core
953        // dev_pic_send_ipi( client_cxy , client_lid );
954    }
955
956#if DEBUG_RPC_PROCESS_SIGACTION
957cycle = (uint32_t)hal_get_cycles();
958if( DEBUG_RPC_PROCESS_SIGACTION < cycle )
959printk("\n[DBG] %s : exit after %s process %x in cluster %x / cycle %d\n",
960__FUNCTION__ , process_action_str( action ) , pid , local_cxy , cycle );
961#endif
962
963} // end rpc_process_sigaction_server()
964
965/////////////////////////////////////////////////////////////////////////////////////////
966// [10]     Marshaling functions attached to RPC_VFS_INODE_CREATE  (blocking)
967/////////////////////////////////////////////////////////////////////////////////////////
968
969/////////////////////////////////////////////////////
970void rpc_vfs_inode_create_client( cxy_t          cxy,     
971                                  xptr_t         dentry_xp,  // in
972                                  uint32_t       fs_type,    // in
973                                  uint32_t       inode_type, // in
974                                  void         * extend,     // in
975                                  uint32_t       attr,       // in
976                                  uint32_t       rights,     // in
977                                  uint32_t       uid,        // in
978                                  uint32_t       gid,        // in
979                                  xptr_t       * inode_xp,   // out
980                                  error_t      * error )     // out
981{
982#if DEBUG_RPC_VFS_INODE_CREATE
983uint32_t cycle = (uint32_t)hal_get_cycles();
984if( cycle > DEBUG_RPC_VFS_INODE_CREATE )
985printk("\n[DBG] %s : thread %x enter on core[%x,%d] / cycle %d\n",
986__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
987#endif
988
989    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
990
991    // initialise RPC descriptor header
992    rpc_desc_t  rpc;
993    rpc.index    = RPC_VFS_INODE_CREATE;
994    rpc.blocking = true;
995    rpc.responses = 1;
996
997    // set input arguments in RPC descriptor
998    rpc.args[0] = (uint64_t)dentry_xp;
999    rpc.args[1] = (uint64_t)fs_type;
1000    rpc.args[2] = (uint64_t)inode_type;
1001    rpc.args[3] = (uint64_t)(intptr_t)extend;
1002    rpc.args[4] = (uint64_t)attr;
1003    rpc.args[5] = (uint64_t)rights;
1004    rpc.args[6] = (uint64_t)uid;
1005    rpc.args[7] = (uint64_t)gid;
1006
1007    // register RPC request in remote RPC fifo
1008    rpc_send( cxy , &rpc );
1009
1010    // get output values from RPC descriptor
1011    *inode_xp = (xptr_t)rpc.args[8];
1012    *error    = (error_t)rpc.args[9];
1013
1014#if DEBUG_RPC_VFS_INODE_CREATE
1015uint32_t cycle = (uint32_t)hal_get_cycles();
1016if( cycle > DEBUG_RPC_VFS_INODE_CREATE )
1017printk("\n[DBG] %s : thread %x exit on core[%x,%d] / cycle %d\n",
1018__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
1019#endif
1020}
1021
1022/////////////////////////////////////////////
1023void rpc_vfs_inode_create_server( xptr_t xp )
1024{
1025#if DEBUG_RPC_VFS_INODE_CREATE
1026uint32_t cycle = (uint32_t)hal_get_cycles();
1027if( cycle > DEBUG_RPC_VFS_INODE_CREATE )
1028printk("\n[DBG] %s : thread %x enter on core[%x,%d] / cycle %d\n",
1029__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
1030#endif
1031
1032    xptr_t           dentry_xp;
1033    uint32_t         fs_type;
1034    uint32_t         inode_type;
1035    void           * extend;
1036    uint32_t         attr;
1037    uint32_t         rights;
1038    uint32_t         uid;
1039    uint32_t         gid;
1040    xptr_t           inode_xp;
1041    error_t          error;
1042
1043    // get client cluster identifier and pointer on RPC descriptor
1044    cxy_t        client_cxy  = GET_CXY( xp );
1045    rpc_desc_t * desc        = GET_PTR( xp );
1046
1047    // get input arguments from client rpc descriptor
1048    dentry_xp  = (xptr_t)          hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
1049    fs_type    = (uint32_t)        hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
1050    inode_type = (uint32_t)        hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) );
1051    extend     = (void *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[3] ) );
1052    attr       = (uint32_t)        hal_remote_lwd( XPTR( client_cxy , &desc->args[4] ) );
1053    rights     = (uint32_t)        hal_remote_lwd( XPTR( client_cxy , &desc->args[5] ) );
1054    uid        = (uid_t)           hal_remote_lwd( XPTR( client_cxy , &desc->args[6] ) );
1055    gid        = (gid_t)           hal_remote_lwd( XPTR( client_cxy , &desc->args[7] ) );
1056
1057    // call local kernel function
1058    error = vfs_inode_create( dentry_xp,
1059                              fs_type,
1060                              inode_type,
1061                              extend,
1062                              attr,
1063                              rights,
1064                              uid,
1065                              gid,
1066                              &inode_xp );
1067
1068    // set output arguments
1069    hal_remote_swd( XPTR( client_cxy , &desc->args[8] ) , (uint64_t)inode_xp );
1070    hal_remote_swd( XPTR( client_cxy , &desc->args[9] ) , (uint64_t)error );
1071
1072#if DEBUG_RPC_VFS_INODE_CREATE
1073uint32_t cycle = (uint32_t)hal_get_cycles();
1074if( cycle > DEBUG_RPC_VFS_INODE_CREATE )
1075printk("\n[DBG] %s : thread %x exit on core[%x,%d] / cycle %d\n",
1076__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
1077#endif
1078}
1079
1080/////////////////////////////////////////////////////////////////////////////////////////
1081// [11]          Marshaling functions attached to RPC_VFS_INODE_DESTROY  (blocking)
1082/////////////////////////////////////////////////////////////////////////////////////////
1083
1084/////////////////////////////////////////////////////////////
1085void rpc_vfs_inode_destroy_client( cxy_t                cxy,
1086                                   struct vfs_inode_s * inode,
1087                                   error_t            * error )
1088{
1089#if DEBUG_RPC_VFS_INODE_DESTROY
1090uint32_t cycle = (uint32_t)hal_get_cycles();
1091if( cycle > DEBUG_RPC_VFS_INODE_DESTROY )
1092printk("\n[DBG] %s : thread %x enter on core[%x,%d] / cycle %d\n",
1093__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
1094#endif
1095
1096    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
1097
1098    // initialise RPC descriptor header
1099    rpc_desc_t  rpc;
1100    rpc.index    = RPC_VFS_INODE_DESTROY;
1101    rpc.blocking = true;
1102    rpc.responses = 1;
1103
1104    // set input arguments in RPC descriptor
1105    rpc.args[0] = (uint64_t)(intptr_t)inode;
1106   
1107    // register RPC request in remote RPC fifo
1108    rpc_send( cxy , &rpc );
1109
1110#if DEBUG_RPC_VFS_INODE_DESTROY
1111uint32_t cycle = (uint32_t)hal_get_cycles();
1112if( cycle > DEBUG_RPC_VFS_INODE_DESTROY )
1113printk("\n[DBG] %s : thread %x exit on core[%x,%d] / cycle %d\n",
1114__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
1115#endif
1116}
1117
1118//////////////////////////////////////////////
1119void rpc_vfs_inode_destroy_server( xptr_t xp )
1120{
1121#if DEBUG_RPC_VFS_INODE_DESTROY
1122uint32_t cycle = (uint32_t)hal_get_cycles();
1123if( cycle > DEBUG_RPC_VFS_INODE_DESTROY )
1124printk("\n[DBG] %s : thread %x enter on core[%x,%d] / cycle %d\n",
1125__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
1126#endif
1127
1128    vfs_inode_t * inode;
1129    error_t       error;
1130
1131    // get client cluster identifier and pointer on RPC descriptor
1132    cxy_t        client_cxy  = GET_CXY( xp );
1133    rpc_desc_t * desc        = GET_PTR( xp );
1134
1135    // get arguments "inode" from client RPC descriptor
1136    inode = (vfs_inode_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
1137                       
1138    // call local kernel function
1139    error = vfs_inode_destroy( inode );
1140
1141    // set output argument
1142    hal_remote_swd( XPTR( client_cxy , &desc->args[1] ) , (uint64_t)error );
1143
1144#if DEBUG_RPC_VFS_INODE_DESTROY
1145uint32_t cycle = (uint32_t)hal_get_cycles();
1146if( cycle > DEBUG_RPC_VFS_INODE_DESTROY )
1147printk("\n[DBG] %s : thread %x exit on core[%x,%d] / cycle %d\n",
1148__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
1149#endif
1150}
1151
1152/////////////////////////////////////////////////////////////////////////////////////////
1153// [12]          Marshaling functions attached to RPC_VFS_DENTRY_CREATE  (blocking)
1154/////////////////////////////////////////////////////////////////////////////////////////
1155
1156//////////////////////////////////////////////////////////////
1157void rpc_vfs_dentry_create_client( cxy_t                  cxy,
1158                                   uint32_t               type,         // in
1159                                   char                 * name,         // in
1160                                   struct vfs_inode_s   * parent,       // in
1161                                   xptr_t               * dentry_xp,    // out
1162                                   error_t              * error )       // out
1163{
1164#if DEBUG_RPC_VFS_DENTRY_CREATE
1165uint32_t cycle = (uint32_t)hal_get_cycles();
1166if( cycle > DEBUG_RPC_VFS_DENTRY_CREATE )
1167printk("\n[DBG] %s : thread %x enter on core[%x,%d] / cycle %d\n",
1168__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
1169#endif
1170
1171    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
1172
1173    // initialise RPC descriptor header
1174    rpc_desc_t  rpc;
1175    rpc.index    = RPC_VFS_DENTRY_CREATE;
1176    rpc.blocking = true;
1177    rpc.responses = 1;
1178
1179    // set input arguments in RPC descriptor
1180    rpc.args[0] = (uint64_t)type;
1181    rpc.args[1] = (uint64_t)(intptr_t)name;
1182    rpc.args[2] = (uint64_t)(intptr_t)parent;
1183
1184    // register RPC request in remote RPC fifo
1185    rpc_send( cxy , &rpc );
1186
1187    // get output values from RPC descriptor
1188    *dentry_xp = (xptr_t)rpc.args[3];
1189    *error     = (error_t)rpc.args[4];
1190
1191#if DEBUG_RPC_VFS_DENTRY_CREATE
1192cycle = (uint32_t)hal_get_cycles();
1193if( cycle > DEBUG_RPC_VFS_DENTRY_CREATE )
1194printk("\n[DBG] %s : thread %x exit / cycle %d\n",
1195__FUNCTION__ , CURRENT_THREAD , cycle );
1196#endif
1197}
1198
1199//////////////////////////////////////////////
1200void rpc_vfs_dentry_create_server( xptr_t xp )
1201{
1202#if DEBUG_RPC_VFS_DENTRY_CREATE
1203uint32_t cycle = (uint32_t)hal_get_cycles();
1204if( cycle > DEBUG_RPC_VFS_DENTRY_CREATE )
1205printk("\n[DBG] %s : thread %x enter on core[%x,%d] / cycle %d\n",
1206__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
1207#endif
1208
1209    uint32_t      type;
1210    char        * name;
1211    vfs_inode_t * parent;
1212    xptr_t        dentry_xp;
1213    error_t       error;
1214    char          name_copy[CONFIG_VFS_MAX_NAME_LENGTH];
1215
1216    // get client cluster identifier and pointer on RPC descriptor
1217    cxy_t        client_cxy  = GET_CXY( xp );
1218    rpc_desc_t * desc        = GET_PTR( xp );
1219
1220    // get arguments "name", "type", and "parent" from client RPC descriptor
1221    type   = (uint32_t)               hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
1222    name   = (char *)(intptr_t)       hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
1223    parent = (vfs_inode_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) );
1224
1225    // makes a local copy of  name
1226    hal_remote_strcpy( XPTR( local_cxy , name_copy ),
1227                       XPTR( client_cxy , name ) );
1228
1229    // call local kernel function
1230    error = vfs_dentry_create( type,
1231                               name_copy,
1232                               parent,
1233                               &dentry_xp );
1234    // set output arguments
1235    hal_remote_swd( XPTR( client_cxy , &desc->args[3] ) , (uint64_t)dentry_xp );
1236    hal_remote_swd( XPTR( client_cxy , &desc->args[4] ) , (uint64_t)error );
1237
1238#if DEBUG_RPC_VFS_DENTRY_CREATE
1239cycle = (uint32_t)hal_get_cycles();
1240if( cycle > DEBUG_RPC_VFS_DENTRY_CREATE )
1241printk("\n[DBG] %s : thread %x exit / cycle %d\n",
1242__FUNCTION__ , CURRENT_THREAD , cycle );
1243#endif
1244}
1245
1246/////////////////////////////////////////////////////////////////////////////////////////
1247// [13]          Marshaling functions attached to RPC_VFS_DENTRY_DESTROY  (blocking)
1248/////////////////////////////////////////////////////////////////////////////////////////
1249
1250
1251///////////////////////////////////////////////////////
1252void rpc_vfs_dentry_destroy_client( cxy_t          cxy,
1253                                    vfs_dentry_t * dentry,
1254                                    error_t      * error )
1255{
1256#if DEBUG_RPC_VFS_DENTRY_DESTROY
1257uint32_t cycle = (uint32_t)hal_get_cycles();
1258if( cycle > DEBUG_RPC_VFS_DENTRY_DESTROY )
1259printk("\n[DBG] %s : thread %x enter on core[%x,%d] / cycle %d\n",
1260__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
1261#endif
1262
1263    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
1264
1265    // initialise RPC descriptor header
1266    rpc_desc_t  rpc;
1267    rpc.index    = RPC_VFS_DENTRY_DESTROY;
1268    rpc.blocking = true;
1269    rpc.responses = 1;
1270
1271    // set input arguments in RPC descriptor
1272    rpc.args[0] = (uint64_t)(intptr_t)dentry;
1273   
1274    // register RPC request in remote RPC fifo
1275    rpc_send( cxy , &rpc );
1276
1277#if DEBUG_RPC_VFS_DENTRY_DESTROY
1278cycle = (uint32_t)hal_get_cycles();
1279if( cycle > DEBUG_RPC_VFS_DENTRY_DESTROY )
1280printk("\n[DBG] %s : thread %x exit / cycle %d\n",
1281__FUNCTION__ , CURRENT_THREAD , cycle );
1282#endif
1283}
1284
1285///////////////////////////////////////////////
1286void rpc_vfs_dentry_destroy_server( xptr_t xp )
1287{
1288#if DEBUG_RPC_VFS_DENTRY_DESTROY
1289uint32_t cycle = (uint32_t)hal_get_cycles();
1290if( cycle > DEBUG_RPC_VFS_DENTRY_DESTROY )
1291printk("\n[DBG] %s : thread %x enter on core[%x,%d] / cycle %d\n",
1292__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
1293#endif
1294
1295    vfs_dentry_t * dentry;
1296    error_t        error;
1297
1298    // get client cluster identifier and pointer on RPC descriptor
1299    cxy_t        client_cxy  = GET_CXY( xp );
1300    rpc_desc_t * desc        = GET_PTR( xp );
1301
1302    // get arguments "dentry" from client RPC descriptor
1303    dentry = (vfs_dentry_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
1304                       
1305    // call local kernel function
1306    error = vfs_dentry_destroy( dentry );
1307
1308    // set output argument
1309    hal_remote_swd( XPTR( client_cxy , &desc->args[1] ) , (uint64_t)error );
1310
1311#if DEBUG_RPC_VFS_DENTRY_DESTROY
1312cycle = (uint32_t)hal_get_cycles();
1313if( cycle > DEBUG_RPC_VFS_DENTRY_DESTROY )
1314printk("\n[DBG] %s : thread %x exit / cycle %d\n",
1315__FUNCTION__ , CURRENT_THREAD , cycle );
1316#endif
1317}
1318
1319
1320/////////////////////////////////////////////////////////////////////////////////////////
1321// [14]          Marshaling functions attached to RPC_VFS_FILE_CREATE  (blocking)
1322/////////////////////////////////////////////////////////////////////////////////////////
1323
1324//////////////////////////////////////////////////////////////
1325void rpc_vfs_file_create_client( cxy_t                  cxy,
1326                                 struct vfs_inode_s   * inode,       // in
1327                                 uint32_t               file_attr,   // in
1328                                 xptr_t               * file_xp,     // out
1329                                 error_t              * error )      // out
1330{
1331#if DEBUG_RPC_VFS_FILE_CREATE
1332uint32_t cycle = (uint32_t)hal_get_cycles();
1333if( cycle > DEBUG_RPC_VFS_FILE_CREATE )
1334printk("\n[DBG] %s : thread %x enter on core[%x,%d] / cycle %d\n",
1335__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
1336#endif
1337
1338    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
1339
1340    // initialise RPC descriptor header
1341    rpc_desc_t  rpc;
1342    rpc.index    = RPC_VFS_FILE_CREATE;
1343    rpc.blocking = true;
1344    rpc.responses = 1;
1345
1346    // set input arguments in RPC descriptor
1347    rpc.args[0] = (uint64_t)(intptr_t)inode;
1348    rpc.args[1] = (uint64_t)file_attr;
1349
1350    // register RPC request in remote RPC fifo
1351    rpc_send( cxy , &rpc );
1352
1353    // get output values from RPC descriptor
1354    *file_xp = (xptr_t)rpc.args[2];
1355    *error   = (error_t)rpc.args[3];
1356
1357#if DEBUG_RPC_VFS_FILE_CREATE
1358cycle = (uint32_t)hal_get_cycles();
1359if( cycle > DEBUG_RPC_VFS_FILE_CREATE )
1360printk("\n[DBG] %s : thread %x exit / cycle %d\n",
1361__FUNCTION__ , CURRENT_THREAD , cycle );
1362#endif
1363}
1364
1365////////////////////////////////////////////
1366void rpc_vfs_file_create_server( xptr_t xp )
1367{
1368#if DEBUG_RPC_VFS_FILE_CREATE
1369uint32_t cycle = (uint32_t)hal_get_cycles();
1370if( cycle > DEBUG_RPC_VFS_FILE_CREATE )
1371printk("\n[DBG] %s : thread %x enter on core[%x,%d] / cycle %d\n",
1372__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
1373#endif
1374
1375    uint32_t      file_attr;
1376    vfs_inode_t * inode;
1377    xptr_t        file_xp;
1378    error_t       error;
1379
1380    // get client cluster identifier and pointer on RPC descriptor
1381    cxy_t        client_cxy  = GET_CXY( xp );
1382    rpc_desc_t * desc        = GET_PTR( xp );
1383
1384    // get arguments "file_attr" and "inode" from client RPC descriptor
1385    inode     = (vfs_inode_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
1386    file_attr = (uint32_t)               hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
1387                       
1388    // call local kernel function
1389    error = vfs_file_create( inode,
1390                             file_attr,
1391                             &file_xp );
1392 
1393    // set output arguments
1394    hal_remote_swd( XPTR( client_cxy , &desc->args[2] ) , (uint64_t)file_xp );
1395    hal_remote_swd( XPTR( client_cxy , &desc->args[3] ) , (uint64_t)error );
1396
1397#if DEBUG_RPC_VFS_FILE_CREATE
1398cycle = (uint32_t)hal_get_cycles();
1399if( cycle > DEBUG_RPC_VFS_FILE_CREATE )
1400printk("\n[DBG] %s : thread %x exit / cycle %d\n",
1401__FUNCTION__ , CURRENT_THREAD , cycle );
1402#endif
1403}
1404
1405/////////////////////////////////////////////////////////////////////////////////////////
1406// [15]          Marshaling functions attached to RPC_VFS_FILE_DESTROY  (blocking)
1407/////////////////////////////////////////////////////////////////////////////////////////
1408
1409///////////////////////////////////////////////////
1410void rpc_vfs_file_destroy_client( cxy_t        cxy,
1411                                  vfs_file_t * file )
1412{
1413#if DEBUG_RPC_VFS_FILE_DESTROY
1414uint32_t cycle = (uint32_t)hal_get_cycles();
1415if( cycle > DEBUG_RPC_VFS_FILE_DESTROY )
1416printk("\n[DBG] %s : thread %x enter on core[%x,%d] / cycle %d\n",
1417__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
1418#endif
1419
1420    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
1421
1422    // initialise RPC descriptor header
1423    rpc_desc_t  rpc;
1424    rpc.index    = RPC_VFS_FILE_DESTROY;
1425    rpc.blocking = true;
1426    rpc.responses = 1;
1427
1428    // set input arguments in RPC descriptor
1429    rpc.args[0] = (uint64_t)(intptr_t)file;
1430   
1431    // register RPC request in remote RPC fifo
1432    rpc_send( cxy , &rpc );
1433
1434#if DEBUG_RPC_VFS_FILE_DESTROY
1435cycle = (uint32_t)hal_get_cycles();
1436if( cycle > DEBUG_RPC_VFS_FILE_DESTROY )
1437printk("\n[DBG] %s : thread %x exit / cycle %d\n",
1438__FUNCTION__ , CURRENT_THREAD , cycle );
1439#endif
1440}
1441
1442/////////////////////////////////////////////
1443void rpc_vfs_file_destroy_server( xptr_t xp )
1444{
1445#if DEBUG_RPC_VFS_FILE_DESTROY
1446uint32_t cycle = (uint32_t)hal_get_cycles();
1447if( cycle > DEBUG_RPC_VFS_FILE_DESTROY )
1448printk("\n[DBG] %s : thread %x enter on core[%x,%d] / cycle %d\n",
1449__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
1450#endif
1451
1452    vfs_file_t * file;
1453
1454    // get client cluster identifier and pointer on RPC descriptor
1455    cxy_t        client_cxy  = GET_CXY( xp );
1456    rpc_desc_t * desc        = GET_PTR( xp );
1457
1458    // get arguments "dentry" from client RPC descriptor
1459    file = (vfs_file_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
1460                       
1461    // call local kernel function
1462    vfs_file_destroy( file );
1463
1464#if DEBUG_RPC_VFS_FILE_DESTROY
1465cycle = (uint32_t)hal_get_cycles();
1466if( cycle > DEBUG_RPC_VFS_FILE_DESTROY )
1467printk("\n[DBG] %s : thread %x exit / cycle %d\n",
1468__FUNCTION__ , CURRENT_THREAD , cycle );
1469#endif
1470}
1471
1472/////////////////////////////////////////////////////////////////////////////////////////
1473// [16]          Marshaling functions attached to RPC_VFS_INODE_LOAD   (blocking)
1474/////////////////////////////////////////////////////////////////////////////////////////
1475
1476//////////////////////////////////////////////////
1477void rpc_vfs_inode_load_client( cxy_t         cxy,
1478                                vfs_inode_t * parent_inode,    // in
1479                                char        * name,            // in
1480                                xptr_t        child_inode_xp,  // in
1481                                error_t     * error )          // out
1482{
1483    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
1484
1485    // initialise RPC descriptor header
1486    rpc_desc_t  rpc;
1487    rpc.index    = RPC_VFS_INODE_LOAD;
1488    rpc.blocking = true;
1489    rpc.responses = 1;
1490
1491    // set input arguments in RPC descriptor
1492    rpc.args[0] = (uint64_t)(intptr_t)parent_inode;
1493    rpc.args[1] = (uint64_t)(intptr_t)name;
1494    rpc.args[2] = (uint64_t)child_inode_xp;
1495
1496    // register RPC request in remote RPC fifo
1497    rpc_send( cxy , &rpc );
1498
1499    // get output values from RPC descriptor
1500    *error   = (error_t)rpc.args[3];
1501
1502}
1503
1504///////////////////////////////////////////
1505void rpc_vfs_inode_load_server( xptr_t xp )
1506{
1507    error_t       error;
1508    vfs_inode_t * parent;
1509    xptr_t        child_xp;
1510    char        * name;
1511
1512    char          name_copy[CONFIG_VFS_MAX_NAME_LENGTH];
1513
1514    // get client cluster identifier and pointer on RPC descriptor
1515    cxy_t        client_cxy  = GET_CXY( xp );
1516    rpc_desc_t * desc        = GET_PTR( xp );
1517
1518    // get arguments "parent", "name", and "child_xp"
1519    parent     = (vfs_inode_t*)(intptr_t)hal_remote_lwd(XPTR(client_cxy , &desc->args[0]));
1520    name       = (char*)(intptr_t)       hal_remote_lwd(XPTR(client_cxy , &desc->args[1]));
1521    child_xp   = (xptr_t)                hal_remote_lwd(XPTR(client_cxy , &desc->args[2]));
1522
1523    // get name local copy
1524    hal_remote_strcpy( XPTR( local_cxy , name_copy ) ,
1525                       XPTR( client_cxy , name ) );
1526
1527    // call the kernel function
1528    error = vfs_inode_load( parent , name_copy , child_xp );
1529
1530    // set output argument
1531    hal_remote_swd( XPTR( client_cxy , &desc->args[3] ) , (uint64_t)error );
1532
1533}
1534
1535/////////////////////////////////////////////////////////////////////////////////////////
1536// [17]          Marshaling functions attached to RPC_VFS_MAPPER_LOAD_ALL  (blocking)
1537/////////////////////////////////////////////////////////////////////////////////////////
1538
1539///////////////////////////////////////////////////////
1540void rpc_vfs_mapper_load_all_client( cxy_t         cxy,
1541                                     vfs_inode_t * inode,      // in
1542                                     error_t     * error )     // out
1543{
1544    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
1545
1546    // initialise RPC descriptor header
1547    rpc_desc_t  rpc;
1548    rpc.index    = RPC_VFS_MAPPER_LOAD_ALL;
1549    rpc.blocking = true;
1550    rpc.responses = 1;
1551
1552    // set input arguments in RPC descriptor
1553    rpc.args[0] = (uint64_t)(intptr_t)inode;
1554
1555    // register RPC request in remote RPC fifo
1556    rpc_send( cxy , &rpc );
1557
1558    // get output values from RPC descriptor
1559    *error   = (error_t)rpc.args[1];
1560
1561}
1562
1563////////////////////////////////////////////////
1564void rpc_vfs_mapper_load_all_server( xptr_t xp )
1565{
1566    error_t       error;
1567    vfs_inode_t * inode;
1568
1569    // get client cluster identifier and pointer on RPC descriptor
1570    cxy_t        client_cxy  = GET_CXY( xp );
1571    rpc_desc_t * desc        = GET_PTR( xp );
1572
1573    // get arguments "parent", "name", and "child_xp"
1574    inode = (vfs_inode_t*)(intptr_t)hal_remote_lwd(XPTR(client_cxy , &desc->args[0]));
1575
1576    // call the kernel function
1577    error = vfs_mapper_load_all( inode );
1578
1579    // set output argument
1580    hal_remote_swd( XPTR( client_cxy , &desc->args[1] ) , (uint64_t)error );
1581
1582}
1583
1584/////////////////////////////////////////////////////////////////////////////////////////
1585// [18]          Marshaling functions attached to RPC_FATFS_GET_CLUSTER  (blocking)
1586/////////////////////////////////////////////////////////////////////////////////////////
1587
1588//////////////////////////////////////////////////
1589void rpc_fatfs_get_cluster_client( cxy_t      cxy,
1590                                   mapper_t * mapper,    // in
1591                                   uint32_t   first,     // in
1592                                   uint32_t   index,     // in
1593                                   uint32_t * cluster,   // out
1594                                   error_t  * error )    // out
1595{
1596    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
1597
1598    // initialise RPC descriptor header
1599    rpc_desc_t  rpc;
1600    rpc.index    = RPC_FATFS_GET_CLUSTER;
1601    rpc.blocking = true;
1602    rpc.responses = 1;
1603
1604    // set input arguments in RPC descriptor
1605    rpc.args[0] = (uint64_t)(intptr_t)mapper;
1606    rpc.args[1] = (uint64_t)first;
1607    rpc.args[2] = (uint64_t)index;
1608
1609    // register RPC request in remote RPC fifo
1610    rpc_send( cxy , &rpc );
1611
1612    // get output argument from rpc descriptor
1613    *cluster = (uint32_t)rpc.args[3];
1614    *error   = (error_t)rpc.args[4];
1615
1616}
1617
1618//////////////////////////////////////////////
1619void rpc_fatfs_get_cluster_server( xptr_t xp )
1620{
1621    mapper_t    * mapper;
1622    uint32_t      first;
1623    uint32_t      index;
1624    uint32_t      cluster;
1625    error_t       error;
1626
1627    // get client cluster identifier and pointer on RPC descriptor
1628    cxy_t        client_cxy  = GET_CXY( xp );
1629    rpc_desc_t * desc        = GET_PTR( xp );
1630
1631    // get input arguments
1632    mapper = (mapper_t *)(intptr_t)hal_remote_lpt( XPTR( client_cxy , &desc->args[0] ) );
1633    first  = (uint32_t)            hal_remote_lw ( XPTR( client_cxy , &desc->args[1] ) );
1634    index  = (uint32_t)            hal_remote_lw ( XPTR( client_cxy , &desc->args[2] ) );
1635
1636    // call the kernel function
1637    error = fatfs_get_cluster( mapper , first , index , &cluster );
1638
1639    // set output argument
1640    hal_remote_swd( XPTR( client_cxy , &desc->args[3] ) , (uint64_t)cluster );
1641    hal_remote_swd( XPTR( client_cxy , &desc->args[4] ) , (uint64_t)error );
1642
1643}
1644
1645/////////////////////////////////////////////////////////////////////////////////////////
1646// [20]          Marshaling functions attached to RPC_VMM_GET_VSEG  (blocking)
1647/////////////////////////////////////////////////////////////////////////////////////////
1648
1649//////////////////////////////////////////////////
1650void rpc_vmm_get_vseg_client( cxy_t       cxy,     
1651                              process_t * process,     // in 
1652                              intptr_t    vaddr,       // in 
1653                              xptr_t    * vseg_xp,     // out
1654                              error_t   * error )      // out
1655{
1656#if DEBUG_RPC_VMM_GET_VSEG
1657uint32_t cycle = (uint32_t)hal_get_cycles();
1658if( cycle > DEBUG_RPC_VMM_GET_VSEG )
1659printk("\n[DBG] %s : thread %x enter on core[%x,%d] / cycle %d\n",
1660__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
1661#endif
1662
1663    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
1664
1665    // initialise RPC descriptor header
1666    rpc_desc_t  rpc;
1667    rpc.index    = RPC_VMM_GET_VSEG;
1668    rpc.blocking = true;
1669    rpc.responses = 1;
1670
1671    // set input arguments in RPC descriptor
1672    rpc.args[0] = (uint64_t)(intptr_t)process;
1673    rpc.args[1] = (uint64_t)vaddr;
1674
1675    // register RPC request in remote RPC fifo
1676    rpc_send( cxy , &rpc );
1677
1678    // get output argument from rpc descriptor
1679    *vseg_xp = rpc.args[2];
1680    *error   = (error_t)rpc.args[3];
1681
1682#if DEBUG_RPC_VMM_GET_VSEG
1683cycle = (uint32_t)hal_get_cycles();
1684if( cycle > DEBUG_RPC_VMM_GET_VSEG )
1685printk("\n[DBG] %s : thread %x exit on core[%x,%d] / cycle %d\n",
1686__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
1687#endif
1688}
1689
1690/////////////////////////////////////////
1691void rpc_vmm_get_vseg_server( xptr_t xp )
1692{
1693#if DEBUG_RPC_VMM_GET_VSEG
1694uint32_t cycle = (uint32_t)hal_get_cycles();
1695if( cycle > DEBUG_RPC_VMM_GET_VSEG )
1696printk("\n[DBG] %s : thread %x enter on core[%x,%d] / cycle %d\n",
1697__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
1698#endif
1699
1700    process_t   * process;
1701    intptr_t      vaddr;
1702    vseg_t      * vseg_ptr;
1703    xptr_t        vseg_xp;
1704    error_t       error;
1705
1706    // get client cluster identifier and pointer on RPC descriptor
1707    cxy_t        client_cxy  = GET_CXY( xp );
1708    rpc_desc_t * desc        = GET_PTR( xp );
1709
1710    // get input argument from client RPC descriptor
1711    process = (process_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
1712    vaddr   = (intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
1713   
1714    // call local kernel function
1715    error = vmm_get_vseg( process , vaddr , &vseg_ptr );
1716
1717    // set output arguments to client RPC descriptor
1718    vseg_xp = XPTR( local_cxy , vseg_ptr );
1719    hal_remote_swd( XPTR( client_cxy , &desc->args[2] ) , (uint64_t)vseg_xp );
1720    hal_remote_swd( XPTR( client_cxy , &desc->args[3] ) , (uint64_t)error );
1721
1722#if DEBUG_RPC_VMM_GET_VSEG
1723cycle = (uint32_t)hal_get_cycles();
1724if( cycle > DEBUG_RPC_VMM_GET_VSEG )
1725printk("\n[DBG] %s : thread %x exit on core[%x,%d] / cycle %d\n",
1726__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
1727#endif
1728}
1729
1730
1731/////////////////////////////////////////////////////////////////////////////////////////
1732// [21]          Marshaling functions attached to RPC_VMM_GET_PTE  (blocking)
1733/////////////////////////////////////////////////////////////////////////////////////////
1734
1735////////////////////////////////////////////
1736void rpc_vmm_get_pte_client( cxy_t       cxy,   
1737                             process_t * process,  // in
1738                             vpn_t       vpn,      // in
1739                             bool_t      cow,      // in
1740                             uint32_t  * attr,     // out
1741                             ppn_t     * ppn,      // out
1742                             error_t   * error )   // out
1743{
1744#if DEBUG_RPC_VMM_GET_PTE
1745uint32_t cycle = (uint32_t)hal_get_cycles();
1746if( cycle > DEBUG_RPC_VMM_GET_PTE )
1747printk("\n[DBG] %s : thread %x enter on core[%x,%d] / cycle %d\n",
1748__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
1749#endif
1750
1751    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
1752
1753    // initialise RPC descriptor header
1754    rpc_desc_t  rpc;
1755    rpc.index    = RPC_VMM_GET_PTE;
1756    rpc.blocking = true;
1757    rpc.responses = 1;
1758
1759    // set input arguments in RPC descriptor
1760    rpc.args[0] = (uint64_t)(intptr_t)process;
1761    rpc.args[1] = (uint64_t)vpn;
1762    rpc.args[2] = (uint64_t)cow;
1763
1764    // register RPC request in remote RPC fifo
1765    rpc_send( cxy , &rpc );
1766
1767    // get output argument from rpc descriptor
1768    *attr  = (uint32_t)rpc.args[3];
1769    *ppn   = (ppn_t)rpc.args[4];
1770    *error = (error_t)rpc.args[5];
1771
1772#if DEBUG_RPC_VMM_GET_PTE
1773cycle = (uint32_t)hal_get_cycles();
1774if( cycle > DEBUG_RPC_VMM_GET_PTE )
1775printk("\n[DBG] %s : thread %x exit on core[%x,%d] / cycle %d\n",
1776__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
1777#endif
1778}
1779
1780////////////////////////////////////////
1781void rpc_vmm_get_pte_server( xptr_t xp )
1782{
1783#if DEBUG_RPC_VMM_GET_PTE
1784uint32_t cycle = (uint32_t)hal_get_cycles();
1785if( cycle > DEBUG_RPC_VMM_GET_PTE )
1786printk("\n[DBG] %s : thread %x enter on core[%x,%d] / cycle %d\n",
1787__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
1788#endif
1789
1790    process_t   * process;
1791    vpn_t         vpn;
1792    bool_t        cow;
1793    uint32_t      attr;
1794    ppn_t         ppn;
1795    error_t       error;
1796
1797    // get client cluster identifier and pointer on RPC descriptor
1798    cxy_t        client_cxy  = GET_CXY( xp );
1799    rpc_desc_t * desc        = GET_PTR( xp );
1800
1801    // get input argument "process" & "vpn" from client RPC descriptor
1802    process = (process_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
1803    vpn     = (vpn_t)                hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
1804    cow     = (bool_t)               hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) );
1805   
1806    // call local kernel function
1807    error = vmm_get_pte( process , vpn , cow , &attr , &ppn ); 
1808
1809    // set output argument "attr" & "ppn" to client RPC descriptor
1810    hal_remote_swd( XPTR( client_cxy , &desc->args[3] ) , (uint64_t)attr );
1811    hal_remote_swd( XPTR( client_cxy , &desc->args[4] ) , (uint64_t)ppn );
1812    hal_remote_swd( XPTR( client_cxy , &desc->args[5] ) , (uint64_t)error );
1813
1814#if DEBUG_RPC_VMM_GET_PTE
1815cycle = (uint32_t)hal_get_cycles();
1816if( cycle > DEBUG_RPC_VMM_GET_PTE )
1817printk("\n[DBG] %s : thread %x exit on core[%x,%d] / cycle %d\n",
1818__FUNCTION__ , CURRENT_THREAD , local_cxy, CURRENT_THREAD->core->lid , cycle );
1819#endif
1820}
1821
1822/////////////////////////////////////////////////////////////////////////////////////////
1823// [22]          Marshaling functions attached to RPC_KCM_ALLOC  (blocking)
1824/////////////////////////////////////////////////////////////////////////////////////////
1825
1826//////////////////////////////////////////
1827void rpc_kcm_alloc_client( cxy_t      cxy,
1828                           uint32_t   kmem_type,   // in
1829                           xptr_t *   buf_xp )     // out
1830{
1831    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
1832
1833    // initialise RPC descriptor header
1834    rpc_desc_t  rpc;
1835    rpc.index    = RPC_KCM_ALLOC;
1836    rpc.blocking = true;
1837    rpc.responses = 1;
1838
1839    // set input arguments in RPC descriptor
1840    rpc.args[0] = (uint64_t)kmem_type;
1841
1842    // register RPC request in remote RPC fifo
1843    rpc_send( cxy , &rpc );
1844
1845    // get output arguments from RPC descriptor
1846    *buf_xp = (xptr_t)rpc.args[1];
1847
1848}
1849
1850//////////////////////////////////////
1851void rpc_kcm_alloc_server( xptr_t xp )
1852{
1853    // get client cluster identifier and pointer on RPC descriptor
1854    cxy_t        client_cxy  = GET_CXY( xp );
1855    rpc_desc_t * desc        = GET_PTR( xp );
1856
1857    // get input argument "kmem_type" from client RPC descriptor
1858    uint32_t kmem_type = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
1859
1860    // allocates memory for kcm
1861    kmem_req_t  req;
1862    req.type  = kmem_type;
1863    req.flags = AF_ZERO;
1864    void * buf_ptr = kmem_alloc( &req );
1865
1866    // set output argument
1867    xptr_t buf_xp = XPTR( local_cxy , buf_ptr );
1868    hal_remote_swd( XPTR( client_cxy , &desc->args[1] ) , (uint64_t)buf_xp );
1869
1870}   
1871
1872/////////////////////////////////////////////////////////////////////////////////////////
1873// [23]          Marshaling functions attached to RPC_KCM_FREE  (blocking)
1874/////////////////////////////////////////////////////////////////////////////////////////
1875
1876/////////////////////////////////////////
1877void rpc_kcm_free_client( cxy_t      cxy,
1878                          void     * buf,          // in
1879                          uint32_t   kmem_type )   // in
1880{
1881    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
1882
1883    // initialise RPC descriptor header
1884    rpc_desc_t  rpc;
1885    rpc.index    = RPC_KCM_FREE;
1886    rpc.blocking = true;
1887    rpc.responses = 1;
1888
1889    // set input arguments in RPC descriptor
1890    rpc.args[0] = (uint64_t)(intptr_t)buf;
1891    rpc.args[1] = (uint64_t)kmem_type;
1892
1893    // register RPC request in remote RPC fifo
1894    rpc_send( cxy , &rpc );
1895
1896}
1897
1898/////////////////////////////////////
1899void rpc_kcm_free_server( xptr_t xp )
1900{
1901    // get client cluster identifier and pointer on RPC descriptor
1902    cxy_t        client_cxy  = GET_CXY( xp );
1903    rpc_desc_t * desc        = GET_PTR( xp );
1904
1905    // get input arguments "buf" and "kmem_type" from client RPC descriptor
1906    void     * buf = (void *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
1907    uint32_t   kmem_type = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
1908
1909    // releases memory
1910    kmem_req_t  req;
1911    req.type = kmem_type;
1912    req.ptr  = buf;
1913    kmem_free( &req );
1914
1915}   
1916
1917/////////////////////////////////////////////////////////////////////////////////////////
1918// [24]          Marshaling functions attached to RPC_MAPPER_MOVE_BUFFER
1919/////////////////////////////////////////////////////////////////////////////////////////
1920
1921///////////////////////////////////////////////////
1922void rpc_mapper_move_buffer_client( cxy_t      cxy,
1923                                    mapper_t * mapper,        // in
1924                                    bool_t     to_buffer,     // in
1925                                    bool_t     is_user,       // in
1926                                    uint32_t   file_offset,   // in
1927                                    uint64_t   buffer,        // in
1928                                    uint32_t   size,          // in
1929                                    error_t  * error )        // out
1930{
1931    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
1932
1933    // initialise RPC descriptor header
1934    rpc_desc_t  rpc;
1935    rpc.index    = RPC_MAPPER_MOVE_BUFFER;
1936    rpc.blocking = true;
1937    rpc.responses = 1;
1938
1939    // set input arguments in RPC descriptor
1940    rpc.args[0] = (uint64_t)(intptr_t)mapper;
1941    rpc.args[1] = (uint64_t)to_buffer;
1942    rpc.args[2] = (uint64_t)is_user;
1943    rpc.args[3] = (uint64_t)file_offset;
1944    rpc.args[4] = (uint64_t)buffer;
1945    rpc.args[5] = (uint64_t)size;
1946
1947    // register RPC request in remote RPC fifo
1948    rpc_send( cxy , &rpc );
1949
1950    // get output values from RPC descriptor
1951    *error     = (error_t)rpc.args[6];
1952
1953}
1954
1955///////////////////////////////////////////////
1956void rpc_mapper_move_buffer_server( xptr_t xp )
1957{
1958    mapper_t * mapper;
1959    bool_t     to_buffer;
1960    bool_t     is_user;
1961    uint32_t   file_offset;
1962    void     * user_buffer;
1963    xptr_t     kern_buffer;
1964    uint32_t   size;
1965    error_t    error;
1966
1967    // get client cluster identifier and pointer on RPC descriptor
1968    cxy_t        client_cxy  = GET_CXY( xp );
1969    rpc_desc_t * desc        = GET_PTR( xp );
1970
1971    // get arguments from client RPC descriptor
1972    mapper      = (mapper_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
1973    to_buffer   =                       hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
1974    is_user     =                       hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) );
1975    file_offset =                       hal_remote_lwd( XPTR( client_cxy , &desc->args[3] ) );
1976    size        =                       hal_remote_lwd( XPTR( client_cxy , &desc->args[5] ) );
1977
1978    // call local kernel function
1979    if( is_user )
1980    {
1981        user_buffer = (void *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[4] ) );
1982
1983        error = mapper_move_user( mapper,
1984                                  to_buffer,
1985                                  file_offset,
1986                                  user_buffer,
1987                                  size );
1988    }
1989    else
1990    {
1991        kern_buffer = (xptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[4] ) );
1992
1993        error = mapper_move_kernel( mapper,
1994                                    to_buffer,
1995                                    file_offset,
1996                                    kern_buffer,
1997                                    size );
1998    }
1999
2000    // set output argument to client RPC descriptor
2001    hal_remote_swd( XPTR( client_cxy , &desc->args[6] ) , (uint64_t)error );
2002
2003}
2004
2005/////////////////////////////////////////////////////////////////////////////////////////
2006// [25]          Marshaling functions attached to RPC_MAPPER_GET_PAGE (blocking)
2007/////////////////////////////////////////////////////////////////////////////////////////
2008
2009///////////////////////////////////////////////////////
2010void rpc_mapper_get_page_client( cxy_t             cxy,
2011                                 struct mapper_s * mapper,     // in
2012                                 uint32_t          index,      // in
2013                                 page_t         ** page )      // out
2014{
2015    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
2016
2017    // initialise RPC descriptor header
2018    rpc_desc_t  rpc;
2019    rpc.index    = RPC_MAPPER_GET_PAGE;
2020    rpc.blocking = true;
2021    rpc.responses = 1;
2022
2023    // set input arguments in RPC descriptor
2024    rpc.args[0] = (uint64_t)(intptr_t)mapper;
2025    rpc.args[1] = (uint64_t)index;
2026
2027    // register RPC request in remote RPC fifo
2028    rpc_send( cxy , &rpc );
2029
2030    // get output values from RPC descriptor
2031    *page = (page_t *)(intptr_t)rpc.args[2];
2032
2033}
2034
2035////////////////////////////////////////////
2036void rpc_mapper_get_page_server( xptr_t xp )
2037{
2038    // get client cluster identifier and pointer on RPC descriptor
2039    cxy_t        cxy  = GET_CXY( xp );
2040    rpc_desc_t * desc = GET_PTR( xp );
2041
2042    // get input arguments from client RPC descriptor
2043    mapper_t * mapper = (mapper_t *)(intptr_t)hal_remote_lwd( XPTR( cxy , &desc->args[0] ) );
2044    uint32_t   index  = (uint32_t)            hal_remote_lwd( XPTR( cxy , &desc->args[1] ) );
2045   
2046    // call local pmem allocator
2047    page_t * page = mapper_get_page( mapper , index ); 
2048
2049    // set output arguments into client RPC descriptor
2050    hal_remote_swd( XPTR( cxy , &desc->args[1] ) , (uint64_t)(intptr_t)page );
2051
2052}
2053
2054/////////////////////////////////////////////////////////////////////////////////////////
2055// [26]          Marshaling functions attached to RPC_VMM_CREATE_VSEG (blocking)
2056/////////////////////////////////////////////////////////////////////////////////////////
2057
2058////////////////////////////////////////////////////////
2059void rpc_vmm_create_vseg_client( cxy_t              cxy,
2060                                 struct process_s * process,
2061                                 vseg_type_t        type,
2062                                 intptr_t           base,
2063                                 uint32_t           size,
2064                                 uint32_t           file_offset,
2065                                 uint32_t           file_size,
2066                                 xptr_t             mapper_xp,
2067                                 cxy_t              vseg_cxy,
2068                                 struct vseg_s   ** vseg )
2069{
2070    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
2071
2072    // initialise RPC descriptor header
2073    rpc_desc_t  rpc;
2074    rpc.index    = RPC_VMM_CREATE_VSEG;
2075    rpc.blocking = true;
2076    rpc.responses = 1;
2077
2078    // set input arguments in RPC descriptor
2079    rpc.args[0] = (uint64_t)(intptr_t)process;
2080    rpc.args[1] = (uint64_t)type;
2081    rpc.args[2] = (uint64_t)base;
2082    rpc.args[3] = (uint64_t)size;
2083    rpc.args[4] = (uint64_t)file_offset;
2084    rpc.args[5] = (uint64_t)file_size;
2085    rpc.args[6] = (uint64_t)mapper_xp;
2086    rpc.args[7] = (uint64_t)vseg_cxy;
2087
2088    // register RPC request in remote RPC fifo
2089    rpc_send( cxy , &rpc );
2090
2091    // get output values from RPC descriptor
2092    *vseg = (vseg_t *)(intptr_t)rpc.args[8];
2093
2094}
2095
2096////////////////////////////////////////////
2097void rpc_vmm_create_vseg_server( xptr_t xp )
2098{
2099    // get client cluster identifier and pointer on RPC descriptor
2100    cxy_t        cxy  = GET_CXY( xp );
2101    rpc_desc_t * desc = GET_PTR( xp );
2102
2103    // get input arguments from client RPC descriptor
2104    process_t * process     = (process_t *)(intptr_t)hal_remote_lwd( XPTR(cxy , &desc->args[0]));
2105    vseg_type_t type        = (vseg_type_t)(uint32_t)hal_remote_lwd( XPTR(cxy , &desc->args[1]));
2106    intptr_t    base        = (intptr_t)             hal_remote_lwd( XPTR(cxy , &desc->args[2]));
2107    uint32_t    size        = (uint32_t)             hal_remote_lwd( XPTR(cxy , &desc->args[3]));
2108    uint32_t    file_offset = (uint32_t)             hal_remote_lwd( XPTR(cxy , &desc->args[4]));
2109    uint32_t    file_size   = (uint32_t)             hal_remote_lwd( XPTR(cxy , &desc->args[5]));
2110    xptr_t      mapper_xp   = (xptr_t)               hal_remote_lwd( XPTR(cxy , &desc->args[6]));
2111    cxy_t       vseg_cxy    = (cxy_t)(uint32_t)      hal_remote_lwd( XPTR(cxy , &desc->args[7]));
2112   
2113    // call local kernel function
2114    vseg_t * vseg = vmm_create_vseg( process,
2115                                     type,
2116                                     base,
2117                                     size,
2118                                     file_offset,
2119                                     file_size,
2120                                     mapper_xp,
2121                                     vseg_cxy ); 
2122
2123    // set output arguments into client RPC descriptor
2124    hal_remote_swd( XPTR( cxy , &desc->args[8] ) , (uint64_t)(intptr_t)vseg );
2125
2126}
2127
2128/////////////////////////////////////////////////////////////////////////////////////////
2129// [27]         undefined slot
2130/////////////////////////////////////////////////////////////////////////////////////////
2131
2132/////////////////////////////////////////////////////////////////////////////////////////
2133// [28]          Marshaling functions attached to RPC_VMM_SET_COW (blocking)
2134/////////////////////////////////////////////////////////////////////////////////////////
2135
2136/////////////////////////////////////////////
2137void rpc_vmm_set_cow_client( cxy_t       cxy,
2138                             process_t * process )
2139{
2140    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
2141
2142    // initialise RPC descriptor header
2143    rpc_desc_t  rpc;
2144    rpc.index    = RPC_VMM_SET_COW;
2145    rpc.blocking = true;
2146    rpc.responses = 1;
2147
2148    // set input arguments in RPC descriptor
2149    rpc.args[0] = (uint64_t)(intptr_t)process;
2150
2151    // register RPC request in remote RPC fifo
2152    rpc_send( cxy , &rpc );
2153
2154}
2155
2156////////////////////////////////////////
2157void rpc_vmm_set_cow_server( xptr_t xp )
2158{
2159    process_t * process;
2160
2161    // get client cluster identifier and pointer on RPC descriptor
2162    cxy_t        cxy  = GET_CXY( xp );
2163    rpc_desc_t * desc = GET_PTR( xp );
2164
2165    // get input arguments from client RPC descriptor
2166    process = (process_t *)(intptr_t)hal_remote_lwd( XPTR(cxy , &desc->args[0]));
2167   
2168    // call local kernel function
2169    vmm_set_cow( process );
2170
2171}
2172
2173/////////////////////////////////////////////////////////////////////////////////////////
2174// [29]          Marshaling functions attached to RPC_VMM_DISPLAY (blocking)
2175/////////////////////////////////////////////////////////////////////////////////////////
2176
2177/////////////////////////////////////////////
2178void rpc_vmm_display_client( cxy_t       cxy,
2179                             process_t * process,
2180                             bool_t      detailed )
2181{
2182    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
2183
2184    // initialise RPC descriptor header
2185    rpc_desc_t  rpc;
2186    rpc.index    = RPC_VMM_DISPLAY;
2187    rpc.blocking = true;
2188    rpc.responses = 1;
2189
2190    // set input arguments in RPC descriptor
2191    rpc.args[0] = (uint64_t)(intptr_t)process;
2192    rpc.args[1] = (uint64_t)detailed;
2193
2194    // register RPC request in remote RPC fifo
2195    rpc_send( cxy , &rpc );
2196
2197}
2198
2199////////////////////////////////////////
2200void rpc_vmm_display_server( xptr_t xp )
2201{
2202    process_t * process;
2203    bool_t      detailed;
2204
2205    // get client cluster identifier and pointer on RPC descriptor
2206    cxy_t        cxy  = GET_CXY( xp );
2207    rpc_desc_t * desc = GET_PTR( xp );
2208
2209    // get input arguments from client RPC descriptor
2210    process  = (process_t *)(intptr_t)hal_remote_lwd( XPTR(cxy , &desc->args[0]));
2211    detailed = (bool_t)               hal_remote_lwd( XPTR(cxy , &desc->args[1]));
2212   
2213    // call local kernel function
2214    vmm_display( process , detailed );
2215
2216}
2217
2218
Note: See TracBrowser for help on using the repository browser.