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