1 #include "syslib.h" 2 #include <assert.h> 3 #include <minix/sysutil.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <unistd.h> 7 #include <string.h> 8 9 /* Self variables. */ 10 #define SEF_SELF_NAME_MAXLEN 20 11 char sef_self_name[SEF_SELF_NAME_MAXLEN]; 12 endpoint_t sef_self_endpoint = NONE; 13 int sef_self_priv_flags; 14 int sef_self_first_receive_done; 15 int sef_self_receiving; 16 17 /* Debug. */ 18 #if SEF_INIT_DEBUG || SEF_LU_DEBUG || SEF_PING_DEBUG || SEF_SIGNAL_DEBUG 19 #define SEF_DEBUG_HEADER_MAXLEN 32 20 static int sef_debug_init = 0; 21 static time_t sef_debug_boottime = 0; 22 static u32_t sef_debug_system_hz = 0; 23 static time_t sef_debug_time_sec = 0; 24 static time_t sef_debug_time_us = 0; 25 static char sef_debug_header_buff[SEF_DEBUG_HEADER_MAXLEN]; 26 static void sef_debug_refresh_params(void); 27 char* sef_debug_header(void); 28 #endif 29 30 /* SEF Init prototypes. */ 31 EXTERN int do_sef_rs_init(endpoint_t old_endpoint); 32 EXTERN int do_sef_init_request(message *m_ptr); 33 34 /* SEF Ping prototypes. */ 35 EXTERN int do_sef_ping_request(message *m_ptr); 36 37 /* SEF Live update prototypes. */ 38 EXTERN void do_sef_lu_before_receive(void); 39 EXTERN int do_sef_lu_request(message *m_ptr); 40 41 /* SEF Signal prototypes. */ 42 EXTERN int do_sef_signal_request(message *m_ptr); 43 44 /* SEF GCOV prototypes. */ 45 #ifdef USE_COVERAGE 46 EXTERN int do_sef_gcov_request(message *m_ptr); 47 #endif 48 49 /* SEF Fault Injection prototypes. */ 50 EXTERN int do_sef_fi_request(message *m_ptr); 51 52 /*===========================================================================* 53 * sef_startup * 54 *===========================================================================*/ 55 void sef_startup() 56 { 57 /* SEF startup interface for system services. */ 58 int r, status; 59 endpoint_t old_endpoint; 60 int priv_flags; 61 62 /* Get information about self. */ 63 r = sys_whoami(&sef_self_endpoint, sef_self_name, SEF_SELF_NAME_MAXLEN, 64 &priv_flags); 65 if ( r != OK) { 66 sef_self_endpoint = SELF; 67 strlcpy(sef_self_name, "Unknown", sizeof(sef_self_name)); 68 } 69 sef_self_priv_flags = priv_flags; 70 old_endpoint = NONE; 71 72 #if USE_LIVEUPDATE 73 /* RS may wake up with the wrong endpoint, perfom the update in that case. */ 74 if((sef_self_priv_flags & ROOT_SYS_PROC) && sef_self_endpoint != RS_PROC_NR) { 75 r = vm_update(RS_PROC_NR, sef_self_endpoint); 76 if(r != OK) { 77 panic("unable to update RS from instance %d to %d: %d", 78 RS_PROC_NR, sef_self_endpoint, r); 79 } 80 old_endpoint = sef_self_endpoint; 81 sef_self_endpoint = RS_PROC_NR; 82 } 83 #endif /* USE_LIVEUPDATE */ 84 85 #if INTERCEPT_SEF_INIT_REQUESTS 86 /* Intercept SEF Init requests. */ 87 if(sef_self_priv_flags & ROOT_SYS_PROC) { 88 /* RS initialization is special. */ 89 if((r = do_sef_rs_init(old_endpoint)) != OK) { 90 panic("RS unable to complete init: %d", r); 91 } 92 } 93 else if(sef_self_endpoint == VM_PROC_NR) { 94 /* VM handles initialization by RS later */ 95 } else { 96 message m; 97 98 /* Wait for an initialization message from RS. We need this to learn the 99 * initialization type and parameters. When restarting after a crash, we 100 * may get some spurious IPC messages from RS (e.g. update request) that 101 * were originally meant to be delivered to the old instance. We discard 102 * these messages and block till a proper initialization request arrives. 103 */ 104 do { 105 r = ipc_receive(RS_PROC_NR, &m, &status); 106 if(r != OK) { 107 panic("unable to ipc_receive from RS: %d", r); 108 } 109 } while(!IS_SEF_INIT_REQUEST(&m)); 110 111 /* Process initialization request for this system service. */ 112 if((r = do_sef_init_request(&m)) != OK) { 113 panic("unable to process init request: %d", r); 114 } 115 } 116 #endif 117 118 /* (Re)initialize SEF variables. */ 119 sef_self_first_receive_done = FALSE; 120 sef_self_priv_flags = priv_flags; 121 } 122 123 /*===========================================================================* 124 * sef_receive_status * 125 *===========================================================================*/ 126 int sef_receive_status(endpoint_t src, message *m_ptr, int *status_ptr) 127 { 128 /* SEF receive() interface for system services. */ 129 int r, status; 130 131 sef_self_receiving = TRUE; 132 133 while(TRUE) { 134 /* If the caller indicated that it no longer wants to receive a message, 135 * return now. 136 */ 137 if (!sef_self_receiving) 138 return EINTR; 139 140 #if INTERCEPT_SEF_LU_REQUESTS 141 /* Handle SEF Live update before receive events. */ 142 do_sef_lu_before_receive(); 143 #endif 144 145 /* Receive and return in case of error. */ 146 r = ipc_receive(src, m_ptr, &status); 147 if(status_ptr) *status_ptr = status; 148 if(!sef_self_first_receive_done) sef_self_first_receive_done = TRUE; 149 if(r != OK) { 150 return r; 151 } 152 153 #if INTERCEPT_SEF_PING_REQUESTS 154 /* Intercept SEF Ping requests. */ 155 if(IS_SEF_PING_REQUEST(m_ptr, status)) { 156 if(do_sef_ping_request(m_ptr) == OK) { 157 continue; 158 } 159 } 160 #endif 161 162 #if INTERCEPT_SEF_LU_REQUESTS 163 /* Intercept SEF Live update requests. */ 164 if(IS_SEF_LU_REQUEST(m_ptr, status)) { 165 if(do_sef_lu_request(m_ptr) == OK) { 166 continue; 167 } 168 } 169 #endif 170 171 #if INTERCEPT_SEF_SIGNAL_REQUESTS 172 /* Intercept SEF Signal requests. */ 173 if(IS_SEF_SIGNAL_REQUEST(m_ptr, status)) { 174 if(do_sef_signal_request(m_ptr) == OK) { 175 continue; 176 } 177 } 178 #endif 179 180 #ifdef USE_COVERAGE 181 /* Intercept GCOV data requests (sent by VFS in vfs/gcov.c). */ 182 if(m_ptr->m_type == COMMON_REQ_GCOV_DATA && 183 m_ptr->m_source == VFS_PROC_NR) { 184 if(do_sef_gcov_request(m_ptr) == OK) { 185 continue; 186 } 187 } 188 #endif 189 190 #ifdef INTERCEPT_SEF_FI_REQUESTS 191 /* Intercept Fault injection requests. */ 192 if(IS_SEF_FI_REQUEST(m_ptr, status)) { 193 if(do_sef_fi_request(m_ptr) == OK) { 194 continue; 195 } 196 } 197 #endif 198 199 /* If we get this far, this is not a valid SEF request, return and 200 * let the caller deal with that. 201 */ 202 break; 203 } 204 205 return r; 206 } 207 208 /*===========================================================================* 209 * sef_self * 210 *===========================================================================*/ 211 endpoint_t sef_self(void) 212 { 213 /* Return the process's own endpoint number. */ 214 215 if (sef_self_endpoint == NONE) 216 panic("sef_self called before initialization"); 217 218 return sef_self_endpoint; 219 } 220 221 /*===========================================================================* 222 * sef_cancel * 223 *===========================================================================*/ 224 void sef_cancel(void) 225 { 226 /* Cancel receiving a message. This function be called from a callback invoked 227 * from within sef_receive_status(), which will then return an EINTR error 228 * code. In particular, this function can be used to exit from the main receive 229 * loop when a signal handler causes the process to want to shut down. 230 */ 231 232 sef_self_receiving = FALSE; 233 } 234 235 /*===========================================================================* 236 * sef_exit * 237 *===========================================================================*/ 238 void sef_exit(int status) 239 { 240 /* System services use a special version of exit() that generates a 241 * self-termination signal. 242 */ 243 244 /* Ask the kernel to exit. */ 245 sys_exit(); 246 247 /* If everything else fails, hang. */ 248 printf("Warning: system service %d couldn't exit\n", sef_self_endpoint); 249 for(;;) { } 250 } 251 252 #ifdef __weak_alias 253 __weak_alias(_exit, sef_exit); 254 __weak_alias(__exit, sef_exit); 255 #endif 256 257 #if SEF_INIT_DEBUG || SEF_LU_DEBUG || SEF_PING_DEBUG || SEF_SIGNAL_DEBUG 258 /*===========================================================================* 259 * sef_debug_refresh_params * 260 *===========================================================================*/ 261 static void sef_debug_refresh_params(void) 262 { 263 /* Refresh SEF debug params. */ 264 clock_t uptime; 265 266 /* Get boottime and system hz the first time. */ 267 if(!sef_debug_init) { 268 if (sys_times(NONE, NULL, NULL, NULL, &sef_debug_boottime) != OK) 269 sef_debug_init = -1; 270 else if (sys_getinfo(GET_HZ, &sef_debug_system_hz, 271 sizeof(sef_debug_system_hz), 0, 0) != OK) 272 sef_debug_init = -1; 273 else 274 sef_debug_init = 1; 275 } 276 277 /* Get uptime. */ 278 uptime = -1; 279 if (sef_debug_init < 1 || sys_times(NONE, NULL, NULL, &uptime, NULL) != OK) { 280 sef_debug_time_sec = 0; 281 sef_debug_time_us = 0; 282 } 283 else { 284 /* Compute current time. */ 285 sef_debug_time_sec = (time_t) (sef_debug_boottime 286 + (uptime/sef_debug_system_hz)); 287 sef_debug_time_us = (uptime%sef_debug_system_hz) 288 * 1000000/sef_debug_system_hz; 289 } 290 } 291 292 /*===========================================================================* 293 * sef_debug_header * 294 *===========================================================================*/ 295 char* sef_debug_header(void) 296 { 297 /* Build and return a SEF debug header. */ 298 sef_debug_refresh_params(); 299 snprintf(sef_debug_header_buff, sizeof(sef_debug_header_buff), 300 "%s: time = %ds %06dus", sef_self_name, (int) sef_debug_time_sec, 301 (int) sef_debug_time_us); 302 303 return sef_debug_header_buff; 304 } 305 #endif /*SEF_INIT_DEBUG || SEF_LU_DEBUG || SEF_PING_DEBUG || SEF_SIGNAL_DEBUG*/ 306 307