1 /* Reincarnation Server. This servers starts new system services and detects 2 * they are exiting. In case of errors, system services can be restarted. 3 * The RS server periodically checks the status of all registered services 4 * services to see whether they are still alive. The system services are 5 * expected to periodically send a heartbeat message. 6 * 7 * Changes: 8 * Nov 22, 2009: rewrite of boot process (Cristiano Giuffrida) 9 * Jul 22, 2005: Created (Jorrit N. Herder) 10 */ 11 #include "inc.h" 12 #include <fcntl.h> 13 #include "kernel/const.h" 14 #include "kernel/type.h" 15 #include "kernel/proc.h" 16 17 /* Declare some local functions. */ 18 static void boot_image_info_lookup( endpoint_t endpoint, struct 19 boot_image *image, struct boot_image **ip, struct boot_image_priv **pp, 20 struct boot_image_sys **sp, struct boot_image_dev **dp); 21 static void catch_boot_init_ready(endpoint_t endpoint); 22 static void get_work(message *m_ptr, int *status_ptr); 23 24 /* SEF functions and variables. */ 25 static void sef_local_startup(void); 26 static int sef_cb_init_fresh(int type, sef_init_info_t *info); 27 static int sef_cb_init_restart(int type, sef_init_info_t *info); 28 static int sef_cb_init_lu(int type, sef_init_info_t *info); 29 static int sef_cb_init_response(message *m_ptr); 30 static int sef_cb_lu_response(message *m_ptr); 31 static void sef_cb_signal_handler(int signo); 32 static int sef_cb_signal_manager(endpoint_t target, int signo); 33 34 35 /*===========================================================================* 36 * main * 37 *===========================================================================*/ 38 int main(void) 39 { 40 /* This is the main routine of this service. The main loop consists of 41 * three major activities: getting new work, processing the work, and 42 * sending the reply. The loop never terminates, unless a panic occurs. 43 */ 44 message m; /* request message */ 45 int ipc_status; /* status code */ 46 int call_nr, who_e,who_p; /* call number and caller */ 47 int result; /* result to return */ 48 int s; 49 50 /* SEF local startup. */ 51 sef_local_startup(); 52 53 if (OK != (s=sys_getmachine(&machine))) 54 panic("couldn't get machine info: %d", s); 55 56 /* Main loop - get work and do it, forever. */ 57 while (TRUE) { 58 /* Perform sensitive background operations when RS is idle. */ 59 rs_idle_period(); 60 61 /* Wait for request message. */ 62 get_work(&m, &ipc_status); 63 who_e = m.m_source; 64 if(rs_isokendpt(who_e, &who_p) != OK) { 65 panic("message from bogus source: %d", who_e); 66 } 67 68 call_nr = m.m_type; 69 70 /* Now determine what to do. Four types of requests are expected: 71 * - Heartbeat messages (notifications from registered system services) 72 * - System notifications (synchronous alarm) 73 * - User requests (control messages to manage system services) 74 * - Ready messages (reply messages from registered services) 75 */ 76 77 /* Notification messages are control messages and do not need a reply. 78 * These include heartbeat messages and system notifications. 79 */ 80 if (is_ipc_notify(ipc_status)) { 81 switch (who_p) { 82 case CLOCK: 83 do_period(&m); /* check services status */ 84 continue; 85 default: /* heartbeat notification */ 86 if (rproc_ptr[who_p] != NULL) { /* mark heartbeat time */ 87 rproc_ptr[who_p]->r_alive_tm = m.m_notify.timestamp; 88 } else { 89 printf("RS: warning: got unexpected notify message from %d\n", 90 m.m_source); 91 } 92 } 93 } 94 95 /* If we get this far, this is a normal request. 96 * Handle the request and send a reply to the caller. 97 */ 98 else { 99 /* Handler functions are responsible for permission checking. */ 100 switch(call_nr) { 101 /* User requests. */ 102 case RS_UP: result = do_up(&m); break; 103 case RS_DOWN: result = do_down(&m); break; 104 case RS_REFRESH: result = do_refresh(&m); break; 105 case RS_RESTART: result = do_restart(&m); break; 106 case RS_SHUTDOWN: result = do_shutdown(&m); break; 107 case RS_UPDATE: result = do_update(&m); break; 108 case RS_CLONE: result = do_clone(&m); break; 109 case RS_UNCLONE: result = do_unclone(&m); break; 110 case RS_EDIT: result = do_edit(&m); break; 111 case RS_SYSCTL: result = do_sysctl(&m); break; 112 case RS_FI: result = do_fi(&m); break; 113 case RS_GETSYSINFO: result = do_getsysinfo(&m); break; 114 case RS_LOOKUP: result = do_lookup(&m); break; 115 /* Ready messages. */ 116 case RS_INIT: result = do_init_ready(&m); break; 117 case RS_LU_PREPARE: result = do_upd_ready(&m); break; 118 default: 119 printf("RS: warning: got unexpected request %d from %d\n", 120 m.m_type, m.m_source); 121 result = ENOSYS; 122 } 123 124 /* Finally send reply message, unless disabled. */ 125 if (result != EDONTREPLY) { 126 m.m_type = result; 127 reply(who_e, NULL, &m); 128 } 129 } 130 } 131 } 132 133 /*===========================================================================* 134 * sef_local_startup * 135 *===========================================================================*/ 136 static void sef_local_startup() 137 { 138 /* Register init callbacks. */ 139 sef_setcb_init_fresh(sef_cb_init_fresh); 140 sef_setcb_init_restart(sef_cb_init_restart); 141 sef_setcb_init_lu(sef_cb_init_lu); 142 143 /* Register response callbacks. */ 144 sef_setcb_init_response(sef_cb_init_response); 145 sef_setcb_lu_response(sef_cb_lu_response); 146 147 /* Register signal callbacks. */ 148 sef_setcb_signal_handler(sef_cb_signal_handler); 149 sef_setcb_signal_manager(sef_cb_signal_manager); 150 151 /* Let SEF perform startup. */ 152 sef_startup(); 153 } 154 155 /*===========================================================================* 156 * sef_cb_init_fresh * 157 *===========================================================================*/ 158 static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info)) 159 { 160 /* Initialize the reincarnation server. */ 161 struct boot_image *ip; 162 int s,i; 163 int nr_image_srvs, nr_image_priv_srvs, nr_uncaught_init_srvs; 164 struct rproc *rp; 165 struct rproc *replica_rp; 166 struct rprocpub *rpub; 167 struct boot_image image[NR_BOOT_PROCS]; 168 struct boot_image_priv *boot_image_priv; 169 struct boot_image_sys *boot_image_sys; 170 struct boot_image_dev *boot_image_dev; 171 int pid, replica_pid; 172 endpoint_t replica_endpoint; 173 int ipc_to; 174 int *calls; 175 int all_c[] = { ALL_C, NULL_C }; 176 int no_c[] = { NULL_C }; 177 178 /* See if we run in verbose mode. */ 179 env_parse("rs_verbose", "d", 0, &rs_verbose, 0, 1); 180 181 if ((s = sys_getinfo(GET_HZ, &system_hz, sizeof(system_hz), 0, 0)) != OK) 182 panic("Cannot get system timer frequency\n"); 183 184 /* Initialize the global init descriptor. */ 185 rinit.rproctab_gid = cpf_grant_direct(ANY, (vir_bytes) rprocpub, 186 sizeof(rprocpub), CPF_READ); 187 if(!GRANT_VALID(rinit.rproctab_gid)) { 188 panic("unable to create rprocpub table grant: %d", rinit.rproctab_gid); 189 } 190 191 /* Initialize some global variables. */ 192 RUPDATE_INIT(); 193 shutting_down = FALSE; 194 195 /* Get a copy of the boot image table. */ 196 if ((s = sys_getimage(image)) != OK) { 197 panic("unable to get copy of boot image table: %d", s); 198 } 199 200 /* Determine the number of system services in the boot image table. */ 201 nr_image_srvs = 0; 202 for(i=0;i<NR_BOOT_PROCS;i++) { 203 ip = &image[i]; 204 205 /* System services only. */ 206 if(iskerneln(_ENDPOINT_P(ip->endpoint))) { 207 continue; 208 } 209 nr_image_srvs++; 210 } 211 212 /* Determine the number of entries in the boot image priv table and make sure 213 * it matches the number of system services in the boot image table. 214 */ 215 nr_image_priv_srvs = 0; 216 for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) { 217 boot_image_priv = &boot_image_priv_table[i]; 218 219 /* System services only. */ 220 if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) { 221 continue; 222 } 223 nr_image_priv_srvs++; 224 } 225 if(nr_image_srvs != nr_image_priv_srvs) { 226 panic("boot image table and boot image priv table mismatch"); 227 } 228 229 /* Reset the system process table. */ 230 for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) { 231 rp->r_flags = 0; 232 rp->r_init_err = ERESTART; 233 rp->r_pub = &rprocpub[rp - rproc]; 234 rp->r_pub->in_use = FALSE; 235 rp->r_pub->old_endpoint = NONE; 236 rp->r_pub->new_endpoint = NONE; 237 } 238 239 /* Initialize the system process table in 4 steps, each of them following 240 * the appearance of system services in the boot image priv table. 241 * - Step 1: set priviliges, sys properties, and dev properties (if any) 242 * for every system service. 243 */ 244 for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) { 245 boot_image_priv = &boot_image_priv_table[i]; 246 247 /* System services only. */ 248 if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) { 249 continue; 250 } 251 252 /* Lookup the corresponding entries in other tables. */ 253 boot_image_info_lookup(boot_image_priv->endpoint, image, 254 &ip, NULL, &boot_image_sys, &boot_image_dev); 255 rp = &rproc[boot_image_priv - boot_image_priv_table]; 256 rpub = rp->r_pub; 257 258 /* 259 * Set privileges. 260 */ 261 /* Get label. */ 262 strcpy(rpub->label, boot_image_priv->label); 263 264 /* Force a static priv id for system services in the boot image. */ 265 rp->r_priv.s_id = static_priv_id( 266 _ENDPOINT_P(boot_image_priv->endpoint)); 267 268 /* Initialize privilege bitmaps and signal manager. */ 269 rp->r_priv.s_flags = boot_image_priv->flags; /* priv flags */ 270 rp->r_priv.s_init_flags = SRV_OR_USR(rp, SRV_I, USR_I); /* init flags */ 271 rp->r_priv.s_trap_mask= SRV_OR_USR(rp, SRV_T, USR_T); /* traps */ 272 ipc_to = SRV_OR_USR(rp, SRV_M, USR_M); /* targets */ 273 fill_send_mask(&rp->r_priv.s_ipc_to, ipc_to == ALL_M); 274 rp->r_priv.s_sig_mgr= SRV_OR_USR(rp, SRV_SM, USR_SM); /* sig mgr */ 275 rp->r_priv.s_bak_sig_mgr = NONE; /* backup sig mgr */ 276 277 /* Initialize kernel call mask bitmap. */ 278 calls = SRV_OR_USR(rp, SRV_KC, USR_KC) == ALL_C ? all_c : no_c; 279 fill_call_mask(calls, NR_SYS_CALLS, 280 rp->r_priv.s_k_call_mask, KERNEL_CALL, TRUE); 281 282 /* Set the privilege structure. RS and VM are exceptions and are already 283 * running. 284 */ 285 if(boot_image_priv->endpoint != RS_PROC_NR && 286 boot_image_priv->endpoint != VM_PROC_NR) { 287 if ((s = sys_privctl(ip->endpoint, SYS_PRIV_SET_SYS, &(rp->r_priv))) 288 != OK) { 289 panic("unable to set privilege structure: %d", s); 290 } 291 } 292 293 /* Synch the privilege structure with the kernel. */ 294 if ((s = sys_getpriv(&(rp->r_priv), ip->endpoint)) != OK) { 295 panic("unable to synch privilege structure: %d", s); 296 } 297 298 /* 299 * Set sys properties. 300 */ 301 rpub->sys_flags = boot_image_sys->flags; /* sys flags */ 302 303 /* 304 * Set dev properties. 305 */ 306 rpub->dev_nr = boot_image_dev->dev_nr; /* major device number */ 307 308 /* Build command settings. Also set the process name. */ 309 strlcpy(rp->r_cmd, ip->proc_name, sizeof(rp->r_cmd)); 310 rp->r_script[0]= '\0'; 311 build_cmd_dep(rp); 312 313 strlcpy(rpub->proc_name, ip->proc_name, sizeof(rpub->proc_name)); 314 315 /* Initialize vm call mask bitmap. */ 316 calls = SRV_OR_USR(rp, SRV_VC, USR_VC) == ALL_C ? all_c : no_c; 317 fill_call_mask(calls, NR_VM_CALLS, rpub->vm_call_mask, VM_RQ_BASE, TRUE); 318 319 /* Scheduling parameters. */ 320 rp->r_scheduler = SRV_OR_USR(rp, SRV_SCH, USR_SCH); 321 rp->r_priority = SRV_OR_USR(rp, SRV_Q, USR_Q); 322 rp->r_quantum = SRV_OR_USR(rp, SRV_QT, USR_QT); 323 324 /* Get some settings from the boot image table. */ 325 rpub->endpoint = ip->endpoint; 326 327 /* Set some defaults. */ 328 rp->r_old_rp = NULL; /* no old version yet */ 329 rp->r_new_rp = NULL; /* no new version yet */ 330 rp->r_prev_rp = NULL; /* no prev replica yet */ 331 rp->r_next_rp = NULL; /* no next replica yet */ 332 rp->r_uid = 0; /* root */ 333 rp->r_check_tm = 0; /* not checked yet */ 334 rp->r_alive_tm = getticks(); /* currently alive */ 335 rp->r_stop_tm = 0; /* not exiting yet */ 336 rp->r_asr_count = 0; /* no ASR updates yet */ 337 rp->r_restarts = 0; /* no restarts so far */ 338 rp->r_period = 0; /* no period yet */ 339 rp->r_exec = NULL; /* no in-memory copy yet */ 340 rp->r_exec_len = 0; 341 342 /* Mark as in use and active. */ 343 rp->r_flags = RS_IN_USE | RS_ACTIVE; 344 rproc_ptr[_ENDPOINT_P(rpub->endpoint)]= rp; 345 rpub->in_use = TRUE; 346 } 347 348 /* - Step 2: allow every system service in the boot image to run. */ 349 nr_uncaught_init_srvs = 0; 350 for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) { 351 boot_image_priv = &boot_image_priv_table[i]; 352 353 /* System services only. */ 354 if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) { 355 continue; 356 } 357 358 /* Lookup the corresponding slot in the system process table. */ 359 rp = &rproc[boot_image_priv - boot_image_priv_table]; 360 rpub = rp->r_pub; 361 362 /* RS/VM are already running as we speak. */ 363 if(boot_image_priv->endpoint == RS_PROC_NR || 364 boot_image_priv->endpoint == VM_PROC_NR) { 365 if ((s = init_service(rp, SEF_INIT_FRESH, rp->r_priv.s_init_flags)) != OK) { 366 panic("unable to initialize %d: %d", boot_image_priv->endpoint, s); 367 } 368 /* VM will still send an RS_INIT message, though. */ 369 if (boot_image_priv->endpoint != RS_PROC_NR) { 370 nr_uncaught_init_srvs++; 371 } 372 continue; 373 } 374 375 /* Allow the service to run. */ 376 if ((s = sched_init_proc(rp)) != OK) { 377 panic("unable to initialize scheduling: %d", s); 378 } 379 if ((s = sys_privctl(rpub->endpoint, SYS_PRIV_ALLOW, NULL)) != OK) { 380 panic("unable to initialize privileges: %d", s); 381 } 382 383 /* Initialize service. We assume every service will always get 384 * back to us here at boot time. 385 */ 386 if(boot_image_priv->flags & SYS_PROC) { 387 if ((s = init_service(rp, SEF_INIT_FRESH, rp->r_priv.s_init_flags)) != OK) { 388 panic("unable to initialize service: %d", s); 389 } 390 if(rpub->sys_flags & SF_SYNCH_BOOT) { 391 /* Catch init ready message now to synchronize. */ 392 catch_boot_init_ready(rpub->endpoint); 393 } 394 else { 395 /* Catch init ready message later. */ 396 nr_uncaught_init_srvs++; 397 } 398 } 399 } 400 401 /* - Step 3: let every system service complete initialization by 402 * catching all the init ready messages left. 403 */ 404 while(nr_uncaught_init_srvs) { 405 catch_boot_init_ready(ANY); 406 nr_uncaught_init_srvs--; 407 } 408 409 /* - Step 4: all the system services in the boot image are now running. 410 * Complete the initialization of the system process table in collaboration 411 * with other system services. 412 */ 413 for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) { 414 boot_image_priv = &boot_image_priv_table[i]; 415 416 /* System services only. */ 417 if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) { 418 continue; 419 } 420 421 /* Lookup the corresponding slot in the system process table. */ 422 rp = &rproc[boot_image_priv - boot_image_priv_table]; 423 rpub = rp->r_pub; 424 425 /* Get pid from PM. */ 426 rp->r_pid = getnpid(rpub->endpoint); 427 if(rp->r_pid < 0) { 428 panic("unable to get pid: %d", rp->r_pid); 429 } 430 } 431 432 /* Set alarm to periodically check service status. */ 433 if (OK != (s=sys_setalarm(RS_DELTA_T, 0))) 434 panic("couldn't set alarm: %d", s); 435 436 #if USE_LIVEUPDATE 437 /* Now create a new RS instance and let the current 438 * instance live update into the replica. Clone RS' own slot first. 439 */ 440 rp = rproc_ptr[_ENDPOINT_P(RS_PROC_NR)]; 441 if((s = clone_slot(rp, &replica_rp)) != OK) { 442 panic("unable to clone current RS instance: %d", s); 443 } 444 445 /* Fork a new RS instance with root:wheel. */ 446 pid = srv_fork(0, 0); 447 if(pid < 0) { 448 panic("unable to fork a new RS instance: %d", pid); 449 } 450 replica_pid = pid ? pid : getpid(); 451 if ((s = getprocnr(replica_pid, &replica_endpoint)) != 0) 452 panic("unable to get replica endpoint: %d", s); 453 replica_rp->r_pid = replica_pid; 454 replica_rp->r_pub->endpoint = replica_endpoint; 455 456 if(pid == 0) { 457 /* New RS instance running. */ 458 459 /* Live update the old instance into the new one. */ 460 s = update_service(&rp, &replica_rp, RS_SWAP, 0); 461 if(s != OK) { 462 panic("unable to live update RS: %d", s); 463 } 464 cpf_reload(); 465 466 /* Clean up the old RS instance, the new instance will take over. */ 467 cleanup_service(rp); 468 469 /* Ask VM to pin memory for the new RS instance. */ 470 if((s = vm_memctl(RS_PROC_NR, VM_RS_MEM_PIN, 0, 0)) != OK) { 471 panic("unable to pin memory for the new RS instance: %d", s); 472 } 473 } 474 else { 475 /* Old RS instance running. */ 476 477 /* Set up privileges for the new instance and let it run. */ 478 s = sys_privctl(replica_endpoint, SYS_PRIV_SET_SYS, &(replica_rp->r_priv)); 479 if(s != OK) { 480 panic("unable to set privileges for the new RS instance: %d", s); 481 } 482 if ((s = sched_init_proc(replica_rp)) != OK) { 483 panic("unable to initialize RS replica scheduling: %d", s); 484 } 485 s = sys_privctl(replica_endpoint, SYS_PRIV_YIELD, NULL); 486 if(s != OK) { 487 panic("unable to yield control to the new RS instance: %d", s); 488 } 489 NOT_REACHABLE; 490 } 491 #endif /* USE_LIVEUPDATE */ 492 493 return(OK); 494 } 495 496 /*===========================================================================* 497 * sef_cb_init_restart * 498 *===========================================================================*/ 499 static int sef_cb_init_restart(int type, sef_init_info_t *info) 500 { 501 /* Restart the reincarnation server. */ 502 int r; 503 struct rproc *old_rs_rp, *new_rs_rp; 504 505 assert(info->endpoint == RS_PROC_NR); 506 507 /* Perform default state transfer first. */ 508 r = SEF_CB_INIT_RESTART_STATEFUL(type, info); 509 if(r != OK) { 510 printf("SEF_CB_INIT_RESTART_STATEFUL failed: %d\n", r); 511 return r; 512 } 513 514 /* New RS takes over. */ 515 old_rs_rp = rproc_ptr[_ENDPOINT_P(RS_PROC_NR)]; 516 new_rs_rp = rproc_ptr[_ENDPOINT_P(info->old_endpoint)]; 517 if(rs_verbose) 518 printf("RS: %s is the new RS after restart\n", srv_to_string(new_rs_rp)); 519 520 /* If an update was in progress, end it. */ 521 if(SRV_IS_UPDATING(old_rs_rp)) { 522 end_update(ERESTART, RS_REPLY); 523 } 524 525 /* Update the service into the replica. */ 526 r = update_service(&old_rs_rp, &new_rs_rp, RS_DONTSWAP, 0); 527 if(r != OK) { 528 printf("update_service failed: %d\n", r); 529 return r; 530 } 531 532 /* Initialize the new RS instance. */ 533 r = init_service(new_rs_rp, SEF_INIT_RESTART, 0); 534 if(r != OK) { 535 printf("init_service failed: %d\n", r); 536 return r; 537 } 538 539 /* Reschedule a synchronous alarm for the next period. */ 540 if (OK != (r=sys_setalarm(RS_DELTA_T, 0))) 541 panic("couldn't set alarm: %d", r); 542 543 return OK; 544 } 545 546 /*===========================================================================* 547 * sef_cb_init_lu * 548 *===========================================================================*/ 549 static int sef_cb_init_lu(int type, sef_init_info_t *info) 550 { 551 /* Start a new version of the reincarnation server. */ 552 int r; 553 struct rproc *old_rs_rp, *new_rs_rp; 554 555 assert(info->endpoint == RS_PROC_NR); 556 557 /* Perform default state transfer first. */ 558 sef_setcb_init_restart(SEF_CB_INIT_RESTART_STATEFUL); 559 r = SEF_CB_INIT_LU_DEFAULT(type, info); 560 if(r != OK) { 561 printf("SEF_CB_INIT_LU_DEFAULT failed: %d\n", r); 562 return r; 563 } 564 565 /* New RS takes over. */ 566 old_rs_rp = rproc_ptr[_ENDPOINT_P(RS_PROC_NR)]; 567 new_rs_rp = rproc_ptr[_ENDPOINT_P(info->old_endpoint)]; 568 if(rs_verbose) 569 printf("RS: %s is the new RS after live update\n", 570 srv_to_string(new_rs_rp)); 571 572 /* Update the service into the replica. */ 573 r = update_service(&old_rs_rp, &new_rs_rp, RS_DONTSWAP, 0); 574 if(r != OK) { 575 printf("update_service failed: %d\n", r); 576 return r; 577 } 578 579 /* Check if everything is as expected. */ 580 assert(RUPDATE_IS_UPDATING()); 581 assert(RUPDATE_IS_INITIALIZING()); 582 assert(rupdate.num_rpupds > 0); 583 assert(rupdate.num_init_ready_pending > 0); 584 585 return OK; 586 } 587 588 /*===========================================================================* 589 * sef_cb_init_response * 590 *===========================================================================*/ 591 int sef_cb_init_response(message *m_ptr) 592 { 593 int r; 594 595 /* Return now if RS initialization failed. */ 596 r = m_ptr->m_rs_init.result; 597 if(r != OK) { 598 return r; 599 } 600 601 /* Simulate an RS-to-RS init message. */ 602 r = do_init_ready(m_ptr); 603 604 /* Assume everything is OK if EDONTREPLY was returned. */ 605 if(r == EDONTREPLY) { 606 r = OK; 607 } 608 return r; 609 } 610 611 /*===========================================================================* 612 * sef_cb_lu_response * 613 *===========================================================================*/ 614 int sef_cb_lu_response(message *m_ptr) 615 { 616 int r; 617 618 /* Simulate an RS-to-RS update ready message. */ 619 r = do_upd_ready(m_ptr); 620 621 /* If we get this far, we didn't get updated for some reason. Report error. */ 622 if(r == EDONTREPLY) { 623 r = EGENERIC; 624 } 625 return r; 626 } 627 628 /*===========================================================================* 629 * sef_cb_signal_handler * 630 *===========================================================================*/ 631 static void sef_cb_signal_handler(int signo) 632 { 633 /* Check for known signals, ignore anything else. */ 634 switch(signo) { 635 case SIGCHLD: 636 do_sigchld(); 637 break; 638 case SIGTERM: 639 do_shutdown(NULL); 640 break; 641 } 642 } 643 644 /*===========================================================================* 645 * sef_cb_signal_manager * 646 *===========================================================================*/ 647 static int sef_cb_signal_manager(endpoint_t target, int signo) 648 { 649 /* Process system signal on behalf of the kernel. */ 650 int target_p; 651 struct rproc *rp; 652 message m; 653 654 /* Lookup slot. */ 655 if(rs_isokendpt(target, &target_p) != OK || rproc_ptr[target_p] == NULL) { 656 if(rs_verbose) 657 printf("RS: ignoring spurious signal %d for process %d\n", 658 signo, target); 659 return OK; /* clear the signal */ 660 } 661 rp = rproc_ptr[target_p]; 662 663 /* Don't bother if a termination signal has already been processed. */ 664 if((rp->r_flags & RS_TERMINATED) && !(rp->r_flags & RS_EXITING)) { 665 return EDEADEPT; /* process is gone */ 666 } 667 668 /* Ignore external signals for inactive service instances. */ 669 if( !(rp->r_flags & RS_ACTIVE) && !(rp->r_flags & RS_EXITING)) { 670 if(rs_verbose) 671 printf("RS: ignoring signal %d for inactive %s\n", 672 signo, srv_to_string(rp)); 673 return OK; /* clear the signal */ 674 } 675 676 if(rs_verbose) 677 printf("RS: %s got %s signal %d\n", srv_to_string(rp), 678 SIGS_IS_TERMINATION(signo) ? "termination" : "non-termination",signo); 679 680 /* Print stacktrace if necessary. */ 681 if(SIGS_IS_STACKTRACE(signo)) { 682 sys_diagctl_stacktrace(target); 683 } 684 685 /* In case of termination signal handle the event. */ 686 if(SIGS_IS_TERMINATION(signo)) { 687 rp->r_flags |= RS_TERMINATED; 688 terminate_service(rp); 689 rs_idle_period(); 690 691 return EDEADEPT; /* process is now gone */ 692 } 693 /* Never deliver signals to VM. */ 694 if (rp->r_pub->endpoint == VM_PROC_NR) { 695 return OK; 696 } 697 698 /* Translate every non-termination signal into a message. */ 699 m.m_type = SIGS_SIGNAL_RECEIVED; 700 m.m_pm_lsys_sigs_signal.num = signo; 701 rs_asynsend(rp, &m, 1); 702 703 return OK; /* signal has been delivered */ 704 } 705 706 /*===========================================================================* 707 * boot_image_info_lookup * 708 *===========================================================================*/ 709 static void boot_image_info_lookup(endpoint, image, ip, pp, sp, dp) 710 endpoint_t endpoint; 711 struct boot_image *image; 712 struct boot_image **ip; 713 struct boot_image_priv **pp; 714 struct boot_image_sys **sp; 715 struct boot_image_dev **dp; 716 { 717 /* Lookup entries in boot image tables. */ 718 int i; 719 720 /* When requested, locate the corresponding entry in the boot image table 721 * or panic if not found. 722 */ 723 if(ip) { 724 for (i=0; i < NR_BOOT_PROCS; i++) { 725 if(image[i].endpoint == endpoint) { 726 *ip = &image[i]; 727 break; 728 } 729 } 730 if(i == NR_BOOT_PROCS) { 731 panic("boot image table lookup failed"); 732 } 733 } 734 735 /* When requested, locate the corresponding entry in the boot image priv table 736 * or panic if not found. 737 */ 738 if(pp) { 739 for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) { 740 if(boot_image_priv_table[i].endpoint == endpoint) { 741 *pp = &boot_image_priv_table[i]; 742 break; 743 } 744 } 745 if(i == NULL_BOOT_NR) { 746 panic("boot image priv table lookup failed"); 747 } 748 } 749 750 /* When requested, locate the corresponding entry in the boot image sys table 751 * or resort to the default entry if not found. 752 */ 753 if(sp) { 754 for (i=0; boot_image_sys_table[i].endpoint != DEFAULT_BOOT_NR; i++) { 755 if(boot_image_sys_table[i].endpoint == endpoint) { 756 *sp = &boot_image_sys_table[i]; 757 break; 758 } 759 } 760 if(boot_image_sys_table[i].endpoint == DEFAULT_BOOT_NR) { 761 *sp = &boot_image_sys_table[i]; /* accept the default entry */ 762 } 763 } 764 765 /* When requested, locate the corresponding entry in the boot image dev table 766 * or resort to the default entry if not found. 767 */ 768 if(dp) { 769 for (i=0; boot_image_dev_table[i].endpoint != DEFAULT_BOOT_NR; i++) { 770 if(boot_image_dev_table[i].endpoint == endpoint) { 771 *dp = &boot_image_dev_table[i]; 772 break; 773 } 774 } 775 if(boot_image_dev_table[i].endpoint == DEFAULT_BOOT_NR) { 776 *dp = &boot_image_dev_table[i]; /* accept the default entry */ 777 } 778 } 779 } 780 781 /*===========================================================================* 782 * catch_boot_init_ready * 783 *===========================================================================*/ 784 static void catch_boot_init_ready(endpoint) 785 endpoint_t endpoint; 786 { 787 /* Block and catch an init ready message from the given source. */ 788 int r; 789 int ipc_status; 790 message m; 791 struct rproc *rp; 792 int result; 793 794 /* Receive init ready message. */ 795 if ((r = sef_receive_status(endpoint, &m, &ipc_status)) != OK) { 796 panic("unable to receive init reply: %d", r); 797 } 798 if(m.m_type != RS_INIT) { 799 panic("unexpected reply from service: %d", m.m_source); 800 } 801 result = m.m_rs_init.result; 802 rp = rproc_ptr[_ENDPOINT_P(m.m_source)]; 803 804 /* Check result. */ 805 if(result != OK) { 806 panic("unable to complete init for service: %d", m.m_source); 807 } 808 809 /* Send a reply to unblock the service, except to VM, which sent the reply 810 * asynchronously. Synchronous replies could lead to deadlocks there. 811 */ 812 if (m.m_source != VM_PROC_NR) { 813 m.m_type = OK; 814 reply(m.m_source, rp, &m); 815 } 816 817 /* Mark the slot as no longer initializing. */ 818 rp->r_flags &= ~RS_INITIALIZING; 819 rp->r_check_tm = 0; 820 rp->r_alive_tm = getticks(); 821 } 822 823 /*===========================================================================* 824 * get_work * 825 *===========================================================================*/ 826 static void get_work(m_ptr, status_ptr) 827 message *m_ptr; /* pointer to message */ 828 int *status_ptr; /* pointer to status */ 829 { 830 int r; 831 if (OK != (r=sef_receive_status(ANY, m_ptr, status_ptr))) 832 panic("sef_receive_status failed: %d", r); 833 } 834 835