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
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
[1]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/////////////////////////////////////////////////////////////////////////////////////////
[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
98                                error_t  * error,      // out
99                                uint32_t * ppn )       // out
100{
[296]101    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
102
[238]103    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
[1]104
105    // initialise RPC descriptor header
106    rpc_desc_t  rpc;
107    rpc.index    = RPC_PMEM_GET_PAGES;
108    rpc.response = 1;
109
110    // set input arguments in RPC descriptor
111    rpc.args[0] = (uint64_t)order;
112
113    // register RPC request in remote RPC fifo (blocking function)
114    rpc_send_sync( cxy , &rpc );
115
116    // get output arguments RPC descriptor
117    *error  = (error_t)rpc.args[0];     
118    *ppn    = (uint32_t)rpc.args[1];
[279]119
[296]120    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]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
[296]130    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
131
[1]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 );
[296]147
148    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]149}
150
151/////////////////////////////////////////////////////////////////////////////////////////
[23]152// [1]           Marshaling functions attached to RPC_PROCESS_PID_ALLOC
[1]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{
[296]161    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
162
[238]163    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
[1]164
165    // initialise RPC descriptor header
166    rpc_desc_t  rpc;
167    rpc.index    = RPC_PROCESS_PID_ALLOC;
168    rpc.response = 1;
169
170    // set input arguments in RPC descriptor
171    rpc.args[0] = (uint64_t)(intptr_t)process;
172
173    // register RPC request in remote RPC fifo (blocking function)
174    rpc_send_sync( cxy , &rpc );
175
176    // get output arguments RPC descriptor
177    *pid    = (pid_t)rpc.args[1];
178    *error  = (error_t)rpc.args[2];     
[279]179
[296]180    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]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
[296]190    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
191
[1]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 );
[296]206
207    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]208}
209
210
211/////////////////////////////////////////////////////////////////////////////////////////
[23]212// [2]           Marshaling functions attached to RPC_PROCESS_EXEC
[1]213/////////////////////////////////////////////////////////////////////////////////////////
214
215////////////////////////////////////////////////
216void rpc_process_exec_client( cxy_t         cxy,
217                              exec_info_t * info,     // in
218                              error_t     * error )   // out
219{
[296]220    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
221
[238]222    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
[1]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];     
[279]237
[296]238    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]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
[296]248    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
249
[1]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 );
[296]267
268    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]269}
270
271
272/////////////////////////////////////////////////////////////////////////////////////////
[23]273// [3]           Marshaling functions attached to RPC_PROCESS_KILL
[1]274/////////////////////////////////////////////////////////////////////////////////////////
275
276///////////////////////////////////////////////////
277void rpc_process_kill_client( process_t * process ) 
278{
[296]279    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
280
[1]281    // only reference cluster can send this RPC
[238]282    assert( (GET_CXY( process->ref_xp ) == local_cxy) , __FUNCTION__ ,
283            "caller must be reference process cluster\n");
[1]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    }
[279]310
[296]311    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]312} 
313
314/////////////////////////////////////////
315void rpc_process_kill_server( xptr_t xp )
316{
317    pid_t       pid;
318    process_t * process; 
319
[296]320    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
321
[1]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    }
[296]341
342    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]343} 
344
345
346/////////////////////////////////////////////////////////////////////////////////////////
[23]347// [4]           Marshaling functions attached to RPC_THREAD_USER_CREATE               
[1]348/////////////////////////////////////////////////////////////////////////////////////////
349
350/////////////////////////////////////////////////////////
351void rpc_thread_user_create_client( cxy_t            cxy, 
[23]352                                    pid_t            pid,         // in
353                                    void           * start_func,  // in
354                                    void           * start_arg,   // in
[1]355                                    pthread_attr_t * attr,        // in
356                                    xptr_t         * thread_xp,   // out
357                                    error_t        * error )      // out
358{
[296]359    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
360
[238]361    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
[1]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
[23]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;
[1]373
374    // register RPC request in remote RPC fifo
375    rpc_send_sync( cxy , &rpc );
376
377    // get output arguments from RPC descriptor
[23]378    *thread_xp = (xptr_t)rpc.args[4];
379    *error     = (error_t)rpc.args[5];
[279]380
[296]381    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]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
[23]391
[1]392    pid_t            pid;        // process identifier
[23]393    void           * start_func;
394    void           * start_arg;
395    error_t          error;
[1]396
[296]397    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
398
[1]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
[23]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
[1]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   
[23]416    assert( (attr_copy.cxy == local_cxy) , __FUNCTION__ , "bad target cluster\n" );
[1]417
[23]418    // call kernel function
419    error = thread_user_create( pid,
420                                start_func,
421                                start_arg,
422                                &attr_copy,
423                                &thread_ptr );
[1]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 );
[296]429
430    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]431}
432
433/////////////////////////////////////////////////////////////////////////////////////////
[23]434// [5]           Marshaling functions attached to RPC_THREAD_KERNEL_CREATE
[1]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{
[296]445    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
446
[238]447    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
[1]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];
[279]465
[296]466    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]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
[296]477    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
478
[1]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 );
[296]498
499    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]500}
501
502/////////////////////////////////////////////////////////////////////////////////////////
[23]503// [6]           Marshaling functions attached to RPC_SIGNAL_RISE
[1]504/////////////////////////////////////////////////////////////////////////////////////////
505
[23]506/////////////////////////////////////////////
507void rpc_signal_rise_client( cxy_t       cxy,
508                             process_t * process,    // in
509                             uint32_t    sig_id )    // in
510{
[296]511    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
512
[238]513    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
[23]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 );
[279]526
[296]527    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[23]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
[296]536    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
537
[23]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 );
[296]548
549    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[23]550}
551
552/////////////////////////////////////////////////////////////////////////////////////////
553// [10]          Marshaling functions attached to RPC_VFS_INODE_CREATE
554/////////////////////////////////////////////////////////////////////////////////////////
555
[1]556/////////////////////////////////////////////////////
557void rpc_vfs_inode_create_client( cxy_t          cxy,     
558                                  xptr_t         dentry_xp,  // in
[23]559                                  uint32_t       fs_type,    // in
560                                  uint32_t       inode_type, // in
[188]561                                  void         * extend,     // in
[1]562                                  uint32_t       attr,       // in
[23]563                                  uint32_t       rights,     // in
[1]564                                  uint32_t       uid,        // in
565                                  uint32_t       gid,        // in
566                                  xptr_t       * inode_xp,   // out
567                                  error_t      * error )     // out
568{
[296]569    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
570
[238]571    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
[1]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;
[23]580    rpc.args[1] = (uint64_t)fs_type;
581    rpc.args[2] = (uint64_t)inode_type;
[188]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;
[1]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
[188]592    *inode_xp = (xptr_t)rpc.args[8];
593    *error    = (error_t)rpc.args[9];
[279]594
[296]595    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]596}
597
598/////////////////////////////////////////////
599void rpc_vfs_inode_create_server( xptr_t xp )
600{
601    xptr_t           dentry_xp;
[23]602    uint32_t         fs_type;
603    uint32_t         inode_type;
[188]604    void           * extend;
[1]605    uint32_t         attr;
[23]606    uint32_t         rights;
[1]607    uint32_t         uid;
608    uint32_t         gid;
609    xptr_t           inode_xp;
610    error_t          error;
611
[296]612    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
613
[1]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
[188]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] ) );
[1]627
628    // call local kernel function
629    error = vfs_inode_create( dentry_xp,
[23]630                              fs_type,
631                              inode_type,
[188]632                              extend,
[1]633                              attr,
[23]634                              rights,
[1]635                              uid,
636                              gid,
637                              &inode_xp );
638
639    // set output arguments
[188]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 );
[296]642
643    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]644}
645
646/////////////////////////////////////////////////////////////////////////////////////////
[23]647// [11]          Marshaling functions attached to RPC_VFS_INODE_DESTROY
[1]648/////////////////////////////////////////////////////////////////////////////////////////
649
650/////////////////////////////////////////////////////////////
651void rpc_vfs_inode_destroy_client( cxy_t                cxy,
652                                   struct vfs_inode_s * inode )
653{
[296]654    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
655
[238]656    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
[1]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 );
[279]668
[296]669    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]670}
671
672//////////////////////////////////////////////
673void rpc_vfs_inode_destroy_server( xptr_t xp )
674{
675    vfs_inode_t * inode;
676
[296]677    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
678
[1]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 );
[296]688
689    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]690}
691
692/////////////////////////////////////////////////////////////////////////////////////////
[23]693// [12]          Marshaling functions attached to RPC_VFS_DENTRY_CREATE
[1]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{
[296]704    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
705
[238]706    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
[1]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;
[238]716    rpc.args[2] = (uint64_t)(intptr_t)parent;
[1]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
[238]722    *dentry_xp = (xptr_t)rpc.args[3];
723    *error     = (error_t)rpc.args[4];
[279]724
[296]725    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]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
[238]737    char          name_copy[CONFIG_VFS_MAX_NAME_LENGTH];
738
[296]739    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
740
[1]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
[238]745    // get arguments "name", "type", and "parent" from client RPC descriptor
[1]746    type   = (uint32_t)               hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
[238]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] ) );
[296]749
[238]750    // makes a local copy of  name
751    hal_remote_strcpy( XPTR( local_cxy , name_copy ),
752                       XPTR( client_cxy , name ) );
753
[1]754    // call local kernel function
755    error = vfs_dentry_create( type,
756                               name_copy,
757                               parent,
758                               &dentry_xp );
759    // set output arguments
[238]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 );
[296]762
763    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]764}
765
766/////////////////////////////////////////////////////////////////////////////////////////
[23]767// [13]          Marshaling functions attached to RPC_VFS_DENTRY_DESTROY
[1]768/////////////////////////////////////////////////////////////////////////////////////////
769
[296]770
[1]771///////////////////////////////////////////////////////
772void rpc_vfs_dentry_destroy_client( cxy_t          cxy,
773                                    vfs_dentry_t * dentry )
774{
[296]775    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
776
[238]777    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
[1]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 );
[279]789
[296]790    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]791}
792
793///////////////////////////////////////////////
794void rpc_vfs_dentry_destroy_server( xptr_t xp )
795{
796    vfs_dentry_t * dentry;
797
[296]798    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
799
[1]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 );
[296]809
810    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]811}
812
813
814/////////////////////////////////////////////////////////////////////////////////////////
[23]815// [14]          Marshaling functions attached to RPC_VFS_FILE_CREATE
[1]816/////////////////////////////////////////////////////////////////////////////////////////
817
[23]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{
[296]825    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
826
[238]827    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
[23]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];
[279]844
[296]845    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[23]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
[296]856    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
857
[23]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 );
[296]874
875    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[23]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{
[296]886    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
887
[238]888    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
[23]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 );
[279]900
[296]901    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[23]902}
903
904/////////////////////////////////////////////
905void rpc_vfs_file_destroy_server( xptr_t xp )
906{
907    vfs_file_t * file;
908
[296]909    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
910
[23]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 );
[296]920
921    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[23]922}
923
924/////////////////////////////////////////////////////////////////////////////////////////
[238]925// [16]          Marshaling functions attached to RPC_VFS_INODE_LOAD 
[23]926/////////////////////////////////////////////////////////////////////////////////////////
927
[1]928//////////////////////////////////////////////////
[238]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{
[296]935    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
936
[238]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];
[279]954
[296]955    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[238]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
[296]968    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
969
[238]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 );
[296]988
989    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[238]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{
[296]1001    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
1002
[238]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];
[279]1018
[296]1019    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[238]1020}
1021
1022////////////////////////////////////////////////
1023void rpc_vfs_mapper_load_all_server( xptr_t xp )
1024{
1025    error_t       error;
1026    vfs_inode_t * inode;
1027
[296]1028    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
1029
[238]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 );
[296]1042
1043    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[238]1044}
1045
1046/////////////////////////////////////////////////////////////////////////////////////////
1047// [18]          Marshaling functions attached to RPC_FATFS_GET_CLUSTER
1048/////////////////////////////////////////////////////////////////////////////////////////
1049
1050//////////////////////////////////////////////////
[23]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{
[296]1058    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
1059
[238]1060    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
[23]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];
[279]1078
[296]1079    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[23]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
[296]1091    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
1092
[23]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 );
[296]1108
1109    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[23]1110}
1111
1112/////////////////////////////////////////////////////////////////////////////////////////
1113// [20]          Marshaling functions attached to RPC_VMM_GET_REF_VSEG
1114/////////////////////////////////////////////////////////////////////////////////////////
1115
1116//////////////////////////////////////////////////
[1]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{
[296]1122    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
1123
[238]1124    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
[1]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];
[279]1140
[296]1141    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]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
[296]1152    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
1153
[1]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
[16]1166    if( vseg_ptr == NULL ) vseg_xp = XPTR_NULL;
1167    else                   vseg_xp = XPTR( local_cxy , vseg_ptr );
[1]1168    hal_remote_swd( XPTR( client_cxy , &desc->args[2] ) , (uint64_t)vseg_xp );
[296]1169
1170    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]1171}
1172
1173
1174/////////////////////////////////////////////////////////////////////////////////////////
[23]1175// [21]          Marshaling functions attached to RPC_VMM_GET_PTE
[1]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{
[296]1186    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
1187
[238]1188    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
[1]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];
[279]1206
[296]1207    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]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
[296]1219    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
1220
[1]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 );
[296]1236
1237    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]1238}
1239
1240/////////////////////////////////////////////////////////////////////////////////////////
[23]1241// [22]          Marshaling functions attached to RPC_KCM_ALLOC
[1]1242/////////////////////////////////////////////////////////////////////////////////////////
1243
[23]1244//////////////////////////////////////////
1245void rpc_kcm_alloc_client( cxy_t      cxy,
1246                           uint32_t   kmem_type,   // in
1247                           xptr_t *   buf_xp )     // out
[1]1248{
[296]1249    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
1250
[238]1251    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
[1]1252
1253    // initialise RPC descriptor header
1254    rpc_desc_t  rpc;
1255    rpc.index    = RPC_THREAD_USER_CREATE;
1256    rpc.response = 1;
1257
[23]1258    // set input arguments in RPC descriptor
1259    rpc.args[0] = (uint64_t)kmem_type;
1260
[1]1261    // register RPC request in remote RPC fifo
1262    rpc_send_sync( cxy , &rpc );
1263
1264    // get output arguments from RPC descriptor
[23]1265    *buf_xp = (xptr_t)rpc.args[1];
[279]1266
[296]1267    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]1268}
1269
[23]1270//////////////////////////////////////
1271void rpc_kcm_alloc_server( xptr_t xp )
[1]1272{
[296]1273    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
1274
[1]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
[23]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
[1]1283    kmem_req_t  req;
[23]1284    req.type  = kmem_type;
[1]1285    req.flags = AF_ZERO;
[23]1286    void * buf_ptr = kmem_alloc( &req );
[1]1287
1288    // set output argument
[23]1289    xptr_t buf_xp = XPTR( local_cxy , buf_ptr );
1290    hal_remote_swd( XPTR( client_cxy , &desc->args[1] ) , (uint64_t)buf_xp );
[296]1291
1292    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]1293}   
1294
1295/////////////////////////////////////////////////////////////////////////////////////////
[23]1296// [23]          Marshaling functions attached to RPC_KCM_FREE
[1]1297/////////////////////////////////////////////////////////////////////////////////////////
1298
[23]1299/////////////////////////////////////////
1300void rpc_kcm_free_client( cxy_t      cxy,
1301                          void     * buf,          // in
1302                          uint32_t   kmem_type )   // in
[1]1303{
[296]1304    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
1305
[238]1306    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
[1]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
[23]1314    rpc.args[0] = (uint64_t)(intptr_t)buf;
1315    rpc.args[1] = (uint64_t)kmem_type;
[1]1316
1317    // register RPC request in remote RPC fifo
1318    rpc_send_sync( cxy , &rpc );
[279]1319
[296]1320    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]1321}
1322
[23]1323/////////////////////////////////////
1324void rpc_kcm_free_server( xptr_t xp )
[1]1325{
[296]1326    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
1327
[1]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
[23]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] ) );
[1]1335
1336    // releases memory
1337    kmem_req_t  req;
[23]1338    req.type = kmem_type;
1339    req.ptr  = buf;
1340    kmem_free( &req );
[296]1341
1342    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]1343}   
1344
1345/////////////////////////////////////////////////////////////////////////////////////////
[265]1346// [24]          Marshaling functions attached to RPC_MAPPER_MOVE_BUFFER
[1]1347/////////////////////////////////////////////////////////////////////////////////////////
1348
[265]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
[1]1358{
[296]1359    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
1360
[238]1361    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
[1]1362
1363    // initialise RPC descriptor header
1364    rpc_desc_t  rpc;
[265]1365    rpc.index    = RPC_MAPPER_MOVE_BUFFER;
[1]1366    rpc.response = 1;
1367
1368    // set input arguments in RPC descriptor
1369    rpc.args[0] = (uint64_t)(intptr_t)mapper;
[23]1370    rpc.args[1] = (uint64_t)to_buffer;
[265]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;
[1]1375
[23]1376    // register RPC request in remote RPC fifo (blocking function)
[1]1377    rpc_send_sync( cxy , &rpc );
1378
[23]1379    // get output values from RPC descriptor
[265]1380    *error     = (error_t)rpc.args[6];
[279]1381
[296]1382    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]1383}
1384
[265]1385///////////////////////////////////////////////
1386void rpc_mapper_move_buffer_server( xptr_t xp )
[1]1387{
[23]1388    mapper_t * mapper;
[265]1389    bool_t     to_buffer;
1390    bool_t     is_user;
[23]1391    uint32_t   file_offset;
1392    void     * buffer;
1393    uint32_t   size;
1394    error_t    error;
[1]1395
[296]1396    rpc_dmsg("\n[INFO] %s : enter at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
1397
[1]1398    // get client cluster identifier and pointer on RPC descriptor
1399    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
[23]1400    rpc_desc_t * desc        = (rpc_desc_t *)GET_PTR( xp );
[1]1401
[23]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] ) );
[265]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] ) );
[1]1409
[23]1410    // call local kernel function
[265]1411    error = mapper_move_buffer( mapper,
1412                                to_buffer,
1413                                is_user,
1414                                file_offset,
1415                                buffer,
1416                                size );
[1]1417
[23]1418    // set output argument to client RPC descriptor
[265]1419    hal_remote_swd( XPTR( client_cxy , &desc->args[6] ) , (uint64_t)error );
[296]1420
1421    rpc_dmsg("\n[INFO] %s : completed at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
[1]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
[279]1437    thread_t * this = CURRENT_THREAD;
[1]1438
[296]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() );
[279]1441
[1]1442    // allocate and initialise an extended pointer on the RPC descriptor
[279]1443        xptr_t   desc_xp = XPTR( local_cxy , rpc );
[1]1444
[279]1445    // get local pointer on rpc_fifo in remote cluster, with the
1446    // assumption that rpc_fifo pddresses are identical in all clusters
[1]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 ),
[279]1454                                      (uint64_t )desc_xp,
[1]1455                                      &first );
1456
1457            if ( error ) 
1458        {
[279]1459            printk("\n[WARNING] %s : cluster %x cannot post RPC to cluster %x\n",
[296]1460            __FUNCTION__ , local_cxy , server_cxy );
[279]1461
[296]1462            if( thread_can_yield() ) sched_yield( NULL );
[1]1463        }
1464    }
1465    while( error );
1466 
[296]1467    rpc_dmsg("\n[INFO] %s : RPC %l registered / server_cxy = %x / cycle %d\n",
1468    __FUNCTION__ , desc_xp , server_cxy , hal_time_stamp() );
[1]1469       
[279]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.
[1]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                {
[279]1479                    dev_pic_send_ipi( server_cxy , 0 );
[1]1480
[279]1481                    rpc_dmsg("\n[INFO] %s : IPI sent / client_cxy = %x / server_cxy = %x\n",
[296]1482            __FUNCTION__, local_cxy , server_cxy );
[1]1483        }
1484        }
1485
[279]1486        // enable IRQs to allow incoming RPC and avoid deadlock
[1]1487        if( this->type == THREAD_RPC ) hal_enable_irq( &sr_save );
1488
[279]1489    // the server thread poll the response slot until RPC completed
1490    // TODO this could be replaced by a descheduling policy... [AG]
[1]1491        while( 1 )
1492    {
1493        if( rpc->response == 0 ) break;
1494    }
1495
[279]1496    // restore IRQs
[1]1497        if( this->type == THREAD_RPC ) hal_restore_irq( sr_save );
1498
[296]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() );
[279]1501
[1]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
[279]1518/////////////////////////////////////////////
1519void rpc_execute_all( rpc_fifo_t * rpc_fifo )
[1]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     
[296]1530        this  = CURRENT_THREAD; 
1531    core  = this->core;   
1532        count = 0;
[1]1533
[296]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 
[1]1537    // handle up to CONFIG_RPC_PENDING_MAX requests before exit
1538        do
1539    {
[296]1540            error = local_fifo_get_item( &rpc_fifo->fifo, (uint64_t *)&xp );
[1]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
[279]1548            // get rpc index from RPC descriptor
[296]1549                index = hal_remote_lw( XPTR( client_cxy , &desc->index ) );
[1]1550
[296]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
[1]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
[279]1561            hal_remote_atomic_add( XPTR(client_cxy,&desc->response) , -1 );
[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        }
[279]1572    while( 1 );
[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
[279]1590   
[1]1591        this   = CURRENT_THREAD;
1592    core   = this->core;
1593    sched  = &core->scheduler;
1594    found  = false;
1595
[279]1596    assert( (this->trdid == rpc_fifo->owner) , __FUNCTION__ ,
1597          "calling thread is not RPC_FIFO owner\n" );
[1]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 );
[279]1608        if( (thread->type == THREAD_RPC) && (thread->blocked == THREAD_BLOCKED_IDLE ) ) 
[1]1609        {
1610            found = true;
1611            break;
1612        }
1613    }
1614
1615    if( found )                    // activate this idle RPC thread     
1616    {
[296]1617        // unblock it
[1]1618        thread->blocked = 0;
[279]1619
[296]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() );
[1]1622    }
1623    else                           // create a new RPC thread
1624    {
[296]1625        // create new thread
[1]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
[296]1639        // unblock new thread
1640        thread->blocked = 0;
[1]1641
1642        // update core descriptor counter 
[279]1643            hal_atomic_add( &LOCAL_CLUSTER->rpc_threads , 1 );
[296]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() );
[1]1647    }
1648
1649    // update owner in rpc_fifo
1650    rpc_fifo->owner = thread->trdid;
1651
[296]1652    // current thread switch to RPC thread 
1653        sched_yield( thread );
[1]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
[296]1670    rpc_dmsg("\n[INFO] %s : enter in cluster %x\n",
1671             __FUNCTION__ , local_cxy );
1672
[5]1673    // calling thread does nothing if light lock already taken or FIFO empty 
[1]1674        if( (rpc_fifo->owner != 0) || (local_fifo_is_empty( &rpc_fifo->fifo )) )
1675    {
[296]1676        rpc_dmsg("\n[INFO] %s : exit but do nothing in cluster %x\n",
1677                 __FUNCTION__ , local_cxy );
1678
[1]1679        return false;
1680    }
1681
[279]1682        // try to take the light lock, and activates an RPC thread if success
[1]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
[296]1696        rpc_dmsg("\n[INFO] %s : exit after activating an RPC thread in cluster %x\n",
1697                 __FUNCTION__ , local_cxy );
1698
[1]1699        return true;
1700    }
1701    else  // light lock taken by another thread
1702    {
[296]1703        rpc_dmsg("\n[INFO] %s : exit but do nothing in cluster %x\n",
1704                 __FUNCTION__ , local_cxy );
1705
[1]1706        return false;
1707    }
[5]1708} // end rpc_check()
[1]1709
1710
1711//////////////////////
1712void rpc_thread_func()
1713{
[296]1714    // makes the RPC thread not preemptable
[1]1715        hal_disable_irq( NULL );
1716 
1717        thread_t   * this     = CURRENT_THREAD;
1718        rpc_fifo_t * rpc_fifo = &LOCAL_CLUSTER->rpc_fifo;
1719
[296]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() );
[1]1722
1723    // this infinite loop is not preemptable
[279]1724    // the RPC thread deschedule only when the RPC_FIFO is empty
[1]1725        while(1)
1726        {
1727        // check fifo ownership (ownership should be given by rpc_activate()
1728        if( this->trdid != rpc_fifo->owner )
1729        {
[296]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 );
[1]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
[279]1742        //  block and deschedule or sucide
1743                if( LOCAL_CLUSTER->rpc_threads >= CONFIG_RPC_THREADS_MAX ) 
[1]1744                {
[296]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() );
[1]1747
1748            // update core descriptor counter
[279]1749                hal_atomic_add( &LOCAL_CLUSTER->rpc_threads , -1 );
[1]1750
1751            // suicide
1752                        thread_exit();
1753                }
[279]1754        else
1755        {
[296]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() ); 
[1]1758
[296]1759                    thread_block( this , THREAD_BLOCKED_IDLE );
1760            sched_yield( NULL );
[1]1761
[296]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() );
[279]1764        }
1765        } // end while
[1]1766} // end rpc_thread_func()
1767
Note: See TracBrowser for help on using the repository browser.