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

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

RSeveral modifs in the page-fault handling.

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