rs: stacktrace if system process exits early.
[minix.git] / servers / rs / main.c
blobf9a3d1bc3ccf45ade91457097d0f5370d859898d
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 <a.out.h>
14 #include <minix/crtso.h>
15 #include "kernel/const.h"
16 #include "kernel/type.h"
17 #include "kernel/proc.h"
18 #include "../pm/mproc.h"
20 /* Declare some local functions. */
21 FORWARD _PROTOTYPE(void exec_image_copy, ( int boot_proc_idx,
22 struct boot_image *ip, struct rproc *rp) );
23 FORWARD _PROTOTYPE(void boot_image_info_lookup, ( endpoint_t endpoint,
24 struct boot_image *image,
25 struct boot_image **ip, struct boot_image_priv **pp,
26 struct boot_image_sys **sp, struct boot_image_dev **dp) );
27 FORWARD _PROTOTYPE(void catch_boot_init_ready, (endpoint_t endpoint) );
28 FORWARD _PROTOTYPE(void get_work, (message *m_ptr, int *status_ptr) );
30 /* Flag set when memory unmapping can be done. */
31 EXTERN int unmap_ok;
33 /* SEF functions and variables. */
34 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
35 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
36 FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
37 FORWARD _PROTOTYPE( int sef_cb_signal_manager, (endpoint_t target, int signo) );
39 /*===========================================================================*
40 * main *
41 *===========================================================================*/
42 PUBLIC int main(void)
44 /* This is the main routine of this service. The main loop consists of
45 * three major activities: getting new work, processing the work, and
46 * sending the reply. The loop never terminates, unless a panic occurs.
48 message m; /* request message */
49 int ipc_status; /* status code */
50 int call_nr, who_e,who_p; /* call number and caller */
51 int result; /* result to return */
53 /* SEF local startup. */
54 sef_local_startup();
56 /* Main loop - get work and do it, forever. */
57 while (TRUE) {
59 /* Wait for request message. */
60 get_work(&m, &ipc_status);
61 who_e = m.m_source;
62 if(rs_isokendpt(who_e, &who_p) != OK) {
63 panic("message from bogus source: %d", who_e);
66 call_nr = m.m_type;
68 /* Now determine what to do. Four types of requests are expected:
69 * - Heartbeat messages (notifications from registered system services)
70 * - System notifications (synchronous alarm)
71 * - User requests (control messages to manage system services)
72 * - Ready messages (reply messages from registered services)
75 /* Notification messages are control messages and do not need a reply.
76 * These include heartbeat messages and system notifications.
78 if (is_ipc_notify(ipc_status)) {
79 switch (who_p) {
80 case CLOCK:
81 do_period(&m); /* check services status */
82 continue;
83 default: /* heartbeat notification */
84 if (rproc_ptr[who_p] != NULL) { /* mark heartbeat time */
85 rproc_ptr[who_p]->r_alive_tm = m.NOTIFY_TIMESTAMP;
86 } else {
87 printf("RS: warning: got unexpected notify message from %d\n",
88 m.m_source);
93 /* If we get this far, this is a normal request.
94 * Handle the request and send a reply to the caller.
96 else {
97 if (call_nr != GETSYSINFO &&
98 (call_nr < RS_RQ_BASE || call_nr >= RS_RQ_BASE+0x100))
100 /* Ignore invalid requests. Do not try to reply. */
101 printf("RS: warning: got invalid request %d from endpoint %d\n",
102 call_nr, m.m_source);
103 continue;
106 /* Handler functions are responsible for permission checking. */
107 switch(call_nr) {
108 /* User requests. */
109 case RS_UP: result = do_up(&m); break;
110 case RS_DOWN: result = do_down(&m); break;
111 case RS_REFRESH: result = do_refresh(&m); break;
112 case RS_RESTART: result = do_restart(&m); break;
113 case RS_SHUTDOWN: result = do_shutdown(&m); break;
114 case RS_UPDATE: result = do_update(&m); break;
115 case GETSYSINFO: result = do_getsysinfo(&m); break;
116 case RS_LOOKUP: result = do_lookup(&m); break;
117 /* Ready messages. */
118 case RS_INIT: result = do_init_ready(&m); break;
119 case RS_LU_PREPARE: result = do_upd_ready(&m); break;
120 default:
121 printf("RS: warning: got unexpected request %d from %d\n",
122 m.m_type, m.m_source);
123 result = EINVAL;
126 /* Finally send reply message, unless disabled. */
127 if (result != EDONTREPLY) {
128 m.m_type = result;
129 reply(who_e, &m);
135 /*===========================================================================*
136 * sef_local_startup *
137 *===========================================================================*/
138 PRIVATE void sef_local_startup()
140 /* Register init callbacks. */
141 sef_setcb_init_fresh(sef_cb_init_fresh); /* RS can only start fresh. */
143 /* Register signal callbacks. */
144 sef_setcb_signal_handler(sef_cb_signal_handler);
145 sef_setcb_signal_manager(sef_cb_signal_manager);
147 /* Let SEF perform startup. */
148 sef_startup();
151 /*===========================================================================*
152 * sef_cb_init_fresh *
153 *===========================================================================*/
154 PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
156 /* Initialize the reincarnation server. */
157 struct boot_image *ip;
158 int s,i,j;
159 int nr_image_srvs, nr_image_priv_srvs, nr_uncaught_init_srvs;
160 struct rproc *rp;
161 struct rprocpub *rpub;
162 struct boot_image image[NR_BOOT_PROCS];
163 struct mproc mproc[NR_PROCS];
164 struct exec header;
165 struct boot_image_priv *boot_image_priv;
166 struct boot_image_sys *boot_image_sys;
167 struct boot_image_dev *boot_image_dev;
169 /* See if we run in verbose mode. */
170 env_parse("rs_verbose", "d", 0, &rs_verbose, 0, 1);
172 /* Initialize the global init descriptor. */
173 rinit.rproctab_gid = cpf_grant_direct(ANY, (vir_bytes) rprocpub,
174 sizeof(rprocpub), CPF_READ);
175 if(!GRANT_VALID(rinit.rproctab_gid)) {
176 panic("unable to create rprocpub table grant: %d", rinit.rproctab_gid);
179 /* Initialize some global variables. */
180 rupdate.flags = 0;
181 shutting_down = FALSE;
183 /* Get a copy of the boot image table. */
184 if ((s = sys_getimage(image)) != OK) {
185 panic("unable to get copy of boot image table: %d", s);
188 /* Determine the number of system services in the boot image table and
189 * compute the size required for the boot image buffer.
191 nr_image_srvs = 0;
192 boot_image_buffer_size = 0;
193 for(i=0;i<NR_BOOT_PROCS;i++) {
194 ip = &image[i];
196 /* System services only. */
197 if(iskerneln(_ENDPOINT_P(ip->endpoint))) {
198 continue;
200 nr_image_srvs++;
202 /* Lookup the corresponding entry in the boot image sys table. */
203 boot_image_info_lookup(ip->endpoint, image,
204 NULL, NULL, &boot_image_sys, NULL);
206 /* If we must keep a copy of this system service, read the header
207 * and increase the size of the boot image buffer.
209 if(boot_image_sys->flags & SF_USE_REPL) {
210 boot_image_sys->flags |= SF_USE_COPY;
212 if(boot_image_sys->flags & SF_USE_COPY) {
213 if((s = sys_getaoutheader(&header, i)) != OK) {
214 panic("unable to get copy of a.out header: %d", s);
216 boot_image_buffer_size += header.a_hdrlen
217 + header.a_text + header.a_data;
221 /* Determine the number of entries in the boot image priv table and make sure
222 * it matches the number of system services in the boot image table.
224 nr_image_priv_srvs = 0;
225 for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
226 boot_image_priv = &boot_image_priv_table[i];
228 /* System services only. */
229 if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) {
230 continue;
232 nr_image_priv_srvs++;
234 if(nr_image_srvs != nr_image_priv_srvs) {
235 panic("boot image table and boot image priv table mismatch");
238 /* Allocate boot image buffer. */
239 if(boot_image_buffer_size > 0) {
240 boot_image_buffer = rs_startup_sbrk(boot_image_buffer_size);
241 if(boot_image_buffer == (char *) -1) {
242 panic("unable to allocate boot image buffer");
246 /* Reset the system process table. */
247 for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
248 rp->r_flags = 0;
249 rp->r_pub = &rprocpub[rp - rproc];
250 rp->r_pub->in_use = FALSE;
253 /* Initialize the system process table in 4 steps, each of them following
254 * the appearance of system services in the boot image priv table.
255 * - Step 1: get a copy of the executable image of every system service that
256 * requires it while it is not yet running.
257 * In addition, set priviliges, sys properties, and dev properties (if any)
258 * for every system service.
260 for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
261 boot_image_priv = &boot_image_priv_table[i];
263 /* System services only. */
264 if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) {
265 continue;
268 /* Lookup the corresponding entries in other tables. */
269 boot_image_info_lookup(boot_image_priv->endpoint, image,
270 &ip, NULL, &boot_image_sys, &boot_image_dev);
271 rp = &rproc[boot_image_priv - boot_image_priv_table];
272 rpub = rp->r_pub;
275 * Get a copy of the executable image if required.
277 rp->r_exec_len = 0;
278 rp->r_exec = NULL;
279 if(boot_image_sys->flags & SF_USE_COPY) {
280 exec_image_copy(ip - image, ip, rp);
284 * Set privileges.
286 /* Get label. */
287 strcpy(rpub->label, boot_image_priv->label);
289 /* Get heartbeat period. */
290 rpub->period = boot_image_priv->period;
292 if(boot_image_priv->endpoint != RS_PROC_NR) {
293 /* Force a static priv id for system services in the boot image. */
294 rp->r_priv.s_id = static_priv_id(
295 _ENDPOINT_P(boot_image_priv->endpoint));
297 /* Initialize privilege bitmaps and signal manager. */
298 rp->r_priv.s_flags = boot_image_priv->flags; /* priv flags */
299 rp->r_priv.s_trap_mask = boot_image_priv->trap_mask; /* traps */
300 memcpy(&rp->r_priv.s_ipc_to, &boot_image_priv->ipc_to,
301 sizeof(rp->r_priv.s_ipc_to)); /* targets */
302 rp->r_priv.s_sig_mgr = boot_image_priv->sig_mgr; /* sig mgr */
304 /* Initialize kernel call mask bitmap from unordered set. */
305 fill_call_mask(boot_image_priv->k_calls, NR_SYS_CALLS,
306 rp->r_priv.s_k_call_mask, KERNEL_CALL, TRUE);
308 /* Set the privilege structure. */
309 if ((s = sys_privctl(ip->endpoint, SYS_PRIV_SET_SYS, &(rp->r_priv)))
310 != OK) {
311 panic("unable to set privilege structure: %d", s);
315 /* Synch the privilege structure with the kernel. */
316 if ((s = sys_getpriv(&(rp->r_priv), ip->endpoint)) != OK) {
317 panic("unable to synch privilege structure: %d", s);
321 * Set sys properties.
323 rpub->sys_flags = boot_image_sys->flags; /* sys flags */
326 * Set dev properties.
328 rpub->dev_flags = boot_image_dev->flags; /* device flags */
329 rpub->dev_nr = boot_image_dev->dev_nr; /* major device number */
330 rpub->dev_style = boot_image_dev->dev_style; /* device style */
331 rpub->dev_style2 = boot_image_dev->dev_style2; /* device style 2 */
333 /* Get process name. */
334 strcpy(rpub->proc_name, ip->proc_name);
336 /* Get command settings. */
337 strcpy(rp->r_cmd, ip->proc_name);
338 rp->r_script[0]= '\0';
339 build_cmd_dep(rp);
341 /* Initialize vm call mask bitmap from unordered set. */
342 fill_call_mask(boot_image_priv->vm_calls, NR_VM_CALLS,
343 rpub->vm_call_mask, VM_RQ_BASE, TRUE);
345 /* Get some settings from the boot image table. */
346 rp->r_nice = ip->priority;
347 rpub->endpoint = ip->endpoint;
349 /* Set some defaults. */
350 rp->r_old_rp = NULL; /* no old version yet */
351 rp->r_new_rp = NULL; /* no new version yet */
352 rp->r_prev_rp = NULL; /* no prev replica yet */
353 rp->r_next_rp = NULL; /* no next replica yet */
354 rp->r_uid = 0; /* root */
355 rp->r_check_tm = 0; /* not checked yet */
356 getuptime(&rp->r_alive_tm); /* currently alive */
357 rp->r_stop_tm = 0; /* not exiting yet */
358 rp->r_restarts = 0; /* no restarts so far */
359 rp->r_set_resources = 0; /* don't set resources */
361 /* Mark as in use and active. */
362 rp->r_flags = RS_IN_USE | RS_ACTIVE;
363 rproc_ptr[_ENDPOINT_P(rpub->endpoint)]= rp;
364 rpub->in_use = TRUE;
367 /* - Step 2: allow every system service in the boot image to run.
369 nr_uncaught_init_srvs = 0;
370 for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
371 boot_image_priv = &boot_image_priv_table[i];
373 /* System services only. */
374 if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) {
375 continue;
378 /* Ignore RS. */
379 if(boot_image_priv->endpoint == RS_PROC_NR) {
380 continue;
383 /* Lookup the corresponding slot in the system process table. */
384 rp = &rproc[boot_image_priv - boot_image_priv_table];
385 rpub = rp->r_pub;
387 /* Allow the service to run. */
388 if ((s = sys_privctl(rpub->endpoint, SYS_PRIV_ALLOW, NULL)) != OK) {
389 panic("unable to initialize privileges: %d", s);
392 /* Initialize service. We assume every service will always get
393 * back to us here at boot time.
395 if(boot_image_priv->flags & SYS_PROC) {
396 if ((s = init_service(rp, SEF_INIT_FRESH)) != OK) {
397 panic("unable to initialize service: %d", s);
399 if(rpub->sys_flags & SF_SYNCH_BOOT) {
400 /* Catch init ready message now to synchronize. */
401 catch_boot_init_ready(rpub->endpoint);
403 else {
404 /* Catch init ready message later. */
405 nr_uncaught_init_srvs++;
410 /* - Step 3: let every system service complete initialization by
411 * catching all the init ready messages left.
413 while(nr_uncaught_init_srvs) {
414 catch_boot_init_ready(ANY);
415 nr_uncaught_init_srvs--;
418 /* - Step 4: all the system services in the boot image are now running.
419 * Complete the initialization of the system process table in collaboration
420 * with other system services.
422 if ((s = getsysinfo(PM_PROC_NR, SI_PROC_TAB, mproc)) != OK) {
423 panic("unable to get copy of PM process table: %d", s);
425 for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
426 boot_image_priv = &boot_image_priv_table[i];
428 /* System services only. */
429 if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) {
430 continue;
433 /* Lookup the corresponding slot in the system process table. */
434 rp = &rproc[boot_image_priv - boot_image_priv_table];
435 rpub = rp->r_pub;
437 /* Get pid from PM process table. */
438 rp->r_pid = -1;
439 for (j = 0; j < NR_PROCS; j++) {
440 if (mproc[j].mp_endpoint == rpub->endpoint) {
441 rp->r_pid = mproc[j].mp_pid;
442 break;
445 if(j == NR_PROCS) {
446 panic("unable to get pid");
449 /* If we must keep a replica of this system service, create it now. */
450 if(rpub->sys_flags & SF_USE_REPL) {
451 if ((s = clone_service(rp)) != OK) {
452 panic("unable to clone service: %d", s);
458 * Now complete RS initialization process in collaboration with other
459 * system services.
461 /* Let the rest of the system know about our dynamically allocated buffer. */
462 if(boot_image_buffer_size > 0) {
463 boot_image_buffer = rs_startup_sbrk_synch(boot_image_buffer_size);
464 if(boot_image_buffer == (char *) -1) {
465 panic("unable to synch boot image buffer");
469 /* Set alarm to periodically check service status. */
470 if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
471 panic("couldn't set alarm: %d", s);
473 /* Map out our own text and data. This is normally done in crtso.o
474 * but RS is an exception - we don't get to talk to VM so early on.
475 * That's why we override munmap() and munmap_text() in utility.c.
477 * _minix_unmapzero() is the same code in crtso.o that normally does
478 * it on startup. It's best that it's there as crtso.o knows exactly
479 * what the ranges are of the filler data.
481 unmap_ok = 1;
482 _minix_unmapzero();
484 return(OK);
487 /*===========================================================================*
488 * sef_cb_signal_handler *
489 *===========================================================================*/
490 PRIVATE void sef_cb_signal_handler(int signo)
492 /* Check for known signals, ignore anything else. */
493 switch(signo) {
494 case SIGCHLD:
495 do_sigchld();
496 break;
497 case SIGTERM:
498 do_shutdown(NULL);
499 break;
503 /*===========================================================================*
504 * sef_cb_signal_manager *
505 *===========================================================================*/
506 PRIVATE int sef_cb_signal_manager(endpoint_t target, int signo)
508 /* Process system signal on behalf of the kernel. */
509 int target_p;
510 struct rproc *rp;
511 struct rprocpub *rpub;
512 message m;
514 /* Lookup slot. */
515 if(rs_isokendpt(target, &target_p) != OK || rproc_ptr[target_p] == NULL) {
516 if(rs_verbose)
517 printf("RS: ignoring spurious signal %d for process %d\n",
518 signo, target);
519 return OK; /* clear the signal */
521 rp = rproc_ptr[target_p];
522 rpub = rp->r_pub;
524 /* Don't bother if a termination signal has already been processed. */
525 if((rp->r_flags & RS_TERMINATED) && !(rp->r_flags & RS_EXITING)) {
526 return EDEADSRCDST; /* process is gone */
529 /* Ignore external signals for inactive service instances. */
530 if( !(rp->r_flags & RS_ACTIVE) && !(rp->r_flags & RS_EXITING)) {
531 if(rs_verbose)
532 printf("RS: ignoring signal %d for inactive %s\n",
533 signo, srv_to_string(rp));
534 return OK; /* clear the signal */
537 if(rs_verbose)
538 printf("RS: %s got %s signal %d\n", srv_to_string(rp),
539 SIGS_IS_TERMINATION(signo) ? "termination" : "non-termination",signo);
541 /* Print stacktrace if necessary. */
542 if(SIGS_IS_STACKTRACE(signo)) {
543 sys_sysctl_stacktrace(target);
546 /* In case of termination signal handle the event. */
547 if(SIGS_IS_TERMINATION(signo)) {
548 rp->r_flags |= RS_TERMINATED;
549 terminate_service(rp);
551 return EDEADSRCDST; /* process is now gone */
554 /* Translate every non-termination signal into a message. */
555 m.m_type = SIGS_SIGNAL_RECEIVED;
556 m.SIGS_SIG_NUM = signo;
557 asynsend3(rpub->endpoint, &m, AMF_NOREPLY);
559 return OK; /* signal has been delivered */
562 /*===========================================================================*
563 * exec_image_copy *
564 *===========================================================================*/
565 PRIVATE void exec_image_copy(boot_proc_idx, ip, rp)
566 int boot_proc_idx;
567 struct boot_image *ip;
568 struct rproc *rp;
570 /* Copy the executable image of the given boot process. */
571 int s;
572 struct exec header;
573 static char *boot_image_ptr = NULL;
575 if(boot_image_ptr == NULL) {
576 boot_image_ptr = boot_image_buffer;
579 /* Get a.out header. */
580 s = ENOMEM;
581 if(boot_image_buffer+boot_image_buffer_size - boot_image_ptr < sizeof(header)
582 || (s = sys_getaoutheader(&header, boot_proc_idx)) != OK) {
583 panic("unable to get copy of a.out header: %d", s);
585 memcpy(boot_image_ptr, &header, header.a_hdrlen);
586 boot_image_ptr += header.a_hdrlen;
588 /* Get text segment. */
589 s = ENOMEM;
590 if(boot_image_buffer+boot_image_buffer_size - boot_image_ptr < header.a_text
591 || (s = rs_startup_segcopy(ip->endpoint, T, D, (vir_bytes) boot_image_ptr,
592 header.a_text)) != OK) {
593 panic("unable to get copy of text segment: %d", s);
595 boot_image_ptr += header.a_text;
597 /* Get data segment. */
598 s = ENOMEM;
599 if(boot_image_buffer+boot_image_buffer_size - boot_image_ptr < header.a_data
600 || (s = rs_startup_segcopy(ip->endpoint, D, D, (vir_bytes) boot_image_ptr,
601 header.a_data)) != OK) {
602 panic("unable to get copy of data segment: %d", s);
604 boot_image_ptr += header.a_data;
606 /* Set the executable image for the given boot process. */
607 rp->r_exec_len = header.a_hdrlen + header.a_text + header.a_data;
608 rp->r_exec = boot_image_ptr - rp->r_exec_len;
611 /*===========================================================================*
612 * boot_image_info_lookup *
613 *===========================================================================*/
614 PRIVATE void boot_image_info_lookup(endpoint, image, ip, pp, sp, dp)
615 endpoint_t endpoint;
616 struct boot_image *image;
617 struct boot_image **ip;
618 struct boot_image_priv **pp;
619 struct boot_image_sys **sp;
620 struct boot_image_dev **dp;
622 /* Lookup entries in boot image tables. */
623 int i;
625 /* When requested, locate the corresponding entry in the boot image table
626 * or panic if not found.
628 if(ip) {
629 for (i=0; i < NR_BOOT_PROCS; i++) {
630 if(image[i].endpoint == endpoint) {
631 *ip = &image[i];
632 break;
635 if(i == NR_BOOT_PROCS) {
636 panic("boot image table lookup failed");
640 /* When requested, locate the corresponding entry in the boot image priv table
641 * or panic if not found.
643 if(pp) {
644 for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
645 if(boot_image_priv_table[i].endpoint == endpoint) {
646 *pp = &boot_image_priv_table[i];
647 break;
650 if(i == NULL_BOOT_NR) {
651 panic("boot image priv table lookup failed");
655 /* When requested, locate the corresponding entry in the boot image sys table
656 * or resort to the default entry if not found.
658 if(sp) {
659 for (i=0; boot_image_sys_table[i].endpoint != DEFAULT_BOOT_NR; i++) {
660 if(boot_image_sys_table[i].endpoint == endpoint) {
661 *sp = &boot_image_sys_table[i];
662 break;
665 if(boot_image_sys_table[i].endpoint == DEFAULT_BOOT_NR) {
666 *sp = &boot_image_sys_table[i]; /* accept the default entry */
670 /* When requested, locate the corresponding entry in the boot image dev table
671 * or resort to the default entry if not found.
673 if(dp) {
674 for (i=0; boot_image_dev_table[i].endpoint != DEFAULT_BOOT_NR; i++) {
675 if(boot_image_dev_table[i].endpoint == endpoint) {
676 *dp = &boot_image_dev_table[i];
677 break;
680 if(boot_image_dev_table[i].endpoint == DEFAULT_BOOT_NR) {
681 *dp = &boot_image_dev_table[i]; /* accept the default entry */
686 /*===========================================================================*
687 * catch_boot_init_ready *
688 *===========================================================================*/
689 PRIVATE void catch_boot_init_ready(endpoint)
690 endpoint_t endpoint;
692 /* Block and catch an init ready message from the given source. */
693 int r;
694 int ipc_status;
695 message m;
696 struct rproc *rp;
697 int result;
699 /* Receive init ready message. */
700 if ((r = sef_receive_status(endpoint, &m, &ipc_status)) != OK) {
701 panic("unable to receive init reply: %d", r);
703 if(m.m_type != RS_INIT) {
704 panic("unexpected reply from service: %d", m.m_source);
706 result = m.RS_INIT_RESULT;
707 rp = rproc_ptr[_ENDPOINT_P(m.m_source)];
709 /* Check result. */
710 if(result != OK) {
711 panic("unable to complete init for service: %d", m.m_source);
714 /* Send a reply to unblock the service. */
715 m.m_type = OK;
716 reply(m.m_source, &m);
718 /* Mark the slot as no longer initializing. */
719 rp->r_flags &= ~RS_INITIALIZING;
720 rp->r_check_tm = 0;
721 getuptime(&rp->r_alive_tm);
724 /*===========================================================================*
725 * get_work *
726 *===========================================================================*/
727 PRIVATE void get_work(m_ptr, status_ptr)
728 message *m_ptr; /* pointer to message */
729 int *status_ptr; /* pointer to status */
731 int r;
732 if (OK != (r=sef_receive_status(ANY, m_ptr, status_ptr)))
733 panic("sef_receive_status failed: %d", r);