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

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

Several modifs in the generic scheduler and in the hal_context to
fix the context switch mechanism.

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