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

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

1/ Fix a bug in the Multithreaded "sort" applicationr:
The pthread_create() arguments must be declared as global variables.
2/ The exit syscall can be called by any thread of a process..

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