1 /* 2 * Copyright (c) 2023 Institute of Parallel And Distributed Systems (IPADS), Shanghai Jiao Tong University (SJTU) 3 * Licensed under the Mulan PSL v2. 4 * You can use this software according to the terms and conditions of the Mulan PSL v2. 5 * You may obtain a copy of Mulan PSL v2 at: 6 * http://license.coscl.org.cn/MulanPSL2 7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR 8 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR 9 * PURPOSE. 10 * See the Mulan PSL v2 for more details. 11 */ 12 13 #pragma once 14 15 #include <chcore/type.h> 16 #include <chcore/defs.h> 17 18 #ifdef __cplusplus 19 extern "C" { 20 #endif 21 22 /* Starts from 1 because the uninitialized value is 0 */ 23 enum system_server_identifier { 24 FS_MANAGER = 1, 25 NET_MANAGER, 26 PROC_MANAGER, 27 }; 28 29 /* 30 * ipc_struct is created in **ipc_register_client** and 31 * thus only used at client side. 32 */ 33 typedef struct ipc_struct { 34 /* Connection_cap: used to call a server */ 35 cap_t conn_cap; 36 /* Shared memory: used to create ipc_msg (client -> server) */ 37 unsigned long shared_buf; 38 unsigned long shared_buf_len; 39 40 /* A spin lock: used to coordinate the access to shared memory */ 41 volatile int lock; 42 enum system_server_identifier server_id; 43 } ipc_struct_t; 44 45 extern cap_t fsm_server_cap; 46 extern cap_t lwip_server_cap; 47 extern cap_t procmgr_server_cap; 48 extern int init_process_in_lwip; 49 extern int init_lwip_lock; 50 51 /* ipc_struct for invoking system servers. 52 * fsm_ipc_struct and lwip_ipc_struct are two addresses. 53 * They can be used like **const** pointers. 54 * 55 * If a system server is related to the scalability (multi-threads) of 56 * applications, we should use the following way to make the connection with it 57 * as per-thread. 58 * 59 * For other system servers (e.g., process manager), it is OK to let multiple 60 * threads share a same connection. 61 */ 62 ipc_struct_t *__fsm_ipc_struct_location(void); 63 ipc_struct_t *__net_ipc_struct_location(void); 64 ipc_struct_t *__procmgr_ipc_struct_location(void); 65 #define fsm_ipc_struct (__fsm_ipc_struct_location()) 66 #define lwip_ipc_struct (__net_ipc_struct_location()) 67 #define procmgr_ipc_struct (__procmgr_ipc_struct_location()) 68 69 /* ipc_msg is located at ipc_struct->shared_buf. */ 70 typedef struct ipc_msg { 71 unsigned int data_len; 72 /* 73 * cap_slot_number represents the number of caps of the ipc_msg. 74 * This is useful for both sending IPC and returning from IPC. 75 * When calling ipc_return, cap_slot_number will be set 0 automatically, 76 * indicating that no cap will be sent. 77 * If you want to send caps when returning from IPC, 78 * use ipc_return_with_cap. 79 */ 80 unsigned int cap_slot_number; 81 unsigned int data_offset; 82 unsigned int cap_slots_offset; 83 84 /* icb: ipc control block (not needed by the kernel) */ 85 ipc_struct_t *icb; 86 87 #if __SIZEOF_POINTER__ == 4 88 /* ipc_msg should be alligned to 8 bytes */ 89 void *padding; 90 #endif 91 } ipc_msg_t; 92 93 #define IPC_SHM_AVAILABLE (IPC_PER_SHM_SIZE - sizeof(ipc_msg_t)) 94 95 /* 96 * server_handler is an IPC routine (can have two arguments): 97 * first is ipc_msg and second is client_badge. 98 */ 99 typedef void (*server_handler)(); 100 typedef void (*server_destructor)(badge_t); 101 102 /* Registeration interfaces */ 103 ipc_struct_t *ipc_register_client(cap_t server_thread_cap); 104 105 void *register_cb(void *ipc_handler); 106 void *register_cb_single(void *ipc_handler); 107 108 #define DEFAULT_CLIENT_REGISTER_HANDLER register_cb 109 #define DEFAULT_DESTRUCTOR NULL 110 111 int ipc_register_server(server_handler server_handler, 112 void *(*client_register_handler)(void *)); 113 int ipc_register_server_with_destructor(server_handler server_handler, 114 void *(*client_register_handler)(void *), 115 server_destructor server_destructor); 116 117 /* IPC message operating interfaces */ 118 ipc_msg_t *ipc_create_msg(ipc_struct_t *icb, unsigned int data_len); 119 ipc_msg_t *ipc_create_msg_with_cap(ipc_struct_t *icb, unsigned int data_len, 120 unsigned int cap_slot_number); 121 char *ipc_get_msg_data(ipc_msg_t *ipc_msg); 122 cap_t ipc_get_msg_cap(ipc_msg_t *ipc_msg, unsigned int cap_id); 123 int ipc_set_msg_data(ipc_msg_t *ipc_msg, void *data, unsigned int offset, 124 unsigned int len); 125 int ipc_set_msg_cap(ipc_msg_t *ipc_msg, unsigned int cap_slot_index, cap_t cap); 126 int ipc_destroy_msg(ipc_msg_t *ipc_msg); 127 128 /* IPC issue/finish interfaces */ 129 long ipc_call(ipc_struct_t *icb, ipc_msg_t *ipc_msg); 130 _Noreturn void ipc_return(ipc_msg_t *ipc_msg, long ret); 131 _Noreturn void ipc_return_with_cap(ipc_msg_t *ipc_msg, long ret); 132 int ipc_client_close_connection(ipc_struct_t *ipc_struct); 133 134 int simple_ipc_forward(ipc_struct_t *ipc_struct, void *data, int len); 135 136 /* 137 * Magic number for coordination between client and server: 138 * the client should wait until the server has reigsterd the service. 139 */ 140 #define NONE_INFO ((void *)(-1UL)) 141 142 #ifdef __cplusplus 143 } 144 #endif 145