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