/* * rpc.h - RPC related operations * * Authors Mohamed Karaoui (2015) * Alain Greiner (2016) * * Copyright (c) UPMC Sorbonne Universites * * This file is part of ALMOS-MK. * * ALMOS-MK 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-MK 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-MK; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _RPC_H_ #define _RPC_H_ #include #include #include #include #include #include #include /**********************************************************************************/ /************** structures for Remote Procedure Calls ****************************/ /**********************************************************************************/ /*********************************************************************************** * This enum defines all RPC indexes (must be consistent with array in rpc.c) **********************************************************************************/ typedef enum { RPC_PMEM_GET_PAGES = 0, RPC_PROCESS_PID_ALLOC = 1, RPC_PROCESS_MIGRATE = 2, RPC_THREAD_USER_CREATE = 3, RPC_VFAT_ALLOC_FAT_ENTRY = 4, RPC_VFAT_CLUSTER_COUNT = 5, RPC_VFS_LOOKUP_CHILD = 6, RPC_MAX_INDEX = 7 } rpc_index_t; /*********************************************************************************** * This structure defines the RPC descriptor **********************************************************************************/ typedef struct rpc_desc_s { rpc_index_t index; // index of requested RPC service volatile uint32_t response; // response valid when 0 uint64_t args[7]; // input/output arguments buffer } rpc_desc_t; /*********************************************************************************** * This structure defines the RPC fifo, the associated light lock, * and the intrumentation counter. **********************************************************************************/ typedef struct rpc_fifo_s { spinlock_t lock; // spinlock for the readers uint64_t count; // total number of received RPCs (instrumentation) remote_fifo_t fifo; // embedded remote fifo } rpc_fifo_t; /**********************************************************************************/ /******* Generic functions supporting RPCs : client side **************************/ /**********************************************************************************/ /*********************************************************************************** * This blocking function executes on the client core. * It puts one RPC extended pointer in the remote fifo. * It sends an IPI if fifo is empty, and waits until RPC response available. * The RPC descriptor must be allocated in the caller's stack * and initialised by the caller. Exit with a Panic message if remote fifo * is still full after (CONFIG_RPC_PUT_MAX_ITERATIONS) retries. * @ cxy : server cluster identifier * @ desc : local pointer on RPC descriptor in client cluster **********************************************************************************/ void rpc_send_sync( cxy_t cxy, rpc_desc_t * desc ); /*********************************************************************************** * This non blocking function is called by the scheduler of the client core * to detect RPC completion. * @ ptr : local pointer on the RPC descriptor in client cluster. * @ return true if the client thread must resume (RPC completed). **********************************************************************************/ static bool_t rpc_callback( void * ptr ); /**********************************************************************************/ /******* Generic functions supporting RPCs : server side **************************/ /**********************************************************************************/ /*********************************************************************************** * This function initialises the local RPC fifo and the lock protecting readers. * The number of slots is defined by the CONFIG_REMOTE_FIFO_SLOTS parameter. * Each slot contains an extended pointer on the RPC descriptor. * @ rf : pointer on the local RPC fifo. **********************************************************************************/ void rpc_fifo_init( rpc_fifo_t * rf ); /*********************************************************************************** * This function is the entry point for RPC handling on the server side. * It can be executed by any thread running (in kernel mode) on any CPU. * It first checks the CPU private RPC fifo, an then the cluster shared RPC fifo. * It calls the rpc_activate_thread() function to activate a dedicated RPC thread, * after registration of the selected RPC fifo in the selected thread descriptor. * @ returns true if at least one RPC found / false otherwise. **********************************************************************************/ bool_t rpc_check(); /*********************************************************************************** * This function contains the loop to execute all pending RPCs on the server side. * It should be called with irq disabled and after light lock acquisition. * @ rpc_fifo : pointer on the local RPC fifo * @ returns 0 if success **********************************************************************************/ error_r rpc_execute_all( rpc_fifo_t * rpc_fifo ); /*********************************************************************************** * This function is acting as a demultiplexor on the server side. * Depending on the RPC index stored in the RPC descriptor, * it calls the relevant rpc_*_server() function. * @ xptr : extended pointer on the RPC descriptor. **********************************************************************************/ void rpc_handle( xptr_t * xp ); /********************************************************************************** * This function activates one RPC thread to handle the pending RPC(s) contained * in one RPC fifo (shared or private). It is called by any thread detecting * a non-empty RPC fifo. * It gets the first free RPC thread from the free-list, or creates a new one * if the RPC thread free-list associated to the current cpu is empty. * Finally, the calling thread immediately switches to the RPC thread. * @ rpc_fifo : pointer on the non-empty RPC fifo. * @ return 0 if success / return ENOMEM if error. **********************************************************************************/ error_t rpc_activate_thread( rpc_fifo_t * rpc_fifo ); /*********************************************************************************** * This function defines the infinite loop executed by each RPC thread. **********************************************************************************/ void * rpc_thread(); /********************************************************************************** * This call-back function must be registered in the RPC thread descriptor. * It is executed by the scheduler when the thread makes a sched_sleep() call, * when the "before_sleep" field in thread descriptor is not NULL. * It releases the light lock and print a debug message. * @ thread : local pointer on thread. **********************************************************************************/ void rpc_before_sleep( thread_t * thread ); /********************************************************************************** * This call-back function must be registered in the RPC thread descriptor. * It is executed by the scheduler when the thread makes a wakeup(), * when the "after_wakeup" field in thread descriptor is not NULL. * It print a debug message. * @ thread : local pointer on thread. **********************************************************************************/ void rpc_after_wakeup( thread_t * thread ); /**********************************************************************************/ /******* Marshalling functions attached to the various RPCs ***********************/ /**********************************************************************************/ /*********************************************************************************** * The RPC_PMEM_GET_PAGES allocates one or several pages in a remote cluster, * and returns the PPN of the first allocated page. * @ cxy : server cluster identifier * @ order : [in] ln2( number of requested pages ) * @ status : [out] error status (0 if success) * @ ppn : [out] first physical page number **********************************************************************************/ void rpc_pmem_get_pages_client( cxy_t cxy, uint32_t order, uint32_t * status, uint32_t * ppn ); void rpc_pmem_get_pages_server( xptr_t xp ); /*********************************************************************************** * The RPC_PROCESS_PID_ALLOC allocates one new PID in a remote cluster, registers * the new process in the remote cluster, and returns the PID, and an error code. * @ cxy : server cluster identifier. * @ process : [in] pointer on process descriptor in client cluster. * @ status : [out] error status (0 if success). * @ pid : [out] new process identifier. **********************************************************************************/ void rpc_process_pid_alloc_client( cxy_t cxy, process_t * process, error_t * status, pid_t * pid ); void rpc_process_pid_alloc_server( xptr_t xp ); /*********************************************************************************** * The RPC_PROCESS_MIGRATE creates a process descriptor copy, in a remote cluster * and initializes if from information found in the reference process descriptor. * This remote cluster becomes the new reference cluster. * @ cxy : server cluster identifier. * @ xp_ref : [in] extended pointer on reference process descriptor. * @ status : [out] error status (0 if success). **********************************************************************************/ void rpc_process_migrate_client( cxy_t cxy, xptr_t xp_ref, error_t * status ); void rpc_process_migrate_server( xptr_t xp ); /*********************************************************************************** * The RPC_VFS_LOOKUP_CHILD returns in the lpr structure information on the * the inode identified by the dentry name and the lkp structure. * @ cxy : server cluster identifier * @ lkp : [in] pointer on input structure in client cluster * @ name : [in] dentry name * @ lpr : [out] pointer on output structure in client cluster **********************************************************************************/ void rpc_vfs_lookup_child_client( cxy_t cxy, vfs_lookup_t * lkp, char * name, vfs_lookup_response_t * lpr ); void rpc_vfs_lookup_child_server( xptr_t xp ); /*********************************************************************************** * The RPC_THREAD_USER_CREATE creates an user thread in the server cluster, * as specified by the pthread_attr_t argument. It returns an extended pointer * on the thread descriptor in server cluster and an error code. * @ cxy : server cluster identifier. * @ attr : [in] pointer on pthread_attr_t in client cluster. * @ error : [out] error status (0 if success). * @ thread : [out] extended pointer on thread descriptor. **********************************************************************************/ void rpc_thread_user_create_client( cxy_t cxy, pthread_attr_t * attr, error_t * error, xptr_t * new_thread ); void rpc_thread_user_create_server( xptr_t xp ); #endif