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

Last change on this file since 356 was 337, checked in by alain, 7 years ago

Introduce the delayed context switch if current thread has a lock.

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