/* * rpc.c - RPC related operations implementation. * * Author Alain Greiner (2016,2017) * * Copyright (c) UPMC Sorbonne Universites * * This file is part of ALMOS-MKH. * * ALMOS-MKH is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2.0 of the License. * * ALMOS-MKH is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ALMOS-MKH; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include ///////////////////////////////////////////////////////////////////////////////////////// // Debug macros for marshalling functions ///////////////////////////////////////////////////////////////////////////////////////// #if CONFIG_DEBUG_RPC_MARSHALING #define RPC_DEBUG_ENTER \ uint32_t cycle = (uint32_t)hal_get_cycles(); \ if( cycle > CONFIG_DEBUG_RPC_MARSHALING ) \ printk("\n[DBG] %s : enter thread %x on core[%x,%d] / cycle %d\n", \ __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , cycle ); #define RPC_DEBUG_EXIT \ cycle = (uint32_t)hal_get_cycles(); \ if( cycle > CONFIG_DEBUG_RPC_MARSHALING ) \ printk("\n[DBG] %s : exit thread %x on core[%x,%d] / cycle %d\n", \ __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , cycle ); #else #define RPC_DEBUG_ENTER #define RPC_DEBUG_EXIT #endif ///////////////////////////////////////////////////////////////////////////////////////// // array of function pointers (must be consistent with enum in rpc.h) ///////////////////////////////////////////////////////////////////////////////////////// rpc_server_t * rpc_server[RPC_MAX_INDEX] = { &rpc_pmem_get_pages_server, // 0 &rpc_pmem_release_pages_server, // 1 &rpc_undefined, // 2 unused slot &rpc_process_make_fork_server, // 3 &rpc_undefined, // 4 unused slot &rpc_process_make_kill_server, // 5 &rpc_thread_user_create_server, // 6 &rpc_thread_kernel_create_server, // 7 &rpc_thread_kill_server, // 8 &rpc_process_sigaction_server, // 9 &rpc_vfs_inode_create_server, // 10 &rpc_vfs_inode_destroy_server, // 11 &rpc_vfs_dentry_create_server, // 12 &rpc_vfs_dentry_destroy_server, // 13 &rpc_vfs_file_create_server, // 14 &rpc_vfs_file_destroy_server, // 15 &rpc_vfs_inode_load_server, // 16 &rpc_vfs_mapper_load_all_server, // 17 &rpc_fatfs_get_cluster_server, // 18 &rpc_undefined, // 19 unused slot &rpc_vmm_get_vseg_server, // 20 &rpc_vmm_get_pte_server, // 21 &rpc_kcm_alloc_server, // 22 &rpc_kcm_free_server, // 23 &rpc_mapper_move_buffer_server, // 24 &rpc_mapper_get_page_server, // 25 &rpc_vmm_create_vseg_server, // 26 &rpc_sched_display_server, // 27 &rpc_vmm_set_cow_server, // 28 &rpc_vmm_display_server, // 29 }; ////////////////////////////////////////////// void __attribute__((noinline)) rpc_undefined() { assert( false , __FUNCTION__ , "called in cluster %x", local_cxy ); } /***************************************************************************************/ /************ Generic functions supporting RPCs : client side **************************/ /***************************************************************************************/ /////////////////////////////////////// void rpc_send( cxy_t server_cxy, rpc_desc_t * rpc ) { error_t error; thread_t * this = CURRENT_THREAD; core_t * core = this->core; // register client thread pointer and core lid in RPC descriptor rpc->thread = this; rpc->lid = core->lid; // build an extended pointer on the RPC descriptor xptr_t desc_xp = XPTR( local_cxy , rpc ); // get local pointer on rpc_fifo in remote cluster, with the // assumption that local pointers are identical in all clusters remote_fifo_t * rpc_fifo = &LOCAL_CLUSTER->rpc_fifo; // try to post an item in remote fifo // deschedule and retry if remote fifo full do { error = remote_fifo_put_item( XPTR( server_cxy , rpc_fifo ), (uint64_t )desc_xp ); if ( error ) { printk("\n[WARNING] %s : cluster %x cannot post RPC to cluster %x\n", __FUNCTION__ , local_cxy , server_cxy ); if( thread_can_yield() ) sched_yield("RPC fifo full"); } } while( error ); hal_fence(); // send IPI to the remote core corresponding to the client core dev_pic_send_ipi( server_cxy , core->lid ); // wait RPC completion before returning if blocking RPC // - busy waiting policy during kernel_init, or if threads cannot yield // - block and deschedule in all other cases if ( rpc->blocking ) { if( (this->type == THREAD_IDLE) || (thread_can_yield() == false) ) // busy waiting { grpc_dmsg("\n[DBG] %s : core[%x,%d] / thread %s busy waiting after registering RPC\n" " rpc = %d / server = %x / cycle %d\n", __FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , thread_type_str(this->type) , rpc->index , server_cxy , hal_time_stamp() ); while( rpc->response ) hal_fixed_delay( 100 ); grpc_dmsg("\n[DBG] %s : core[%x,%d] / thread %s exit after RPC completion\n", __FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , thread_type_str(this->type) ); } else // block & deschedule { grpc_dmsg("\n[DBG] %s : core[%x,%d] / thread %s deschedule after registering RPC\n" " rpc = %d / server = %x / cycle %d\n", __FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , thread_type_str(this->type) , rpc->index , server_cxy , hal_time_stamp() ); thread_block( this , THREAD_BLOCKED_RPC ); sched_yield("BLOCKED on RPC"); grpc_dmsg("\n[DBG] %s : core[%x,%d] / thread %s resumes after RPC completion\n", __FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , thread_type_str(this->type) ); } // check response available assert( (rpc->response == 0) , __FUNCTION__, "illegal RPC response\n" ); // acknowledge the IPI sent by the server dev_pic_ack_ipi(); } } // end rpc_send() /***************************************************************************************/ /************ Generic functions supporting RPCs : server side **************************/ /***************************************************************************************/ //////////////// void rpc_check() { error_t error; thread_t * thread; uint32_t sr_save; bool_t found = false; thread_t * this = CURRENT_THREAD; core_t * core = this->core; scheduler_t * sched = &core->scheduler; remote_fifo_t * rpc_fifo = &LOCAL_CLUSTER->rpc_fifo; grpc_dmsg("\n[DBG] %s : core[%x,%d] / interrupted thread %s / cycle %d\n", __FUNCTION__, local_cxy, core->lid, thread_type_str(this->type), hal_time_stamp() ); // interrupted thread not preemptable during RPC chek hal_disable_irq( &sr_save ); // check RPC FIFO not empty and no RPC thread handling it if( (rpc_fifo->owner == 0) && (local_fifo_is_empty(rpc_fifo) == false) ) { // search one non blocked RPC thread list_entry_t * iter; LIST_FOREACH( &sched->k_root , iter ) { thread = LIST_ELEMENT( iter , thread_t , sched_list ); if( (thread->type == THREAD_RPC) && (thread->blocked == 0 ) ) { found = true; break; } } // create new RPC thread if not found if( found == false ) { error = thread_kernel_create( &thread, THREAD_RPC, &rpc_thread_func, NULL, this->core->lid ); if( error ) { printk("\n[WARNING] in %s : no memory for new RPC thread in cluster %x\n", __FUNCTION__ , local_cxy ); } else { // unblock created RPC thread thread->blocked = 0; // update core descriptor counter hal_atomic_add( &LOCAL_CLUSTER->rpc_threads , 1 ); grpc_dmsg("\n[DBG] %s : core [%x,%d] creates a new RPC thread %x / trdid %x / cycle %d\n", __FUNCTION__ , local_cxy , core->lid , thread , thread->trdid , hal_time_stamp() ); } } } grpc_dmsg("\n[DBG] %s : core[%x,%d] / interrupted thread %s deschedules / cycle %d\n", __FUNCTION__, local_cxy, core->lid, thread_type_str(this->type), hal_time_stamp() ); // interrupted thread deschedule always sched_yield("IPI received"); grpc_dmsg("\n[DBG] %s : core[%x,%d] / interrupted thread %s resume / cycle %d\n", __FUNCTION__, local_cxy, core->lid, thread_type_str(this->type), hal_time_stamp() ); // interrupted thread restore IRQs after resume hal_restore_irq( sr_save ); } // end rpc_check() ////////////////////// void rpc_thread_func() { uint32_t count; // handled RPC requests counter error_t empty; // local RPC fifo state xptr_t desc_xp; // extended pointer on RPC request cxy_t desc_cxy; // RPC request cluster (client) rpc_desc_t * desc_ptr; // RPC request local pointer uint32_t index; // RPC request index thread_t * thread_ptr; // local pointer on client thread lid_t core_lid; // local index of client core bool_t blocking; // blocking RPC when true // makes RPC thread not preemptable hal_disable_irq( NULL ); thread_t * this = CURRENT_THREAD; remote_fifo_t * rpc_fifo = &LOCAL_CLUSTER->rpc_fifo; // two embedded loops: // - external loop : "infinite" RPC thread // - internal loop : handle up to CONFIG_RPC_PENDING_MAX RPC requests while(1) // external loop { // try to take RPC_FIFO ownership if( hal_atomic_test_set( &rpc_fifo->owner , this->trdid ) ) { // initializes RPC requests counter count = 0; // acknowledge local IPI dev_pic_ack_ipi(); // exit internal loop in three cases: // - RPC fifo is empty // - ownership has been lost (because descheduling) // - max number of RPCs is reached while( 1 ) // internal loop { empty = local_fifo_get_item( rpc_fifo , (uint64_t *)&desc_xp ); if ( empty == 0 ) // one RPC request found { // get client cluster and pointer on RPC descriptor desc_cxy = (cxy_t)GET_CXY( desc_xp ); desc_ptr = (rpc_desc_t *)GET_PTR( desc_xp ); // get RPC & fields from RPC descriptor index = hal_remote_lw( XPTR( desc_cxy , &desc_ptr->index ) ); blocking = hal_remote_lw( XPTR( desc_cxy , &desc_ptr->blocking ) ); grpc_dmsg("\n[DBG] %s : core[%x,%d] / RPC thread %x / starts rpc %d / cycle %d\n", __FUNCTION__ , local_cxy , this->core->lid , this->trdid , index , (uint32_t)hal_get_cycles() ); // call the relevant server function rpc_server[index]( desc_xp ); grpc_dmsg("\n[DBG] %s : core[%x,%d] / RPC thread %x / completes rpc %d / cycle %d\n", __FUNCTION__ , local_cxy , this->core->lid , this->trdid , index , hal_time_stamp() ); // increment handled RPCs counter count++; // decrement response counter in RPC descriptor if blocking if( blocking ) { // decrement responses counter in RPC descriptor hal_remote_atomic_add(XPTR( desc_cxy, &desc_ptr->response ), -1); // unblock client thread thread_ptr = (thread_t *)hal_remote_lpt(XPTR(desc_cxy,&desc_ptr->thread)); thread_unblock( XPTR(desc_cxy,thread_ptr) , THREAD_BLOCKED_RPC ); hal_fence(); // get client core lid and send IPI core_lid = hal_remote_lw(XPTR(desc_cxy, &desc_ptr->lid)); dev_pic_send_ipi( desc_cxy , core_lid ); } } // chek exit condition if( local_fifo_is_empty( rpc_fifo ) || (rpc_fifo->owner != this->trdid) || (count >= CONFIG_RPC_PENDING_MAX) ) break; } // end internal loop // release rpc_fifo ownership if not lost if( rpc_fifo->owner == this->trdid ) rpc_fifo->owner = 0; } // end if RPC fifo // sucide if too many RPC threads in cluster if( LOCAL_CLUSTER->rpc_threads >= CONFIG_RPC_THREADS_MAX ) { grpc_dmsg("\n[DBG] %s : core[%x,%d] (RPC thread %x) suicide at cycle %d\n", __FUNCTION__, local_cxy, this->core->lid, this->trdid, hal_time_stamp() ); // update RPC threads counter hal_atomic_add( &LOCAL_CLUSTER->rpc_threads , -1 ); // suicide thread_kill( this ); } grpc_dmsg("\n[DBG] %s : core[%x,%d] (RPC thread %x) deschedules / cycle %d\n", __FUNCTION__, local_cxy, this->core->lid, this->trdid, hal_time_stamp() ); // deschedule without blocking sched_yield("RPC fifo empty or too much work"); grpc_dmsg("\n[DBG] %s : core[%x,%d] (RPC thread %x) resumes / cycle %d\n", __FUNCTION__, local_cxy, this->core->lid, this->trdid, hal_time_stamp() ); } // end external loop } // end rpc_thread_func() ///////////////////////////////////////////////////////////////////////////////////////// // [0] Marshaling functions attached to RPC_PMEM_GET_PAGES (blocking) ///////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////// void rpc_pmem_get_pages_client( cxy_t cxy, uint32_t order, // in page_t ** page ) // out { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n"); // initialise RPC descriptor header rpc_desc_t rpc; rpc.index = RPC_PMEM_GET_PAGES; rpc.response = 1; rpc.blocking = true; // set input arguments in RPC descriptor rpc.args[0] = (uint64_t)order; // register RPC request in remote RPC fifo (blocking function) rpc_send( cxy , &rpc ); // get output arguments from RPC descriptor *page = (page_t *)(intptr_t)rpc.args[1]; rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } /////////////////////////////////////////// void rpc_pmem_get_pages_server( xptr_t xp ) { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); // get client cluster identifier and pointer on RPC descriptor cxy_t cxy = (cxy_t)GET_CXY( xp ); rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); // get input arguments from client RPC descriptor uint32_t order = (uint32_t)hal_remote_lwd( XPTR( cxy , &desc->args[0] ) ); // call local pmem allocator page_t * page = ppm_alloc_pages( order ); // set output arguments into client RPC descriptor hal_remote_swd( XPTR( cxy , &desc->args[1] ) , (uint64_t)(intptr_t)page ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////////////////////////////////////////////////// // [1] Marshaling functions attached to RPC_PMEM_RELEASE_PAGES (blocking) ///////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////// void rpc_pmem_release_pages_client( cxy_t cxy, page_t * page ) // out { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n"); // initialise RPC descriptor header rpc_desc_t rpc; rpc.index = RPC_PMEM_RELEASE_PAGES; rpc.response = 1; rpc.blocking = true; // set input arguments in RPC descriptor rpc.args[0] = (uint64_t)(intptr_t)page; // register RPC request in remote RPC fifo (blocking function) rpc_send( cxy , &rpc ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } /////////////////////////////////////////////// void rpc_pmem_release_pages_server( xptr_t xp ) { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); // get client cluster identifier and pointer on RPC descriptor cxy_t cxy = (cxy_t)GET_CXY( xp ); rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); // get input arguments from client RPC descriptor page_t * page = (page_t *)(intptr_t)hal_remote_lwd( XPTR( cxy , &desc->args[0] ) ); // release memory to local pmem kmem_req_t req; req.type = KMEM_PAGE; req.ptr = page; kmem_free( &req ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////////////////////////////////////////////////// // [2] undefined slot ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// // [3] Marshaling functions attached to RPC_PROCESS_MAKE_FORK (blocking) ///////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////// void rpc_process_make_fork_client( cxy_t cxy, xptr_t ref_process_xp, // in xptr_t parent_thread_xp, // in pid_t * child_pid, // out thread_t ** child_thread_ptr, // out error_t * error ) // out { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n"); // initialise RPC descriptor header rpc_desc_t rpc; rpc.index = RPC_PROCESS_MAKE_FORK; rpc.response = 1; rpc.blocking = true; // set input arguments in RPC descriptor rpc.args[0] = (uint64_t)(intptr_t)ref_process_xp; rpc.args[1] = (uint64_t)(intptr_t)parent_thread_xp; // register RPC request in remote RPC fifo (blocking function) rpc_send( cxy , &rpc ); // get output arguments from RPC descriptor *child_pid = (pid_t)rpc.args[2]; *child_thread_ptr = (thread_t *)(intptr_t)rpc.args[3]; *error = (error_t)rpc.args[4]; rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ////////////////////////////////////////////// void rpc_process_make_fork_server( xptr_t xp ) { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); xptr_t ref_process_xp; // extended pointer on reference parent process xptr_t parent_thread_xp; // extended pointer on parent thread pid_t child_pid; // child process identifier thread_t * child_thread_ptr; // local copy of exec_info structure error_t error; // local error status // get client cluster identifier and pointer on RPC descriptor cxy_t client_cxy = (cxy_t)GET_CXY( xp ); rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); // get input arguments from cient RPC descriptor ref_process_xp = (xptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); parent_thread_xp = (xptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) ); // call local kernel function error = process_make_fork( ref_process_xp, parent_thread_xp, &child_pid, &child_thread_ptr ); // set output argument into client RPC descriptor hal_remote_swd( XPTR( client_cxy , &desc->args[2] ) , (uint64_t)child_pid ); hal_remote_swd( XPTR( client_cxy , &desc->args[3] ) , (uint64_t)(intptr_t)child_thread_ptr ); hal_remote_swd( XPTR( client_cxy , &desc->args[4] ) , (uint64_t)error ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////////////////////////////////////////////////// // [4] undefined slot ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// // [5] Marshaling functions attached to RPC_PROCESS_MAKE_KILL (blocking) ///////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////// void rpc_process_make_kill_client( cxy_t cxy, process_t * process, bool_t is_exit, uint32_t status ) { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); // initialise RPC descriptor header rpc_desc_t rpc; rpc.index = RPC_PROCESS_MAKE_KILL; rpc.response = 1; rpc.blocking = true; // set input arguments in RPC descriptor rpc.args[0] = (uint64_t)(intptr_t)process; rpc.args[1] = (uint64_t)is_exit; rpc.args[2] = (uint64_t)status; // register RPC request in remote RPC fifo (blocking function) rpc_send( cxy , &rpc ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ////////////////////////////////////////////// void rpc_process_make_kill_server( xptr_t xp ) { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); process_t * process; bool_t is_exit; uint32_t status; // get client cluster identifier and pointer on RPC descriptor cxy_t client_cxy = (cxy_t)GET_CXY( xp ); rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); // get arguments from RPC descriptor process = (process_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); is_exit = (bool_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) ); status = (uint32_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) ); // call local kernel function process_make_kill( process , is_exit , status ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////////////////////////////////////////////////// // [6] Marshaling functions attached to RPC_THREAD_USER_CREATE (blocking) ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////// void rpc_thread_user_create_client( cxy_t cxy, pid_t pid, // in void * start_func, // in void * start_arg, // in pthread_attr_t * attr, // in xptr_t * thread_xp, // out error_t * error ) // out { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n"); // initialise RPC descriptor header rpc_desc_t rpc; rpc.index = RPC_THREAD_USER_CREATE; rpc.response = 1; rpc.blocking = true; // set input arguments in RPC descriptor rpc.args[0] = (uint64_t)pid; rpc.args[1] = (uint64_t)(intptr_t)start_func; rpc.args[2] = (uint64_t)(intptr_t)start_arg; rpc.args[3] = (uint64_t)(intptr_t)attr; // register RPC request in remote RPC fifo (blocking function) rpc_send( cxy , &rpc ); // get output arguments from RPC descriptor *thread_xp = (xptr_t)rpc.args[4]; *error = (error_t)rpc.args[5]; rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } /////////////////////////////////////////////// void rpc_thread_user_create_server( xptr_t xp ) { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); pthread_attr_t * attr_ptr; // pointer on attributes structure in client cluster pthread_attr_t attr_copy; // attributes structure copy in server cluster thread_t * thread_ptr; // local pointer on thread descriptor xptr_t thread_xp; // extended pointer on thread descriptor pid_t pid; // process identifier void * start_func; void * start_arg; error_t error; // get client cluster identifier and pointer on RPC descriptor cxy_t client_cxy = (cxy_t)GET_CXY( xp ); rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); // get pointer on attributes structure in client cluster from RPC descriptor // get input arguments from RPC descriptor pid = (pid_t) hal_remote_lwd(XPTR(client_cxy , &desc->args[0])); start_func = (void *)(intptr_t) hal_remote_lwd(XPTR(client_cxy , &desc->args[1])); start_arg = (void *)(intptr_t) hal_remote_lwd(XPTR(client_cxy , &desc->args[2])); attr_ptr = (pthread_attr_t *)(intptr_t)hal_remote_lwd(XPTR(client_cxy , &desc->args[3])); // makes a local copy of attributes structure hal_remote_memcpy( XPTR( local_cxy , &attr_copy ), XPTR( client_cxy , attr_ptr ), sizeof(pthread_attr_t) ); // call kernel function error = thread_user_create( pid, start_func, start_arg, &attr_copy, &thread_ptr ); // set output arguments thread_xp = XPTR( local_cxy , thread_ptr ); hal_remote_swd( XPTR( client_cxy , &desc->args[4] ) , (uint64_t)thread_xp ); hal_remote_swd( XPTR( client_cxy , &desc->args[5] ) , (uint64_t)error ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////////////////////////////////////////////////// // [7] Marshaling functions attached to RPC_THREAD_KERNEL_CREATE (blocking) ///////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////// void rpc_thread_kernel_create_client( cxy_t cxy, uint32_t type, // in void * func, // in void * args, // in xptr_t * thread_xp, // out error_t * error ) // out { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n"); // initialise RPC descriptor header rpc_desc_t rpc; rpc.index = RPC_THREAD_KERNEL_CREATE; rpc.response = 1; rpc.blocking = true; // set input arguments in RPC descriptor rpc.args[0] = (uint64_t)type; rpc.args[1] = (uint64_t)(intptr_t)func; rpc.args[2] = (uint64_t)(intptr_t)args; // register RPC request in remote RPC fifo (blocking function) rpc_send( cxy , &rpc ); // get output arguments from RPC descriptor *thread_xp = (xptr_t)rpc.args[3]; *error = (error_t)rpc.args[4]; rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////////// void rpc_thread_kernel_create_server( xptr_t xp ) { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); thread_t * thread_ptr; // local pointer on thread descriptor xptr_t thread_xp; // extended pointer on thread descriptor lid_t core_lid; // core local index error_t error; // get client cluster identifier and pointer on RPC descriptor cxy_t client_cxy = (cxy_t)GET_CXY( xp ); rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); // get attributes from RPC descriptor uint32_t type = (uint32_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); void * func = (void*)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) ); void * args = (void*)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) ); // select one core core_lid = cluster_select_local_core(); // call local kernel function error = thread_kernel_create( &thread_ptr , type , func , args , core_lid ); // set output arguments thread_xp = XPTR( local_cxy , thread_ptr ); hal_remote_swd( XPTR( client_cxy , &desc->args[1] ) , (uint64_t)error ); hal_remote_swd( XPTR( client_cxy , &desc->args[2] ) , (uint64_t)thread_xp ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////////////////////////////////////////////////// // [8] Marshaling functions attached to RPC_THREAD_KILL (blocking) ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////// void rpc_thread_kill_client( cxy_t cxy, thread_t * thread ) // in { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); // this RPC can be called in local cluster // initialise RPC descriptor header rpc_desc_t rpc; rpc.index = RPC_THREAD_KILL; rpc.response = 1; rpc.blocking = true; // set input arguments in RPC descriptor rpc.args[0] = (uint64_t)(intptr_t)thread; // register RPC request in remote RPC fifo (blocking function) rpc_send( cxy , &rpc ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } //////////////////////////////////////// void rpc_thread_kill_server( xptr_t xp ) { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); thread_t * thread; // local pointer on process descriptor // get client cluster identifier and pointer on RPC descriptor cxy_t client_cxy = (cxy_t)GET_CXY( xp ); rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); // get attributes from RPC descriptor thread = (thread_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); // call local kernel function thread_kill( thread ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////////////////////////////////////////////////// // [9] Marshaling functions attached to RPC_PROCESS_SIGACTION (multicast / non blocking) ///////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////// void rpc_process_sigaction_client( cxy_t cxy, rpc_desc_t * rpc_ptr ) { sigaction_dmsg("\n[DBG] %s : enter to %s process %x in cluster %x / cycle %d\n", __FUNCTION__ , process_action_str( (uint32_t)rpc_ptr->args[0] ) , ((process_t *)(intptr_t)rpc_ptr->args[1])->pid , cxy , (uint32_t)hal_get_cycles() ); // register RPC request in remote RPC fifo rpc_send( cxy , rpc_ptr ); sigaction_dmsg("\n[DBG] %s : exit after %s process %x in cluster %x / cycle %d\n", __FUNCTION__ , process_action_str( (uint32_t)rpc_ptr->args[0] ) , ((process_t *)(intptr_t)rpc_ptr->args[1])->pid , cxy , (uint32_t)hal_get_cycles() ); } ////////////////////////////////////////////// void rpc_process_sigaction_server( xptr_t xp ) { process_t * process; // pointer on local process descriptor uint32_t action; // sigaction index thread_t * client_ptr; // local pointer on client thread in client cluster cxy_t client_cxy; // client cluster identifier xptr_t client_xp; // extended pointer on client thread core_t * client_core; // local pointer on core running the client thread rpc_desc_t * rpc; // local pointer on rpc descriptor in client cluster // get client cluster identifier and pointer on RPC descriptor client_cxy = (cxy_t)GET_CXY( xp ); rpc = (rpc_desc_t *)GET_PTR( xp ); // get arguments from RPC descriptor action = (uint32_t) hal_remote_lwd( XPTR( client_cxy , &rpc->args[0] ) ); process = (process_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &rpc->args[1] ) ); client_ptr = (thread_t *)hal_remote_lpt( XPTR( client_cxy , &rpc->thread ) ); // build extended pointer on client thread client_xp = XPTR( client_cxy , client_ptr ); sigaction_dmsg("\n[DBG] %s : enter to %s process %x / cycle %d\n", __FUNCTION__ , process_action_str( action ) , process->pid , (uint32_t)hal_get_cycles() ); // call relevant kernel function if (action == DELETE_ALL_THREADS ) process_delete_threads ( process ); else if (action == BLOCK_ALL_THREADS ) process_block_threads ( process ); else if (action == UNBLOCK_ALL_THREADS ) process_unblock_threads( process ); // decrement the responses counter in RPC descriptor, // unblock the client thread only if it is the last response. if( hal_remote_atomic_add( XPTR( client_cxy , &rpc->response ) , -1 ) == 1 ) { client_core = (core_t *)hal_remote_lpt( XPTR( client_cxy , &client_ptr->core ) ); thread_unblock( client_xp , THREAD_BLOCKED_RPC ); dev_pic_send_ipi( client_cxy , client_core->lid ); } sigaction_dmsg("\n[DBG] %s : exit after %s process %x / cycle %d\n", __FUNCTION__ , process_action_str( action ) , process->pid , (uint32_t)hal_get_cycles() ); } ///////////////////////////////////////////////////////////////////////////////////////// // [10] Marshaling functions attached to RPC_VFS_INODE_CREATE (blocking) ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////// void rpc_vfs_inode_create_client( cxy_t cxy, xptr_t dentry_xp, // in uint32_t fs_type, // in uint32_t inode_type, // in void * extend, // in uint32_t attr, // in uint32_t rights, // in uint32_t uid, // in uint32_t gid, // in xptr_t * inode_xp, // out error_t * error ) // out { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n"); // initialise RPC descriptor header rpc_desc_t rpc; rpc.index = RPC_VFS_INODE_CREATE; rpc.response = 1; rpc.blocking = true; // set input arguments in RPC descriptor rpc.args[0] = (uint64_t)dentry_xp; rpc.args[1] = (uint64_t)fs_type; rpc.args[2] = (uint64_t)inode_type; rpc.args[3] = (uint64_t)(intptr_t)extend; rpc.args[4] = (uint64_t)attr; rpc.args[5] = (uint64_t)rights; rpc.args[6] = (uint64_t)uid; rpc.args[7] = (uint64_t)gid; // register RPC request in remote RPC fifo (blocking function) rpc_send( cxy , &rpc ); // get output values from RPC descriptor *inode_xp = (xptr_t)rpc.args[8]; *error = (error_t)rpc.args[9]; rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////// void rpc_vfs_inode_create_server( xptr_t xp ) { xptr_t dentry_xp; uint32_t fs_type; uint32_t inode_type; void * extend; uint32_t attr; uint32_t rights; uint32_t uid; uint32_t gid; xptr_t inode_xp; error_t error; rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); // get client cluster identifier and pointer on RPC descriptor cxy_t client_cxy = (cxy_t)GET_CXY( xp ); rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); // get input arguments from client rpc descriptor dentry_xp = (xptr_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); fs_type = (uint32_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) ); inode_type = (uint32_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) ); extend = (void *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[3] ) ); attr = (uint32_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[4] ) ); rights = (uint32_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[5] ) ); uid = (uid_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[6] ) ); gid = (gid_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[7] ) ); // call local kernel function error = vfs_inode_create( dentry_xp, fs_type, inode_type, extend, attr, rights, uid, gid, &inode_xp ); // set output arguments hal_remote_swd( XPTR( client_cxy , &desc->args[8] ) , (uint64_t)inode_xp ); hal_remote_swd( XPTR( client_cxy , &desc->args[9] ) , (uint64_t)error ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////////////////////////////////////////////////// // [11] Marshaling functions attached to RPC_VFS_INODE_DESTROY (blocking) ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////// void rpc_vfs_inode_destroy_client( cxy_t cxy, struct vfs_inode_s * inode ) { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n"); // initialise RPC descriptor header rpc_desc_t rpc; rpc.index = RPC_VFS_INODE_DESTROY; rpc.response = 1; rpc.blocking = true; // set input arguments in RPC descriptor rpc.args[0] = (uint64_t)(intptr_t)inode; // register RPC request in remote RPC fifo (blocking function) rpc_send( cxy , &rpc ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ////////////////////////////////////////////// void rpc_vfs_inode_destroy_server( xptr_t xp ) { vfs_inode_t * inode; rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); // get client cluster identifier and pointer on RPC descriptor cxy_t client_cxy = (cxy_t)GET_CXY( xp ); rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); // get arguments "inode" from client RPC descriptor inode = (vfs_inode_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); // call local kernel function vfs_inode_destroy( inode ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////////////////////////////////////////////////// // [12] Marshaling functions attached to RPC_VFS_DENTRY_CREATE (blocking) ///////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// void rpc_vfs_dentry_create_client( cxy_t cxy, uint32_t type, // in char * name, // in struct vfs_inode_s * parent, // in xptr_t * dentry_xp, // out error_t * error ) // out { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n"); // initialise RPC descriptor header rpc_desc_t rpc; rpc.index = RPC_VFS_DENTRY_CREATE; rpc.response = 1; rpc.blocking = true; // set input arguments in RPC descriptor rpc.args[0] = (uint64_t)type; rpc.args[1] = (uint64_t)(intptr_t)name; rpc.args[2] = (uint64_t)(intptr_t)parent; // register RPC request in remote RPC fifo (blocking function) rpc_send( cxy , &rpc ); // get output values from RPC descriptor *dentry_xp = (xptr_t)rpc.args[3]; *error = (error_t)rpc.args[4]; rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ////////////////////////////////////////////// void rpc_vfs_dentry_create_server( xptr_t xp ) { uint32_t type; char * name; vfs_inode_t * parent; xptr_t dentry_xp; error_t error; char name_copy[CONFIG_VFS_MAX_NAME_LENGTH]; rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); // get client cluster identifier and pointer on RPC descriptor cxy_t client_cxy = (cxy_t)GET_CXY( xp ); rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); // get arguments "name", "type", and "parent" from client RPC descriptor type = (uint32_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); name = (char *)(intptr_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) ); parent = (vfs_inode_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) ); // makes a local copy of name hal_remote_strcpy( XPTR( local_cxy , name_copy ), XPTR( client_cxy , name ) ); // call local kernel function error = vfs_dentry_create( type, name_copy, parent, &dentry_xp ); // set output arguments hal_remote_swd( XPTR( client_cxy , &desc->args[3] ) , (uint64_t)dentry_xp ); hal_remote_swd( XPTR( client_cxy , &desc->args[4] ) , (uint64_t)error ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////////////////////////////////////////////////// // [13] Marshaling functions attached to RPC_VFS_DENTRY_DESTROY (blocking) ///////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////// void rpc_vfs_dentry_destroy_client( cxy_t cxy, vfs_dentry_t * dentry ) { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n"); // initialise RPC descriptor header rpc_desc_t rpc; rpc.index = RPC_VFS_DENTRY_DESTROY; rpc.response = 1; rpc.blocking = true; // set input arguments in RPC descriptor rpc.args[0] = (uint64_t)(intptr_t)dentry; // register RPC request in remote RPC fifo (blocking function) rpc_send( cxy , &rpc ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } /////////////////////////////////////////////// void rpc_vfs_dentry_destroy_server( xptr_t xp ) { vfs_dentry_t * dentry; rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); // get client cluster identifier and pointer on RPC descriptor cxy_t client_cxy = (cxy_t)GET_CXY( xp ); rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); // get arguments "dentry" from client RPC descriptor dentry = (vfs_dentry_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); // call local kernel function vfs_dentry_destroy( dentry ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////////////////////////////////////////////////// // [14] Marshaling functions attached to RPC_VFS_FILE_CREATE (blocking) ///////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// void rpc_vfs_file_create_client( cxy_t cxy, struct vfs_inode_s * inode, // in uint32_t file_attr, // in xptr_t * file_xp, // out error_t * error ) // out { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n"); // initialise RPC descriptor header rpc_desc_t rpc; rpc.index = RPC_VFS_FILE_CREATE; rpc.response = 1; rpc.blocking = true; // set input arguments in RPC descriptor rpc.args[0] = (uint64_t)(intptr_t)inode; rpc.args[1] = (uint64_t)file_attr; // register RPC request in remote RPC fifo (blocking function) rpc_send( cxy , &rpc ); // get output values from RPC descriptor *file_xp = (xptr_t)rpc.args[2]; *error = (error_t)rpc.args[3]; rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } //////////////////////////////////////////// void rpc_vfs_file_create_server( xptr_t xp ) { uint32_t file_attr; vfs_inode_t * inode; xptr_t file_xp; error_t error; rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); // get client cluster identifier and pointer on RPC descriptor cxy_t client_cxy = (cxy_t)GET_CXY( xp ); rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); // get arguments "file_attr" and "inode" from client RPC descriptor inode = (vfs_inode_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); file_attr = (uint32_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) ); // call local kernel function error = vfs_file_create( inode, file_attr, &file_xp ); // set output arguments hal_remote_swd( XPTR( client_cxy , &desc->args[2] ) , (uint64_t)file_xp ); hal_remote_swd( XPTR( client_cxy , &desc->args[3] ) , (uint64_t)error ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////////////////////////////////////////////////// // [15] Marshaling functions attached to RPC_VFS_FILE_DESTROY (blocking) ///////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////// void rpc_vfs_file_destroy_client( cxy_t cxy, vfs_file_t * file ) { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n"); // initialise RPC descriptor header rpc_desc_t rpc; rpc.index = RPC_VFS_FILE_DESTROY; rpc.response = 1; rpc.blocking = true; // set input arguments in RPC descriptor rpc.args[0] = (uint64_t)(intptr_t)file; // register RPC request in remote RPC fifo (blocking function) rpc_send( cxy , &rpc ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////// void rpc_vfs_file_destroy_server( xptr_t xp ) { vfs_file_t * file; rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); // get client cluster identifier and pointer on RPC descriptor cxy_t client_cxy = (cxy_t)GET_CXY( xp ); rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); // get arguments "dentry" from client RPC descriptor file = (vfs_file_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); // call local kernel function vfs_file_destroy( file ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////////////////////////////////////////////////// // [16] Marshaling functions attached to RPC_VFS_INODE_LOAD (blocking) ///////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////// void rpc_vfs_inode_load_client( cxy_t cxy, vfs_inode_t * parent_inode, // in char * name, // in xptr_t child_inode_xp, // in error_t * error ) // out { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n"); // initialise RPC descriptor header rpc_desc_t rpc; rpc.index = RPC_VFS_INODE_LOAD; rpc.response = 1; rpc.blocking = true; // set input arguments in RPC descriptor rpc.args[0] = (uint64_t)(intptr_t)parent_inode; rpc.args[1] = (uint64_t)(intptr_t)name; rpc.args[2] = (uint64_t)child_inode_xp; // register RPC request in remote RPC fifo (blocking function) rpc_send( cxy , &rpc ); // get output values from RPC descriptor *error = (error_t)rpc.args[3]; rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } /////////////////////////////////////////// void rpc_vfs_inode_load_server( xptr_t xp ) { error_t error; vfs_inode_t * parent; xptr_t child_xp; char * name; char name_copy[CONFIG_VFS_MAX_NAME_LENGTH]; rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); // get client cluster identifier and pointer on RPC descriptor cxy_t client_cxy = (cxy_t)GET_CXY( xp ); rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); // get arguments "parent", "name", and "child_xp" parent = (vfs_inode_t*)(intptr_t)hal_remote_lwd(XPTR(client_cxy , &desc->args[0])); name = (char*)(intptr_t) hal_remote_lwd(XPTR(client_cxy , &desc->args[1])); child_xp = (xptr_t) hal_remote_lwd(XPTR(client_cxy , &desc->args[2])); // get name local copy hal_remote_strcpy( XPTR( local_cxy , name_copy ) , XPTR( client_cxy , name ) ); // call the kernel function error = vfs_inode_load( parent , name_copy , child_xp ); // set output argument hal_remote_swd( XPTR( client_cxy , &desc->args[3] ) , (uint64_t)error ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////////////////////////////////////////////////// // [17] Marshaling functions attached to RPC_VFS_MAPPER_LOAD_ALL (blocking) ///////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////// void rpc_vfs_mapper_load_all_client( cxy_t cxy, vfs_inode_t * inode, // in error_t * error ) // out { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n"); // initialise RPC descriptor header rpc_desc_t rpc; rpc.index = RPC_VFS_MAPPER_LOAD_ALL; rpc.response = 1; rpc.blocking = true; // set input arguments in RPC descriptor rpc.args[0] = (uint64_t)(intptr_t)inode; // register RPC request in remote RPC fifo (blocking function) rpc_send( cxy , &rpc ); // get output values from RPC descriptor *error = (error_t)rpc.args[1]; rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } //////////////////////////////////////////////// void rpc_vfs_mapper_load_all_server( xptr_t xp ) { error_t error; vfs_inode_t * inode; rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); // get client cluster identifier and pointer on RPC descriptor cxy_t client_cxy = (cxy_t)GET_CXY( xp ); rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); // get arguments "parent", "name", and "child_xp" inode = (vfs_inode_t*)(intptr_t)hal_remote_lwd(XPTR(client_cxy , &desc->args[0])); // call the kernel function error = vfs_mapper_load_all( inode ); // set output argument hal_remote_swd( XPTR( client_cxy , &desc->args[1] ) , (uint64_t)error ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////////////////////////////////////////////////// // [18] Marshaling functions attached to RPC_FATFS_GET_CLUSTER (blocking) ///////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////// void rpc_fatfs_get_cluster_client( cxy_t cxy, mapper_t * mapper, // in uint32_t first, // in uint32_t index, // in uint32_t * cluster, // out error_t * error ) // out { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n"); // initialise RPC descriptor header rpc_desc_t rpc; rpc.index = RPC_FATFS_GET_CLUSTER; rpc.response = 1; rpc.blocking = true; // set input arguments in RPC descriptor rpc.args[0] = (uint64_t)(intptr_t)mapper; rpc.args[1] = (uint64_t)first; rpc.args[2] = (uint64_t)index; // register RPC request in remote RPC fifo rpc_send( cxy , &rpc ); // get output argument from rpc descriptor *cluster = (uint32_t)rpc.args[3]; *error = (error_t)rpc.args[4]; rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ////////////////////////////////////////////// void rpc_fatfs_get_cluster_server( xptr_t xp ) { mapper_t * mapper; uint32_t first; uint32_t index; uint32_t cluster; error_t error; rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); // get client cluster identifier and pointer on RPC descriptor cxy_t client_cxy = (cxy_t)GET_CXY( xp ); rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); // get input arguments mapper = (mapper_t *)(intptr_t)hal_remote_lpt( XPTR( client_cxy , &desc->args[0] ) ); first = (uint32_t) hal_remote_lw ( XPTR( client_cxy , &desc->args[1] ) ); index = (uint32_t) hal_remote_lw ( XPTR( client_cxy , &desc->args[2] ) ); // call the kernel function error = fatfs_get_cluster( mapper , first , index , &cluster ); // set output argument hal_remote_swd( XPTR( client_cxy , &desc->args[3] ) , (uint64_t)cluster ); hal_remote_swd( XPTR( client_cxy , &desc->args[4] ) , (uint64_t)error ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////////////////////////////////////////////////// // [20] Marshaling functions attached to RPC_VMM_GET_VSEG (blocking) ///////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////// void rpc_vmm_get_vseg_client( cxy_t cxy, process_t * process, // in intptr_t vaddr, // in xptr_t * vseg_xp, // out error_t * error ) // out { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n"); // initialise RPC descriptor header rpc_desc_t rpc; rpc.index = RPC_VMM_GET_VSEG; rpc.response = 1; rpc.blocking = true; // set input arguments in RPC descriptor rpc.args[0] = (uint64_t)(intptr_t)process; rpc.args[1] = (uint64_t)vaddr; // register RPC request in remote RPC fifo (blocking function) rpc_send( cxy , &rpc ); // get output argument from rpc descriptor *vseg_xp = rpc.args[2]; *error = (error_t)rpc.args[3]; rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////// void rpc_vmm_get_vseg_server( xptr_t xp ) { process_t * process; intptr_t vaddr; vseg_t * vseg_ptr; xptr_t vseg_xp; error_t error; rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); // get client cluster identifier and pointer on RPC descriptor cxy_t client_cxy = (cxy_t)GET_CXY( xp ); rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); // get input argument from client RPC descriptor process = (process_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); vaddr = (intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) ); // call local kernel function error = vmm_get_vseg( process , vaddr , &vseg_ptr ); // set output arguments to client RPC descriptor vseg_xp = XPTR( local_cxy , vseg_ptr ); hal_remote_swd( XPTR( client_cxy , &desc->args[2] ) , (uint64_t)vseg_xp ); hal_remote_swd( XPTR( client_cxy , &desc->args[3] ) , (uint64_t)error ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////////////////////////////////////////////////// // [21] Marshaling functions attached to RPC_VMM_GET_PTE (blocking) ///////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////// void rpc_vmm_get_pte_client( cxy_t cxy, process_t * process, // in vpn_t vpn, // in bool_t cow, // in uint32_t * attr, // out ppn_t * ppn, // out error_t * error ) // out { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n"); // initialise RPC descriptor header rpc_desc_t rpc; rpc.index = RPC_VMM_GET_PTE; rpc.response = 1; rpc.blocking = true; // set input arguments in RPC descriptor rpc.args[0] = (uint64_t)(intptr_t)process; rpc.args[1] = (uint64_t)vpn; rpc.args[2] = (uint64_t)cow; // register RPC request in remote RPC fifo (blocking function) rpc_send( cxy , &rpc ); // get output argument from rpc descriptor *attr = (uint32_t)rpc.args[3]; *ppn = (ppn_t)rpc.args[4]; *error = (error_t)rpc.args[5]; rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } //////////////////////////////////////// void rpc_vmm_get_pte_server( xptr_t xp ) { process_t * process; vpn_t vpn; bool_t cow; uint32_t attr; ppn_t ppn; error_t error; rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); // get client cluster identifier and pointer on RPC descriptor cxy_t client_cxy = (cxy_t)GET_CXY( xp ); rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); // get input argument "process" & "vpn" from client RPC descriptor process = (process_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); vpn = (vpn_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) ); cow = (bool_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) ); // call local kernel function error = vmm_get_pte( process , vpn , cow , &attr , &ppn ); // set output argument "attr" & "ppn" to client RPC descriptor hal_remote_swd( XPTR( client_cxy , &desc->args[3] ) , (uint64_t)attr ); hal_remote_swd( XPTR( client_cxy , &desc->args[4] ) , (uint64_t)ppn ); hal_remote_swd( XPTR( client_cxy , &desc->args[5] ) , (uint64_t)error ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////////////////////////////////////////////////// // [22] Marshaling functions attached to RPC_KCM_ALLOC (blocking) ///////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////// void rpc_kcm_alloc_client( cxy_t cxy, uint32_t kmem_type, // in xptr_t * buf_xp ) // out { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n"); // initialise RPC descriptor header rpc_desc_t rpc; rpc.index = RPC_THREAD_USER_CREATE; rpc.response = 1; rpc.blocking = true; // set input arguments in RPC descriptor rpc.args[0] = (uint64_t)kmem_type; // register RPC request in remote RPC fifo (blocking function) rpc_send( cxy , &rpc ); // get output arguments from RPC descriptor *buf_xp = (xptr_t)rpc.args[1]; rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ////////////////////////////////////// void rpc_kcm_alloc_server( xptr_t xp ) { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); // get client cluster identifier and pointer on RPC descriptor cxy_t client_cxy = (cxy_t)GET_CXY( xp ); rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); // get input argument "kmem_type" from client RPC descriptor uint32_t kmem_type = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); // allocates memory for kcm kmem_req_t req; req.type = kmem_type; req.flags = AF_ZERO; void * buf_ptr = kmem_alloc( &req ); // set output argument xptr_t buf_xp = XPTR( local_cxy , buf_ptr ); hal_remote_swd( XPTR( client_cxy , &desc->args[1] ) , (uint64_t)buf_xp ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////////////////////////////////////////////////// // [23] Marshaling functions attached to RPC_KCM_FREE (blocking) ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////// void rpc_kcm_free_client( cxy_t cxy, void * buf, // in uint32_t kmem_type ) // in { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n"); // initialise RPC descriptor header rpc_desc_t rpc; rpc.index = RPC_THREAD_USER_CREATE; rpc.response = 1; rpc.blocking = true; // set input arguments in RPC descriptor rpc.args[0] = (uint64_t)(intptr_t)buf; rpc.args[1] = (uint64_t)kmem_type; // register RPC request in remote RPC fifo (blocking function) rpc_send( cxy , &rpc ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////// void rpc_kcm_free_server( xptr_t xp ) { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); // get client cluster identifier and pointer on RPC descriptor cxy_t client_cxy = (cxy_t)GET_CXY( xp ); rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); // get input arguments "buf" and "kmem_type" from client RPC descriptor void * buf = (void *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); uint32_t kmem_type = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) ); // releases memory kmem_req_t req; req.type = kmem_type; req.ptr = buf; kmem_free( &req ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////////////////////////////////////////////////// // [24] Marshaling functions attached to RPC_MAPPER_MOVE_BUFFER ///////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////// void rpc_mapper_move_buffer_client( cxy_t cxy, mapper_t * mapper, // in bool_t to_buffer, // in bool_t is_user, // in uint32_t file_offset, // in uint64_t buffer, // in uint32_t size, // in error_t * error ) // out { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n"); // initialise RPC descriptor header rpc_desc_t rpc; rpc.index = RPC_MAPPER_MOVE_BUFFER; rpc.response = 1; rpc.blocking = true; // set input arguments in RPC descriptor rpc.args[0] = (uint64_t)(intptr_t)mapper; rpc.args[1] = (uint64_t)to_buffer; rpc.args[2] = (uint64_t)is_user; rpc.args[3] = (uint64_t)file_offset; rpc.args[4] = (uint64_t)buffer; rpc.args[5] = (uint64_t)size; // register RPC request in remote RPC fifo (blocking function) rpc_send( cxy , &rpc ); // get output values from RPC descriptor *error = (error_t)rpc.args[6]; rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } /////////////////////////////////////////////// void rpc_mapper_move_buffer_server( xptr_t xp ) { mapper_t * mapper; bool_t to_buffer; bool_t is_user; uint32_t file_offset; void * user_buffer; xptr_t kern_buffer; uint32_t size; error_t error; rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); // get client cluster identifier and pointer on RPC descriptor cxy_t client_cxy = (cxy_t)GET_CXY( xp ); rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); // get arguments from client RPC descriptor mapper = (mapper_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); to_buffer = hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) ); is_user = hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) ); file_offset = hal_remote_lwd( XPTR( client_cxy , &desc->args[3] ) ); size = hal_remote_lwd( XPTR( client_cxy , &desc->args[5] ) ); // call local kernel function if( is_user ) { user_buffer = (void *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[4] ) ); error = mapper_move_user( mapper, to_buffer, file_offset, user_buffer, size ); } else { kern_buffer = (xptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[4] ) ); error = mapper_move_kernel( mapper, to_buffer, file_offset, kern_buffer, size ); } // set output argument to client RPC descriptor hal_remote_swd( XPTR( client_cxy , &desc->args[6] ) , (uint64_t)error ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////////////////////////////////////////////////// // [25] Marshaling functions attached to RPC_MAPPER_GET_PAGE (blocking) ///////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////// void rpc_mapper_get_page_client( cxy_t cxy, struct mapper_s * mapper, // in uint32_t index, // in page_t ** page ) // out { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n"); // initialise RPC descriptor header rpc_desc_t rpc; rpc.index = RPC_MAPPER_GET_PAGE; rpc.response = 1; rpc.blocking = true; // set input arguments in RPC descriptor rpc.args[0] = (uint64_t)(intptr_t)mapper; rpc.args[1] = (uint64_t)index; // register RPC request in remote RPC fifo (blocking function) rpc_send( cxy , &rpc ); // get output values from RPC descriptor *page = (page_t *)(intptr_t)rpc.args[2]; rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } //////////////////////////////////////////// void rpc_mapper_get_page_server( xptr_t xp ) { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); // get client cluster identifier and pointer on RPC descriptor cxy_t cxy = (cxy_t)GET_CXY( xp ); rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); // get input arguments from client RPC descriptor mapper_t * mapper = (mapper_t *)(intptr_t)hal_remote_lwd( XPTR( cxy , &desc->args[0] ) ); uint32_t index = (uint32_t) hal_remote_lwd( XPTR( cxy , &desc->args[1] ) ); // call local pmem allocator page_t * page = mapper_get_page( mapper , index ); // set output arguments into client RPC descriptor hal_remote_swd( XPTR( cxy , &desc->args[1] ) , (uint64_t)(intptr_t)page ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////////////////////////////////////////////////// // [26] Marshaling functions attached to RPC_VMM_CREATE_VSEG (blocking) ///////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////// void rpc_vmm_create_vseg_client( cxy_t cxy, struct process_s * process, vseg_type_t type, intptr_t base, uint32_t size, uint32_t file_offset, uint32_t file_size, xptr_t mapper_xp, cxy_t vseg_cxy, struct vseg_s ** vseg ) { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n"); // initialise RPC descriptor header rpc_desc_t rpc; rpc.index = RPC_VMM_CREATE_VSEG; rpc.response = 1; rpc.blocking = true; // set input arguments in RPC descriptor rpc.args[0] = (uint64_t)(intptr_t)process; rpc.args[1] = (uint64_t)type; rpc.args[2] = (uint64_t)base; rpc.args[3] = (uint64_t)size; rpc.args[4] = (uint64_t)file_offset; rpc.args[5] = (uint64_t)file_size; rpc.args[6] = (uint64_t)mapper_xp; rpc.args[7] = (uint64_t)vseg_cxy; // register RPC request in remote RPC fifo (blocking function) rpc_send( cxy , &rpc ); // get output values from RPC descriptor *vseg = (vseg_t *)(intptr_t)rpc.args[8]; rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } //////////////////////////////////////////// void rpc_vmm_create_vseg_server( xptr_t xp ) { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); // get client cluster identifier and pointer on RPC descriptor cxy_t cxy = (cxy_t)GET_CXY( xp ); rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); // get input arguments from client RPC descriptor process_t * process = (process_t *)(intptr_t)hal_remote_lwd( XPTR(cxy , &desc->args[0])); vseg_type_t type = (vseg_type_t)(uint32_t)hal_remote_lwd( XPTR(cxy , &desc->args[1])); intptr_t base = (intptr_t) hal_remote_lwd( XPTR(cxy , &desc->args[2])); uint32_t size = (uint32_t) hal_remote_lwd( XPTR(cxy , &desc->args[3])); uint32_t file_offset = (uint32_t) hal_remote_lwd( XPTR(cxy , &desc->args[4])); uint32_t file_size = (uint32_t) hal_remote_lwd( XPTR(cxy , &desc->args[5])); xptr_t mapper_xp = (xptr_t) hal_remote_lwd( XPTR(cxy , &desc->args[6])); cxy_t vseg_cxy = (cxy_t)(uint32_t) hal_remote_lwd( XPTR(cxy , &desc->args[7])); // call local kernel function vseg_t * vseg = vmm_create_vseg( process, type, base, size, file_offset, file_size, mapper_xp, vseg_cxy ); // set output arguments into client RPC descriptor hal_remote_swd( XPTR( cxy , &desc->args[8] ) , (uint64_t)(intptr_t)vseg ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////////////////////////////////////////////////// // [27] Marshaling functions attached to RPC_SCHED_DISPLAY (blocking) ///////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////// void rpc_sched_display_client( cxy_t cxy, lid_t lid) { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n"); // initialise RPC descriptor header rpc_desc_t rpc; rpc.index = RPC_SCHED_DISPLAY; rpc.response = 1; rpc.blocking = true; // set input arguments in RPC descriptor rpc.args[0] = (uint64_t)lid; // register RPC request in remote RPC fifo (blocking function) rpc_send( cxy , &rpc ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ////////////////////////////////////////// void rpc_sched_display_server( xptr_t xp ) { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); // get client cluster identifier and pointer on RPC descriptor cxy_t cxy = (cxy_t)GET_CXY( xp ); rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); // get input arguments from client RPC descriptor lid_t lid = (lid_t)hal_remote_lwd( XPTR(cxy , &desc->args[0])); // call local kernel function sched_display( lid ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////////////////////////////////////////////////// // [28] Marshaling functions attached to RPC_VMM_SET_COW (blocking) ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////// void rpc_vmm_set_cow_client( cxy_t cxy, process_t * process ) { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n"); // initialise RPC descriptor header rpc_desc_t rpc; rpc.index = RPC_VMM_SET_COW; rpc.response = 1; rpc.blocking = true; // set input arguments in RPC descriptor rpc.args[0] = (uint64_t)(intptr_t)process; // register RPC request in remote RPC fifo (blocking function) rpc_send( cxy , &rpc ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } //////////////////////////////////////// void rpc_vmm_set_cow_server( xptr_t xp ) { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); process_t * process; // get client cluster identifier and pointer on RPC descriptor cxy_t cxy = (cxy_t)GET_CXY( xp ); rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); // get input arguments from client RPC descriptor process = (process_t *)(intptr_t)hal_remote_lwd( XPTR(cxy , &desc->args[0])); // call local kernel function vmm_set_cow( process ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } ///////////////////////////////////////////////////////////////////////////////////////// // [29] Marshaling functions attached to RPC_VMM_DISPLAY (blocking) ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////// void rpc_vmm_display_client( cxy_t cxy, process_t * process, bool_t detailed ) { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n"); // initialise RPC descriptor header rpc_desc_t rpc; rpc.index = RPC_VMM_DISPLAY; rpc.response = 1; rpc.blocking = true; // set input arguments in RPC descriptor rpc.args[0] = (uint64_t)(intptr_t)process; rpc.args[1] = (uint64_t)detailed; // register RPC request in remote RPC fifo (blocking function) rpc_send( cxy , &rpc ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); } //////////////////////////////////////// void rpc_vmm_display_server( xptr_t xp ) { rpc_dmsg("\n[DBG] %s : enter / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); process_t * process; bool_t detailed; // get client cluster identifier and pointer on RPC descriptor cxy_t cxy = (cxy_t)GET_CXY( xp ); rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); // get input arguments from client RPC descriptor process = (process_t *)(intptr_t)hal_remote_lwd( XPTR(cxy , &desc->args[0])); detailed = (bool_t) hal_remote_lwd( XPTR(cxy , &desc->args[1])); // call local kernel function vmm_display( process , detailed ); rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", __FUNCTION__ , CURRENT_THREAD->trdid , local_cxy, CURRENT_THREAD->core->lid , hal_time_stamp() ); }