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

Last change on this file since 396 was 389, checked in by alain, 7 years ago

Update the RPC_VMM_GET_VSEG.

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