Remove building with NOCRYPTO option
[minix3.git] / minix / servers / rs / main.c
blobf2391a1774871328e5a3880cb1aa1bb7a58474c1
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)
11 #include "inc.h"
12 #include <fcntl.h>
13 #include "kernel/const.h"
14 #include "kernel/type.h"
15 #include "kernel/proc.h"
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);
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);
35 /*===========================================================================*
36 * main *
37 *===========================================================================*/
38 int main(void)
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.
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;
50 /* SEF local startup. */
51 sef_local_startup();
53 if (OK != (s=sys_getmachine(&machine)))
54 panic("couldn't get machine info: %d", s);
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();
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);
68 call_nr = m.m_type;
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)
77 /* Notification messages are control messages and do not need a reply.
78 * These include heartbeat messages and system notifications.
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);
95 /* If we get this far, this is a normal request.
96 * Handle the request and send a reply to the caller.
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;
124 /* Finally send reply message, unless disabled. */
125 if (result != EDONTREPLY) {
126 m.m_type = result;
127 reply(who_e, NULL, &m);
133 /*===========================================================================*
134 * sef_local_startup *
135 *===========================================================================*/
136 static void sef_local_startup()
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);
143 /* Register response callbacks. */
144 sef_setcb_init_response(sef_cb_init_response);
145 sef_setcb_lu_response(sef_cb_lu_response);
147 /* Register signal callbacks. */
148 sef_setcb_signal_handler(sef_cb_signal_handler);
149 sef_setcb_signal_manager(sef_cb_signal_manager);
151 /* Let SEF perform startup. */
152 sef_startup();
155 /*===========================================================================*
156 * sef_cb_init_fresh *
157 *===========================================================================*/
158 static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
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 };
178 /* See if we run in verbose mode. */
179 env_parse("rs_verbose", "d", 0, &rs_verbose, 0, 1);
181 if ((s = sys_getinfo(GET_HZ, &system_hz, sizeof(system_hz), 0, 0)) != OK)
182 panic("Cannot get system timer frequency\n");
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);
191 /* Initialize some global variables. */
192 RUPDATE_INIT();
193 shutting_down = FALSE;
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);
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];
205 /* System services only. */
206 if(iskerneln(_ENDPOINT_P(ip->endpoint))) {
207 continue;
209 nr_image_srvs++;
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.
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];
219 /* System services only. */
220 if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) {
221 continue;
223 nr_image_priv_srvs++;
225 if(nr_image_srvs != nr_image_priv_srvs) {
226 panic("boot image table and boot image priv table mismatch");
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;
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.
244 for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
245 boot_image_priv = &boot_image_priv_table[i];
247 /* System services only. */
248 if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) {
249 continue;
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;
259 * Set privileges.
261 /* Get label. */
262 strcpy(rpub->label, boot_image_priv->label);
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));
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 */
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);
282 /* Set the privilege structure. RS and VM are exceptions and are already
283 * running.
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);
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);
299 * Set sys properties.
301 rpub->sys_flags = boot_image_sys->flags; /* sys flags */
304 * Set dev properties.
306 rpub->dev_nr = boot_image_dev->dev_nr; /* major device number */
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);
313 strlcpy(rpub->proc_name, ip->proc_name, sizeof(rpub->proc_name));
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);
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);
324 /* Get some settings from the boot image table. */
325 rpub->endpoint = ip->endpoint;
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;
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;
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];
353 /* System services only. */
354 if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) {
355 continue;
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;
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);
368 /* VM will still send an RS_INIT message, though. */
369 if (boot_image_priv->endpoint != RS_PROC_NR) {
370 nr_uncaught_init_srvs++;
372 continue;
375 /* Allow the service to run. */
376 if ((s = sched_init_proc(rp)) != OK) {
377 panic("unable to initialize scheduling: %d", s);
379 if ((s = sys_privctl(rpub->endpoint, SYS_PRIV_ALLOW, NULL)) != OK) {
380 panic("unable to initialize privileges: %d", s);
383 /* Initialize service. We assume every service will always get
384 * back to us here at boot time.
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);
390 if(rpub->sys_flags & SF_SYNCH_BOOT) {
391 /* Catch init ready message now to synchronize. */
392 catch_boot_init_ready(rpub->endpoint);
394 else {
395 /* Catch init ready message later. */
396 nr_uncaught_init_srvs++;
401 /* - Step 3: let every system service complete initialization by
402 * catching all the init ready messages left.
404 while(nr_uncaught_init_srvs) {
405 catch_boot_init_ready(ANY);
406 nr_uncaught_init_srvs--;
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.
413 for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
414 boot_image_priv = &boot_image_priv_table[i];
416 /* System services only. */
417 if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) {
418 continue;
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;
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);
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);
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.
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);
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);
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;
456 if(pid == 0) {
457 /* New RS instance running. */
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);
464 cpf_reload();
466 /* Clean up the old RS instance, the new instance will take over. */
467 cleanup_service(rp);
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);
474 else {
475 /* Old RS instance running. */
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);
482 if ((s = sched_init_proc(replica_rp)) != OK) {
483 panic("unable to initialize RS replica scheduling: %d", s);
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);
489 NOT_REACHABLE;
491 #endif /* USE_LIVEUPDATE */
493 return(OK);
496 /*===========================================================================*
497 * sef_cb_init_restart *
498 *===========================================================================*/
499 static int sef_cb_init_restart(int type, sef_init_info_t *info)
501 /* Restart the reincarnation server. */
502 int r;
503 struct rproc *old_rs_rp, *new_rs_rp;
505 assert(info->endpoint == RS_PROC_NR);
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;
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));
520 /* If an update was in progress, end it. */
521 if(SRV_IS_UPDATING(old_rs_rp)) {
522 end_update(ERESTART, RS_REPLY);
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;
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;
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);
543 return OK;
546 /*===========================================================================*
547 * sef_cb_init_lu *
548 *===========================================================================*/
549 static int sef_cb_init_lu(int type, sef_init_info_t *info)
551 /* Start a new version of the reincarnation server. */
552 int r;
553 struct rproc *old_rs_rp, *new_rs_rp;
555 assert(info->endpoint == RS_PROC_NR);
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;
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));
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;
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);
585 return OK;
588 /*===========================================================================*
589 * sef_cb_init_response *
590 *===========================================================================*/
591 int sef_cb_init_response(message *m_ptr)
593 int r;
595 /* Return now if RS initialization failed. */
596 r = m_ptr->m_rs_init.result;
597 if(r != OK) {
598 return r;
601 /* Simulate an RS-to-RS init message. */
602 r = do_init_ready(m_ptr);
604 /* Assume everything is OK if EDONTREPLY was returned. */
605 if(r == EDONTREPLY) {
606 r = OK;
608 return r;
611 /*===========================================================================*
612 * sef_cb_lu_response *
613 *===========================================================================*/
614 int sef_cb_lu_response(message *m_ptr)
616 int r;
618 /* Simulate an RS-to-RS update ready message. */
619 r = do_upd_ready(m_ptr);
621 /* If we get this far, we didn't get updated for some reason. Report error. */
622 if(r == EDONTREPLY) {
623 r = EGENERIC;
625 return r;
628 /*===========================================================================*
629 * sef_cb_signal_handler *
630 *===========================================================================*/
631 static void sef_cb_signal_handler(int signo)
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;
644 /*===========================================================================*
645 * sef_cb_signal_manager *
646 *===========================================================================*/
647 static int sef_cb_signal_manager(endpoint_t target, int signo)
649 /* Process system signal on behalf of the kernel. */
650 int target_p;
651 struct rproc *rp;
652 message m;
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 */
661 rp = rproc_ptr[target_p];
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 */
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 */
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);
680 /* Print stacktrace if necessary. */
681 if(SIGS_IS_STACKTRACE(signo)) {
682 sys_diagctl_stacktrace(target);
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();
691 return EDEADEPT; /* process is now gone */
693 /* Never deliver signals to VM. */
694 if (rp->r_pub->endpoint == VM_PROC_NR) {
695 return OK;
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);
703 return OK; /* signal has been delivered */
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;
717 /* Lookup entries in boot image tables. */
718 int i;
720 /* When requested, locate the corresponding entry in the boot image table
721 * or panic if not found.
723 if(ip) {
724 for (i=0; i < NR_BOOT_PROCS; i++) {
725 if(image[i].endpoint == endpoint) {
726 *ip = &image[i];
727 break;
730 if(i == NR_BOOT_PROCS) {
731 panic("boot image table lookup failed");
735 /* When requested, locate the corresponding entry in the boot image priv table
736 * or panic if not found.
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;
745 if(i == NULL_BOOT_NR) {
746 panic("boot image priv table lookup failed");
750 /* When requested, locate the corresponding entry in the boot image sys table
751 * or resort to the default entry if not found.
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;
760 if(boot_image_sys_table[i].endpoint == DEFAULT_BOOT_NR) {
761 *sp = &boot_image_sys_table[i]; /* accept the default entry */
765 /* When requested, locate the corresponding entry in the boot image dev table
766 * or resort to the default entry if not found.
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;
775 if(boot_image_dev_table[i].endpoint == DEFAULT_BOOT_NR) {
776 *dp = &boot_image_dev_table[i]; /* accept the default entry */
781 /*===========================================================================*
782 * catch_boot_init_ready *
783 *===========================================================================*/
784 static void catch_boot_init_ready(endpoint)
785 endpoint_t endpoint;
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;
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);
798 if(m.m_type != RS_INIT) {
799 panic("unexpected reply from service: %d", m.m_source);
801 result = m.m_rs_init.result;
802 rp = rproc_ptr[_ENDPOINT_P(m.m_source)];
804 /* Check result. */
805 if(result != OK) {
806 panic("unable to complete init for service: %d", m.m_source);
809 /* Send a reply to unblock the service, except to VM, which sent the reply
810 * asynchronously. Synchronous replies could lead to deadlocks there.
812 if (m.m_source != VM_PROC_NR) {
813 m.m_type = OK;
814 reply(m.m_source, rp, &m);
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();
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 */
830 int r;
831 if (OK != (r=sef_receive_status(ANY, m_ptr, status_ptr)))
832 panic("sef_receive_status failed: %d", r);