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

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

Fix several bugs in the fork() syscall.

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