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

Last change on this file since 438 was 438, checked in by alain, 4 years ago

Fix a bug in scheduler related to RPC blocking.

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