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

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

Update the RPC_VMM_GET_VSEG.

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