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

Last change on this file since 374 was 374, checked in by max@…, 5 years ago

Use panic().

File size: 76.0 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_ref_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_INODE_LOAD;
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[3] ) , (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_REF_VSEG
1232/////////////////////////////////////////////////////////////////////////////////////////
1233
1234//////////////////////////////////////////////////
1235void rpc_vmm_get_ref_vseg_client( cxy_t       cxy,     
1236                                  process_t * process,     // in 
1237                                  intptr_t    vaddr,       // in 
1238                                  xptr_t    * vseg_xp )    // out
1239{
1240    rpc_dmsg("\n[INFO] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
1241    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
1242    CURRENT_THREAD->core->lid , hal_time_stamp() );
1243
1244    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
1245
1246    // initialise RPC descriptor header
1247    rpc_desc_t  rpc;
1248    rpc.index    = RPC_VMM_GET_REF_VSEG;
1249    rpc.response = 1;
1250
1251    // set input arguments in RPC descriptor
1252    rpc.args[0] = (uint64_t)(intptr_t)process;
1253    rpc.args[1] = (uint64_t)vaddr;
1254
1255    // register RPC request in remote RPC fifo (blocking function)
1256    rpc_send_sync( cxy , &rpc );
1257
1258    // get output argument from rpc descriptor
1259    *vseg_xp = rpc.args[2];
1260
1261    rpc_dmsg("\n[INFO] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
1262    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
1263    CURRENT_THREAD->core->lid , hal_time_stamp() );
1264}
1265
1266/////////////////////////////////////////////
1267void rpc_vmm_get_ref_vseg_server( xptr_t xp )
1268{
1269    process_t   * process;
1270    intptr_t      vaddr;
1271    vseg_t      * vseg_ptr;
1272    xptr_t        vseg_xp;
1273
1274    rpc_dmsg("\n[INFO] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
1275    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
1276    CURRENT_THREAD->core->lid , hal_time_stamp() );
1277
1278    // get client cluster identifier and pointer on RPC descriptor
1279    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
1280    rpc_desc_t * desc        = (rpc_desc_t *)GET_PTR( xp );
1281
1282    // get input argument from client RPC descriptor
1283    process = (process_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
1284    vaddr   = (intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
1285   
1286    // call local kernel function
1287    vseg_ptr = vmm_get_vseg( process , vaddr );
1288
1289    // set output argument to client RPC descriptor
1290    if( vseg_ptr == NULL ) vseg_xp = XPTR_NULL;
1291    else                   vseg_xp = XPTR( local_cxy , vseg_ptr );
1292    hal_remote_swd( XPTR( client_cxy , &desc->args[2] ) , (uint64_t)vseg_xp );
1293
1294    rpc_dmsg("\n[INFO] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
1295    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
1296    CURRENT_THREAD->core->lid , hal_time_stamp() );
1297}
1298
1299
1300/////////////////////////////////////////////////////////////////////////////////////////
1301// [21]          Marshaling functions attached to RPC_VMM_GET_PTE
1302/////////////////////////////////////////////////////////////////////////////////////////
1303
1304////////////////////////////////////////////
1305void rpc_vmm_get_pte_client( cxy_t       cxy,   
1306                             process_t * process,  // in
1307                             vpn_t       vpn,      // in
1308                             uint32_t  * attr,     // out
1309                             ppn_t     * ppn,      // out
1310                             error_t   * error )   // out
1311{
1312    rpc_dmsg("\n[INFO] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
1313    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
1314    CURRENT_THREAD->core->lid , hal_time_stamp() );
1315
1316    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
1317
1318    // initialise RPC descriptor header
1319    rpc_desc_t  rpc;
1320    rpc.index    = RPC_VMM_GET_PTE;
1321    rpc.response = 1;
1322
1323    // set input arguments in RPC descriptor
1324    rpc.args[0] = (uint64_t)(intptr_t)process;
1325    rpc.args[1] = (uint64_t)vpn;
1326
1327    // register RPC request in remote RPC fifo (blocking function)
1328    rpc_send_sync( cxy , &rpc );
1329
1330    // get output argument from rpc descriptor
1331    *attr  = (uint32_t)rpc.args[2];
1332    *ppn   = (ppn_t)rpc.args[3];
1333    *error = (error_t)rpc.args[4];
1334
1335    rpc_dmsg("\n[INFO] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
1336    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
1337    CURRENT_THREAD->core->lid , hal_time_stamp() );
1338}
1339
1340////////////////////////////////////////
1341void rpc_vmm_get_pte_server( xptr_t xp )
1342{
1343    process_t   * process;
1344    vpn_t         vpn;
1345    uint32_t      attr;
1346    ppn_t         ppn;
1347    error_t       error;
1348
1349    rpc_dmsg("\n[INFO] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
1350    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
1351    CURRENT_THREAD->core->lid , hal_time_stamp() );
1352
1353    // get client cluster identifier and pointer on RPC descriptor
1354    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
1355    rpc_desc_t * desc        = (rpc_desc_t *)GET_PTR( xp );
1356
1357    // get input argument "process" & "vpn" from client RPC descriptor
1358    process = (process_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
1359    vpn     = (vpn_t)                hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
1360   
1361    // call local kernel function
1362    error = vmm_get_pte( process , vpn , &attr , &ppn ); 
1363
1364    // set output argument "attr" & "ppn" to client RPC descriptor
1365    hal_remote_swd( XPTR( client_cxy , &desc->args[2] ) , (uint64_t)attr );
1366    hal_remote_swd( XPTR( client_cxy , &desc->args[3] ) , (uint64_t)ppn );
1367    hal_remote_swd( XPTR( client_cxy , &desc->args[4] ) , (uint64_t)error );
1368
1369    rpc_dmsg("\n[INFO] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
1370    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
1371    CURRENT_THREAD->core->lid , hal_time_stamp() );
1372}
1373
1374/////////////////////////////////////////////////////////////////////////////////////////
1375// [22]          Marshaling functions attached to RPC_KCM_ALLOC
1376/////////////////////////////////////////////////////////////////////////////////////////
1377
1378//////////////////////////////////////////
1379void rpc_kcm_alloc_client( cxy_t      cxy,
1380                           uint32_t   kmem_type,   // in
1381                           xptr_t *   buf_xp )     // out
1382{
1383    rpc_dmsg("\n[INFO] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
1384    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
1385    CURRENT_THREAD->core->lid , hal_time_stamp() );
1386
1387    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
1388
1389    // initialise RPC descriptor header
1390    rpc_desc_t  rpc;
1391    rpc.index    = RPC_THREAD_USER_CREATE;
1392    rpc.response = 1;
1393
1394    // set input arguments in RPC descriptor
1395    rpc.args[0] = (uint64_t)kmem_type;
1396
1397    // register RPC request in remote RPC fifo
1398    rpc_send_sync( cxy , &rpc );
1399
1400    // get output arguments from RPC descriptor
1401    *buf_xp = (xptr_t)rpc.args[1];
1402
1403    rpc_dmsg("\n[INFO] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
1404    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
1405    CURRENT_THREAD->core->lid , hal_time_stamp() );
1406}
1407
1408//////////////////////////////////////
1409void rpc_kcm_alloc_server( xptr_t xp )
1410{
1411    rpc_dmsg("\n[INFO] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
1412    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
1413    CURRENT_THREAD->core->lid , hal_time_stamp() );
1414
1415    // get client cluster identifier and pointer on RPC descriptor
1416    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
1417    rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp );
1418
1419    // get input argument "kmem_type" from client RPC descriptor
1420    uint32_t kmem_type = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
1421
1422    // allocates memory for kcm
1423    kmem_req_t  req;
1424    req.type  = kmem_type;
1425    req.flags = AF_ZERO;
1426    void * buf_ptr = kmem_alloc( &req );
1427
1428    // set output argument
1429    xptr_t buf_xp = XPTR( local_cxy , buf_ptr );
1430    hal_remote_swd( XPTR( client_cxy , &desc->args[1] ) , (uint64_t)buf_xp );
1431
1432    rpc_dmsg("\n[INFO] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
1433    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
1434    CURRENT_THREAD->core->lid , hal_time_stamp() );
1435}   
1436
1437/////////////////////////////////////////////////////////////////////////////////////////
1438// [23]          Marshaling functions attached to RPC_KCM_FREE
1439/////////////////////////////////////////////////////////////////////////////////////////
1440
1441/////////////////////////////////////////
1442void rpc_kcm_free_client( cxy_t      cxy,
1443                          void     * buf,          // in
1444                          uint32_t   kmem_type )   // in
1445{
1446    rpc_dmsg("\n[INFO] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
1447    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
1448    CURRENT_THREAD->core->lid , hal_time_stamp() );
1449
1450    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
1451
1452    // initialise RPC descriptor header
1453    rpc_desc_t  rpc;
1454    rpc.index    = RPC_THREAD_USER_CREATE;
1455    rpc.response = 1;
1456
1457    // set input arguments in RPC descriptor
1458    rpc.args[0] = (uint64_t)(intptr_t)buf;
1459    rpc.args[1] = (uint64_t)kmem_type;
1460
1461    // register RPC request in remote RPC fifo
1462    rpc_send_sync( cxy , &rpc );
1463
1464    rpc_dmsg("\n[INFO] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
1465    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
1466    CURRENT_THREAD->core->lid , hal_time_stamp() );
1467}
1468
1469/////////////////////////////////////
1470void rpc_kcm_free_server( xptr_t xp )
1471{
1472    rpc_dmsg("\n[INFO] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
1473    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
1474    CURRENT_THREAD->core->lid , hal_time_stamp() );
1475
1476    // get client cluster identifier and pointer on RPC descriptor
1477    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
1478    rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp );
1479
1480    // get input arguments "buf" and "kmem_type" from client RPC descriptor
1481    void     * buf = (void *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
1482    uint32_t   kmem_type = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
1483
1484    // releases memory
1485    kmem_req_t  req;
1486    req.type = kmem_type;
1487    req.ptr  = buf;
1488    kmem_free( &req );
1489
1490    rpc_dmsg("\n[INFO] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
1491    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
1492    CURRENT_THREAD->core->lid , hal_time_stamp() );
1493}   
1494
1495/////////////////////////////////////////////////////////////////////////////////////////
1496// [24]          Marshaling functions attached to RPC_MAPPER_MOVE_BUFFER
1497/////////////////////////////////////////////////////////////////////////////////////////
1498
1499///////////////////////////////////////////////////
1500void rpc_mapper_move_buffer_client( cxy_t      cxy,
1501                                    mapper_t * mapper,        // in
1502                                    bool_t     to_buffer,     // in
1503                                    bool_t     is_user,       // in
1504                                    uint32_t   file_offset,   // in
1505                                    uint64_t   buffer,        // in
1506                                    uint32_t   size,          // in
1507                                    error_t  * error )        // out
1508{
1509    rpc_dmsg("\n[INFO] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
1510    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
1511    CURRENT_THREAD->core->lid , hal_time_stamp() );
1512
1513    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
1514
1515    // initialise RPC descriptor header
1516    rpc_desc_t  rpc;
1517    rpc.index    = RPC_MAPPER_MOVE_BUFFER;
1518    rpc.response = 1;
1519
1520    // set input arguments in RPC descriptor
1521    rpc.args[0] = (uint64_t)(intptr_t)mapper;
1522    rpc.args[1] = (uint64_t)to_buffer;
1523    rpc.args[2] = (uint64_t)is_user;
1524    rpc.args[3] = (uint64_t)file_offset;
1525    rpc.args[4] = (uint64_t)buffer;
1526    rpc.args[5] = (uint64_t)size;
1527
1528    // register RPC request in remote RPC fifo (blocking function)
1529    rpc_send_sync( cxy , &rpc );
1530
1531    // get output values from RPC descriptor
1532    *error     = (error_t)rpc.args[6];
1533
1534    rpc_dmsg("\n[INFO] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
1535    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
1536    CURRENT_THREAD->core->lid , hal_time_stamp() );
1537}
1538
1539///////////////////////////////////////////////
1540void rpc_mapper_move_buffer_server( xptr_t xp )
1541{
1542    mapper_t * mapper;
1543    bool_t     to_buffer;
1544    bool_t     is_user;
1545    uint32_t   file_offset;
1546    void     * user_buffer;
1547    xptr_t     kern_buffer;
1548    uint32_t   size;
1549    error_t    error;
1550
1551    rpc_dmsg("\n[INFO] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
1552    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
1553    CURRENT_THREAD->core->lid , hal_time_stamp() );
1554
1555    // get client cluster identifier and pointer on RPC descriptor
1556    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
1557    rpc_desc_t * desc        = (rpc_desc_t *)GET_PTR( xp );
1558
1559    // get arguments from client RPC descriptor
1560    mapper      = (mapper_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
1561    to_buffer   =                       hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
1562    is_user     =                       hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) );
1563    file_offset =                       hal_remote_lwd( XPTR( client_cxy , &desc->args[3] ) );
1564    size        =                       hal_remote_lwd( XPTR( client_cxy , &desc->args[5] ) );
1565
1566    // call local kernel function
1567    if( is_user )
1568    {
1569        user_buffer = (void *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[4] ) );
1570
1571        error = mapper_move_user( mapper,
1572                                  to_buffer,
1573                                  file_offset,
1574                                  user_buffer,
1575                                  size );
1576    }
1577    else
1578    {
1579        kern_buffer = (xptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[4] ) );
1580
1581        error = mapper_move_kernel( mapper,
1582                                    to_buffer,
1583                                    file_offset,
1584                                    kern_buffer,
1585                                    size );
1586    }
1587
1588    // set output argument to client RPC descriptor
1589    hal_remote_swd( XPTR( client_cxy , &desc->args[6] ) , (uint64_t)error );
1590
1591    rpc_dmsg("\n[INFO] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
1592    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
1593    CURRENT_THREAD->core->lid , hal_time_stamp() );
1594}
1595
1596/////////////////////////////////////////////////////////////////////////////////////////
1597// [25]          Marshaling functions attached to RPC_MAPPER_GET_PAGE
1598/////////////////////////////////////////////////////////////////////////////////////////
1599
1600///////////////////////////////////////////////////////
1601void rpc_mapper_get_page_client( cxy_t             cxy,
1602                                 struct mapper_s * mapper,     // in
1603                                 uint32_t          index,      // in
1604                                 page_t         ** page )      // out
1605{
1606    rpc_dmsg("\n[INFO] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
1607    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
1608    CURRENT_THREAD->core->lid , hal_time_stamp() );
1609
1610    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
1611
1612    // initialise RPC descriptor header
1613    rpc_desc_t  rpc;
1614    rpc.index    = RPC_MAPPER_GET_PAGE;
1615    rpc.response = 1;
1616
1617    // set input arguments in RPC descriptor
1618    rpc.args[0] = (uint64_t)(intptr_t)mapper;
1619    rpc.args[1] = (uint64_t)index;
1620
1621    // register RPC request in remote RPC fifo (blocking function)
1622    rpc_send_sync( cxy , &rpc );
1623
1624    // get output values from RPC descriptor
1625    *page = (page_t *)(intptr_t)rpc.args[2];
1626
1627    rpc_dmsg("\n[INFO] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
1628    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
1629    CURRENT_THREAD->core->lid , hal_time_stamp() );
1630}
1631
1632////////////////////////////////////////////
1633void rpc_mapper_get_page_server( xptr_t xp )
1634{
1635    rpc_dmsg("\n[INFO] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
1636    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
1637    CURRENT_THREAD->core->lid , hal_time_stamp() );
1638
1639    // get client cluster identifier and pointer on RPC descriptor
1640    cxy_t        cxy  = (cxy_t)GET_CXY( xp );
1641    rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp );
1642
1643    // get input arguments from client RPC descriptor
1644    mapper_t * mapper = (mapper_t *)(intptr_t)hal_remote_lwd( XPTR( cxy , &desc->args[0] ) );
1645    uint32_t   index  = (uint32_t)            hal_remote_lwd( XPTR( cxy , &desc->args[1] ) );
1646   
1647    // call local pmem allocator
1648    page_t * page = mapper_get_page( mapper , index ); 
1649
1650    // set output arguments into client RPC descriptor
1651    hal_remote_swd( XPTR( cxy , &desc->args[1] ) , (uint64_t)(intptr_t)page );
1652
1653    rpc_dmsg("\n[INFO] %s : exit / thread %x on core[%x,%d] / cycle %d\n",
1654    __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, 
1655    CURRENT_THREAD->core->lid , hal_time_stamp() );
1656}
1657
1658
1659/***************************************************************************************/
1660/************ Generic functions supporting RPCs : client side **************************/
1661/***************************************************************************************/
1662
1663////////////////////////////////////////////
1664void rpc_send_sync( cxy_t        server_cxy, 
1665                    rpc_desc_t * rpc )
1666{
1667    uint32_t   cores;
1668    error_t    error;
1669    bool_t     first;
1670    reg_t      sr_save;
1671
1672    rpcg_dmsg("\n[INFO] %s : enter / client_cxy = %x / server_cxy = %x / cycle %d\n",
1673    __FUNCTION__ , local_cxy , server_cxy , hal_time_stamp() );
1674
1675    // allocate and initialise an extended pointer on the RPC descriptor
1676        xptr_t   desc_xp = XPTR( local_cxy , rpc );
1677
1678    // get local pointer on rpc_fifo in remote cluster, with the
1679    // assumption that rpc_fifo pddresses are identical in all clusters
1680    rpc_fifo_t * rf = &LOCAL_CLUSTER->rpc_fifo;
1681
1682        // try to post an item in remote fifo
1683    // deschedule and retry if remote fifo full
1684    do
1685    { 
1686        error = remote_fifo_put_item( XPTR( server_cxy , &rf->fifo ),
1687                                      (uint64_t )desc_xp,
1688                                      &first );
1689            if ( error ) 
1690        {
1691            printk("\n[WARNING] %s : cluster %x cannot post RPC to cluster %x\n",
1692            __FUNCTION__ , local_cxy , server_cxy );
1693
1694            if( thread_can_yield() ) sched_yield( NULL );
1695        }
1696    }
1697    while( error );
1698 
1699    rpcg_dmsg("\n[INFO] %s : RPC %l registered / server_cxy = %x / cycle %d\n",
1700    __FUNCTION__ , desc_xp , server_cxy , hal_time_stamp() );
1701       
1702    // send IPI to remote CP0, if this is the first RPC in remote FIFO,
1703    // and there is no CPU is in kernel mode in server cluster.
1704        if( first )
1705        {
1706        // get number of cores in kernel mode in server cluster
1707        cores = hal_remote_lw( XPTR( server_cxy , &LOCAL_CLUSTER->cores_in_kernel ) );
1708
1709                if( cores == 0 ) // no core in kernel mode in server
1710                {
1711                    dev_pic_send_ipi( server_cxy , 0 );
1712
1713                    rpcg_dmsg("\n[INFO] %s : IPI sent / client_cxy = %x / server_cxy = %x\n",
1714            __FUNCTION__, local_cxy , server_cxy );
1715        }
1716        }
1717
1718        // enable IRQs to allow incoming RPC and avoid deadlock
1719        hal_enable_irq( &sr_save );
1720
1721    // the server thread poll the response slot until RPC completed
1722    // TODO this could be replaced by a descheduling policy... [AG]
1723    while( rpc->response ) asm volatile( "nop" );
1724
1725    // restore IRQs
1726        hal_restore_irq( sr_save );
1727
1728    rpcg_dmsg("\n[INFO] %s : completed / client_cxy = %x / server_cxy = %x / cycle %d\n",
1729    __FUNCTION__ , local_cxy , server_cxy , hal_time_stamp() );
1730
1731}  // end rpc_send_sync()
1732
1733
1734
1735/***************************************************************************************/
1736/************ Generic functions supporting RPCs : server side **************************/
1737/***************************************************************************************/
1738
1739///////////////////////////////////////////
1740void rpc_fifo_init( rpc_fifo_t * rpc_fifo )
1741{
1742        rpc_fifo->count       = 0;
1743        rpc_fifo->owner       = 0;
1744        local_fifo_init( &rpc_fifo->fifo );
1745}
1746
1747/////////////////////////////////////////////
1748void rpc_execute_all( rpc_fifo_t * rpc_fifo )
1749{
1750        xptr_t         xp;             // extended pointer on RPC descriptor
1751        uint32_t       count;          // handled RPC request counter
1752        thread_t     * this;           // pointer on this RPC thread
1753    core_t       * core;           // pointer on core running this thread
1754    rpc_desc_t   * desc;           // pointer on RPC descriptor
1755    uint32_t       index;          // RPC index
1756    cxy_t          client_cxy;     // client cluster identifier
1757        error_t        error;
1758     
1759        this  = CURRENT_THREAD; 
1760    core  = this->core;   
1761        count = 0;
1762
1763    rpcg_dmsg("\n[INFO] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
1764    __FUNCTION__, this->trdid, local_cxy, core->lid , hal_time_stamp() );
1765 
1766    // handle up to CONFIG_RPC_PENDING_MAX requests before exit
1767        do
1768    {
1769            error = local_fifo_get_item( &rpc_fifo->fifo, (uint64_t *)&xp );
1770
1771                if ( error == 0 )  // One RPC request successfully extracted from RPC_FIFO
1772        {
1773            // get client cluster identifier and pointer on RPC descriptor
1774            client_cxy = (cxy_t)GET_CXY( xp );
1775            desc       = (rpc_desc_t *)GET_PTR( xp );
1776
1777            // get rpc index from RPC descriptor
1778                index = hal_remote_lw( XPTR( client_cxy , &desc->index ) );
1779
1780            rpcg_dmsg("\n[INFO] %s : thread %x on core [%x,%d] / rpc = %d\n",
1781                     __FUNCTION__ , this->trdid , core->lid , local_cxy , index );
1782
1783            // call the relevant server function
1784            rpc_server[index]( xp );
1785
1786            // increment handled RPC counter
1787                count++;
1788
1789            // notify RPC completion as required
1790            hal_remote_atomic_add( XPTR( client_cxy , &desc->response ) , -1 );
1791                }
1792       
1793                // exit loop in three cases:
1794        // - fifo is empty
1795        // - look has been released (because descheduling)
1796        // - max number of RPCs has been reached
1797                if( error || 
1798            (rpc_fifo->owner != this->trdid) || 
1799            (count > CONFIG_RPC_PENDING_MAX) ) break;
1800        }
1801    while( 1 );
1802
1803    // update RPC_FIFO global counter
1804        rpc_fifo->count += count;
1805
1806}  // end rpc_execute_all()
1807
1808////////////////////////////////////////////////////
1809error_t rpc_activate_thread( rpc_fifo_t * rpc_fifo )
1810{
1811        core_t      * core;
1812        thread_t    * thread;
1813        thread_t    * this;
1814    scheduler_t * sched;
1815        error_t       error;
1816    bool_t        found;
1817    reg_t         sr_save;
1818
1819   
1820        this   = CURRENT_THREAD;
1821    core   = this->core;
1822    sched  = &core->scheduler;
1823    found  = false;
1824
1825    assert( (this->trdid == rpc_fifo->owner) , __FUNCTION__ ,
1826          "calling thread is not RPC_FIFO owner\n" );
1827
1828    // makes the calling thread not preemptable
1829    // during activation / creation of the RPC thread
1830        hal_disable_irq( &sr_save );
1831
1832    // search a free RPC thread (must be in THREAD_BLOCKED_IDLE state)   
1833    list_entry_t * iter;
1834    LIST_FOREACH( &sched->k_root , iter )
1835    {
1836        thread = LIST_ELEMENT( iter , thread_t , sched_list );
1837        if( (thread->type == THREAD_RPC) && (thread->blocked == THREAD_BLOCKED_IDLE ) ) 
1838        {
1839            found = true;
1840            break;
1841        }
1842    }
1843
1844    if( found )                    // activate this idle RPC thread     
1845    {
1846        // unblock it
1847        thread->blocked = 0;
1848
1849        rpcg_dmsg("\n[INFO] %s : activate RPC thread %x on core [%x,%d] / cycle %d\n", 
1850                          __FUNCTION__ , thread , core->gid , local_cxy , hal_time_stamp() );
1851    }
1852    else                           // create a new RPC thread
1853    {
1854        // create new thread
1855        error = thread_kernel_create( &thread,
1856                                      THREAD_RPC, 
1857                                                  &rpc_thread_func, 
1858                                      NULL,
1859                                                  core->lid );
1860            if( error ) 
1861        {
1862                hal_restore_irq( sr_save );
1863            printk("\n[ERROR] in %s : no memory for new RPC thread in cluster %x\n",
1864                   __FUNCTION__ , local_cxy );
1865            return ENOMEM;
1866        }
1867
1868        // unblock new thread
1869        thread->blocked = 0;
1870
1871        // update core descriptor counter 
1872            hal_atomic_add( &LOCAL_CLUSTER->rpc_threads , 1 );
1873
1874        rpcg_dmsg("\n[INFO] %s : create RPC thread %x on core [%x,%d] / cycle %d\n", 
1875                          __FUNCTION__ , thread->trdid, local_cxy, core->lid, hal_time_stamp() );
1876    }
1877
1878    // update owner in rpc_fifo
1879    rpc_fifo->owner = thread->trdid;
1880
1881    // current thread switch to RPC thread 
1882        sched_yield( thread );
1883
1884    // restore IRQs for the calling thread
1885        hal_restore_irq( sr_save );
1886
1887    // return success
1888        return 0;
1889
1890}  // end rpc_activate_thread()
1891
1892//////////////////
1893bool_t rpc_check()
1894{
1895        thread_t   * this     = CURRENT_THREAD;
1896        rpc_fifo_t * rpc_fifo = &LOCAL_CLUSTER->rpc_fifo;
1897    error_t      error;
1898
1899    rpcg_dmsg("\n[INFO] %s : enter / thread %x / cluster %x / cycle %d\n",
1900             __FUNCTION__ , this->trdid , local_cxy , hal_time_stamp() );
1901
1902    // calling thread does nothing if light lock already taken or FIFO empty 
1903        if( (rpc_fifo->owner != 0) || (local_fifo_is_empty( &rpc_fifo->fifo )) )
1904    {
1905        rpcg_dmsg("\n[INFO] %s : exit do nothing / thread %x / cluster %x / cycle %d\n",
1906                 __FUNCTION__ , this->trdid , local_cxy , hal_time_stamp() );
1907
1908        return false;
1909    }
1910
1911        // try to take the light lock, and activates an RPC thread if success
1912    if( hal_atomic_test_set( &rpc_fifo->owner , this->trdid ) )
1913        {
1914        error = rpc_activate_thread( rpc_fifo );
1915
1916        if( error )    // cannot activate an RPC_THREAD
1917        {
1918            rpc_fifo->owner = 0;
1919
1920            printk("\n[ERROR] in %s : no memory to create a RPC thread for core %d"
1921                   " in cluster %x => do nothing\n",
1922                   __FUNCTION__ , CURRENT_CORE->lid , local_cxy );
1923        }
1924
1925        rpcg_dmsg("\n[INFO] %s : exit after RPC thread activation / "
1926                 "thread %x / cluster %x / cycle %d\n",
1927                 __FUNCTION__ , this->trdid , local_cxy , hal_time_stamp() );
1928
1929        return true;
1930    }
1931    else  // light lock taken by another thread
1932    {
1933        rpcg_dmsg("\n[INFO] %s : exit do nothing / thread %x / cluster %x / cycle %d\n",
1934                 __FUNCTION__ , this->trdid , local_cxy , hal_time_stamp() );
1935
1936        return false;
1937    }
1938} // end rpc_check()
1939
1940
1941//////////////////////
1942void rpc_thread_func()
1943{
1944    // makes the RPC thread not preemptable
1945        hal_disable_irq( NULL );
1946 
1947        thread_t   * this     = CURRENT_THREAD;
1948        rpc_fifo_t * rpc_fifo = &LOCAL_CLUSTER->rpc_fifo;
1949
1950    rpcg_dmsg("\n[INFO] %s : enter / thread %x on core[%x,%d] / cycle %d\n",
1951             __FUNCTION__, this->trdid, local_cxy, this->core->lid, hal_time_stamp() );
1952
1953    // this infinite loop is not preemptable
1954    // the RPC thread deschedule only when the RPC_FIFO is empty
1955        while(1)
1956        {
1957        // check fifo ownership (ownership should be given by rpc_activate()
1958        if( this->trdid != rpc_fifo->owner )
1959        {
1960            panic("thread %x on core[%x,%d] not owner of RPC_FIFO",
1961                  this->trdid, local_cxy, this->core->lid );
1962        }
1963 
1964        // executes pending RPC(s)
1965        rpc_execute_all( rpc_fifo );
1966
1967        // release rpc_fifo ownership (can be lost during RPC execution)
1968        if( rpc_fifo->owner == this->trdid ) rpc_fifo->owner = 0;
1969
1970
1971        //  block and deschedule or sucide
1972                if( LOCAL_CLUSTER->rpc_threads >= CONFIG_RPC_THREADS_MAX ) 
1973                {
1974            rpcg_dmsg("\n[INFO] %s : RPC thread %x on core[%x,%d] suicide / cycle %d\n", 
1975                    __FUNCTION__, this->trdid, local_cxy, this->core->lid, hal_time_stamp() );
1976
1977            // update core descriptor counter
1978                hal_atomic_add( &LOCAL_CLUSTER->rpc_threads , -1 );
1979
1980            // suicide
1981                        thread_exit();
1982                }
1983        else
1984        {
1985            rpcg_dmsg("\n[INFO] %s : RPC thread %x on core[%x,%d] blocks / cycle %d\n", 
1986                        __FUNCTION__, this->trdid, local_cxy, this->core->lid, hal_time_stamp() ); 
1987
1988                    thread_block( this , THREAD_BLOCKED_IDLE );
1989            sched_yield( NULL );
1990
1991                    rpcg_dmsg("\n[INFO] %s : RPC thread %x wake up on core[%x,%d] / cycle %d\n", 
1992                __FUNCTION__, this->trdid, local_cxy, this->core->lid, hal_time_stamp() );
1993        }
1994        } // end while
1995} // end rpc_thread_func()
1996
Note: See TracBrowser for help on using the repository browser.