libexec exec fix
[minix.git] / servers / rs / request.c
blobe659c712ada02b033e248a50fefb63dc7ba1852b
1 /*
2 * Changes:
3 * Jan 22, 2010: Created (Cristiano Giuffrida)
4 */
6 #include "inc.h"
8 #include "kernel/proc.h"
10 static int check_request(struct rs_start *rs_start);
12 /*===========================================================================*
13 * do_up *
14 *===========================================================================*/
15 int do_up(m_ptr)
16 message *m_ptr; /* request message pointer */
18 /* A request was made to start a new system service. */
19 struct rproc *rp;
20 struct rprocpub *rpub;
21 int r;
22 struct rs_start rs_start;
23 int noblock;
25 /* Check if the call can be allowed. */
26 if((r = check_call_permission(m_ptr->m_source, RS_UP, NULL)) != OK)
27 return r;
29 /* Allocate a new system service slot. */
30 r = alloc_slot(&rp);
31 if(r != OK) {
32 printf("RS: do_up: unable to allocate a new slot: %d\n", r);
33 return r;
35 rpub = rp->r_pub;
37 /* Copy the request structure. */
38 r = copy_rs_start(m_ptr->m_source, m_ptr->RS_CMD_ADDR, &rs_start);
39 if (r != OK) {
40 return r;
42 r = check_request(&rs_start);
43 if (r != OK) {
44 return r;
46 noblock = (rs_start.rss_flags & RSS_NOBLOCK);
48 /* Initialize the slot as requested. */
49 r = init_slot(rp, &rs_start, m_ptr->m_source);
50 if(r != OK) {
51 printf("RS: do_up: unable to init the new slot: %d\n", r);
52 return r;
55 /* Check for duplicates */
56 if(lookup_slot_by_label(rpub->label)) {
57 printf("RS: service with the same label '%s' already exists\n",
58 rpub->label);
59 return EBUSY;
61 if(rpub->dev_nr>0 && lookup_slot_by_dev_nr(rpub->dev_nr)) {
62 printf("RS: service with the same device number %d already exists\n",
63 rpub->dev_nr);
64 return EBUSY;
67 /* All information was gathered. Now try to start the system service. */
68 r = start_service(rp);
69 if(r != OK) {
70 return r;
73 /* Unblock the caller immediately if requested. */
74 if(noblock) {
75 return OK;
78 /* Late reply - send a reply when service completes initialization. */
79 rp->r_flags |= RS_LATEREPLY;
80 rp->r_caller = m_ptr->m_source;
81 rp->r_caller_request = RS_UP;
83 return EDONTREPLY;
86 /*===========================================================================*
87 * do_down *
88 *===========================================================================*/
89 int do_down(message *m_ptr)
91 register struct rproc *rp;
92 int s;
93 char label[RS_MAX_LABEL_LEN];
95 /* Copy label. */
96 s = copy_label(m_ptr->m_source, m_ptr->RS_CMD_ADDR,
97 m_ptr->RS_CMD_LEN, label, sizeof(label));
98 if(s != OK) {
99 return s;
102 /* Lookup slot by label. */
103 rp = lookup_slot_by_label(label);
104 if(!rp) {
105 if(rs_verbose)
106 printf("RS: do_down: service '%s' not found\n", label);
107 return(ESRCH);
110 /* Check if the call can be allowed. */
111 if((s = check_call_permission(m_ptr->m_source, RS_DOWN, rp)) != OK)
112 return s;
114 /* Stop service. */
115 if (rp->r_flags & RS_TERMINATED) {
116 /* A recovery script is requesting us to bring down the service.
117 * The service is already gone, simply perform cleanup.
119 if(rs_verbose)
120 printf("RS: recovery script performs service down...\n");
121 unpublish_service(rp);
122 cleanup_service(rp);
123 return(OK);
125 stop_service(rp,RS_EXITING);
127 /* Late reply - send a reply when service dies. */
128 rp->r_flags |= RS_LATEREPLY;
129 rp->r_caller = m_ptr->m_source;
130 rp->r_caller_request = RS_DOWN;
132 return EDONTREPLY;
135 /*===========================================================================*
136 * do_restart *
137 *===========================================================================*/
138 int do_restart(message *m_ptr)
140 struct rproc *rp;
141 int s, r;
142 char label[RS_MAX_LABEL_LEN];
143 char script[MAX_SCRIPT_LEN];
145 /* Copy label. */
146 s = copy_label(m_ptr->m_source, m_ptr->RS_CMD_ADDR,
147 m_ptr->RS_CMD_LEN, label, sizeof(label));
148 if(s != OK) {
149 return s;
152 /* Lookup slot by label. */
153 rp = lookup_slot_by_label(label);
154 if(!rp) {
155 if(rs_verbose)
156 printf("RS: do_restart: service '%s' not found\n", label);
157 return(ESRCH);
160 /* Check if the call can be allowed. */
161 if((r = check_call_permission(m_ptr->m_source, RS_RESTART, rp)) != OK)
162 return r;
164 /* We can only be asked to restart a service from a recovery script. */
165 if (! (rp->r_flags & RS_TERMINATED) ) {
166 if(rs_verbose)
167 printf("RS: %s is still running\n", srv_to_string(rp));
168 return EBUSY;
171 if(rs_verbose)
172 printf("RS: recovery script performs service restart...\n");
174 /* Restart the service, but make sure we don't call the script again. */
175 strcpy(script, rp->r_script);
176 rp->r_script[0] = '\0';
177 restart_service(rp);
178 strcpy(rp->r_script, script);
180 return OK;
183 /*===========================================================================*
184 * do_clone *
185 *===========================================================================*/
186 int do_clone(message *m_ptr)
188 struct rproc *rp;
189 struct rprocpub *rpub;
190 int s, r;
191 char label[RS_MAX_LABEL_LEN];
193 /* Copy label. */
194 s = copy_label(m_ptr->m_source, m_ptr->RS_CMD_ADDR,
195 m_ptr->RS_CMD_LEN, label, sizeof(label));
196 if(s != OK) {
197 return s;
200 /* Lookup slot by label. */
201 rp = lookup_slot_by_label(label);
202 if(!rp) {
203 if(rs_verbose)
204 printf("RS: do_clone: service '%s' not found\n", label);
205 return(ESRCH);
207 rpub = rp->r_pub;
209 /* Check if the call can be allowed. */
210 if((r = check_call_permission(m_ptr->m_source, RS_CLONE, rp)) != OK)
211 return r;
213 /* Don't clone if a replica is already available. */
214 if(rp->r_next_rp) {
215 return EEXIST;
218 /* Clone the service as requested. */
219 rpub->sys_flags |= SF_USE_REPL;
220 if ((r = clone_service(rp, RST_SYS_PROC)) != OK) {
221 rpub->sys_flags &= ~SF_USE_REPL;
222 return r;
225 return OK;
228 /*===========================================================================*
229 * do_edit *
230 *===========================================================================*/
231 int do_edit(message *m_ptr)
233 struct rproc *rp;
234 struct rprocpub *rpub;
235 struct rs_start rs_start;
236 int r;
237 char label[RS_MAX_LABEL_LEN];
239 /* Copy the request structure. */
240 r = copy_rs_start(m_ptr->m_source, m_ptr->RS_CMD_ADDR, &rs_start);
241 if (r != OK) {
242 return r;
245 /* Copy label. */
246 r = copy_label(m_ptr->m_source, rs_start.rss_label.l_addr,
247 rs_start.rss_label.l_len, label, sizeof(label));
248 if(r != OK) {
249 return r;
252 /* Lookup slot by label. */
253 rp = lookup_slot_by_label(label);
254 if(!rp) {
255 if(rs_verbose)
256 printf("RS: do_edit: service '%s' not found\n", label);
257 return ESRCH;
259 rpub = rp->r_pub;
261 /* Check if the call can be allowed. */
262 if((r = check_call_permission(m_ptr->m_source, RS_EDIT, rp)) != OK)
263 return r;
265 if(rs_verbose)
266 printf("RS: %s edits settings\n", srv_to_string(rp));
268 /* Synch the privilege structure with the kernel. */
269 if ((r = sys_getpriv(&rp->r_priv, rpub->endpoint)) != OK) {
270 printf("RS: do_edit: unable to synch privilege structure: %d\n", r);
271 return r;
274 /* Tell scheduler this process is finished */
275 if ((r = sched_stop(rp->r_scheduler, rpub->endpoint)) != OK) {
276 printf("RS: do_edit: scheduler won't give up process: %d\n", r);
277 return r;
280 /* Edit the slot as requested. */
281 if((r = edit_slot(rp, &rs_start, m_ptr->m_source)) != OK) {
282 printf("RS: do_edit: unable to edit the existing slot: %d\n", r);
283 return r;
286 /* Update privilege structure. */
287 r = sys_privctl(rpub->endpoint, SYS_PRIV_UPDATE_SYS, &rp->r_priv);
288 if(r != OK) {
289 printf("RS: do_edit: unable to update privilege structure: %d\n", r);
290 return r;
293 /* Update VM calls. */
294 if ((r = vm_set_priv(rpub->endpoint, &rpub->vm_call_mask[0])) != OK) {
295 printf("RS: do_edit: failed: %d\n", r);
296 return r;
299 /* Reinitialize scheduling. */
300 if ((r = sched_init_proc(rp)) != OK) {
301 printf("RS: do_edit: unable to reinitialize scheduling: %d\n", r);
302 return r;
305 /* Cleanup old replicas and create a new one, if necessary. */
306 if(rpub->sys_flags & SF_USE_REPL) {
307 if(rp->r_next_rp) {
308 cleanup_service(rp->r_next_rp);
309 rp->r_next_rp = NULL;
311 if ((r = clone_service(rp, RST_SYS_PROC)) != OK) {
312 printf("RS: warning: unable to clone %s\n", srv_to_string(rp));
316 return OK;
319 /*===========================================================================*
320 * do_refresh *
321 *===========================================================================*/
322 int do_refresh(message *m_ptr)
324 register struct rproc *rp;
325 int s;
326 char label[RS_MAX_LABEL_LEN];
328 /* Copy label. */
329 s = copy_label(m_ptr->m_source, m_ptr->RS_CMD_ADDR,
330 m_ptr->RS_CMD_LEN, label, sizeof(label));
331 if(s != OK) {
332 return s;
335 /* Lookup slot by label. */
336 rp = lookup_slot_by_label(label);
337 if(!rp) {
338 if(rs_verbose)
339 printf("RS: do_refresh: service '%s' not found\n", label);
340 return(ESRCH);
343 /* Check if the call can be allowed. */
344 if((s = check_call_permission(m_ptr->m_source, RS_REFRESH, rp)) != OK)
345 return s;
347 /* Refresh service. */
348 if(rs_verbose)
349 printf("RS: %s refreshing\n", srv_to_string(rp));
350 stop_service(rp,RS_REFRESHING);
352 return OK;
355 /*===========================================================================*
356 * do_shutdown *
357 *===========================================================================*/
358 int do_shutdown(message *m_ptr)
360 int slot_nr;
361 struct rproc *rp;
362 int r;
364 /* Check if the call can be allowed. */
365 if (m_ptr != NULL) {
366 if((r = check_call_permission(m_ptr->m_source, RS_SHUTDOWN, NULL)) != OK)
367 return r;
370 if(rs_verbose)
371 printf("RS: shutting down...\n");
373 /* Set flag to tell RS we are shutting down. */
374 shutting_down = TRUE;
376 /* Don't restart dead services. */
377 for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) {
378 rp = &rproc[slot_nr];
379 if (rp->r_flags & RS_IN_USE) {
380 rp->r_flags |= RS_EXITING;
383 return(OK);
386 /*===========================================================================*
387 * do_init_ready *
388 *===========================================================================*/
389 int do_init_ready(message *m_ptr)
391 int who_p;
392 message m;
393 struct rproc *rp;
394 struct rprocpub *rpub;
395 int result, is_rs;
396 int r;
398 is_rs = (m_ptr->m_source == RS_PROC_NR);
399 who_p = _ENDPOINT_P(m_ptr->m_source);
400 result = m_ptr->RS_INIT_RESULT;
402 /* Check for RS failing initialization first. */
403 if(is_rs && result != OK) {
404 return result;
407 rp = rproc_ptr[who_p];
408 rpub = rp->r_pub;
410 /* Make sure the originating service was requested to initialize. */
411 if(! (rp->r_flags & RS_INITIALIZING) ) {
412 if(rs_verbose)
413 printf("RS: do_init_ready: got unexpected init ready msg from %d\n",
414 m_ptr->m_source);
415 return EINVAL;
418 /* Check if something went wrong and the service failed to init.
419 * In that case, kill the service.
421 if(result != OK) {
422 if(rs_verbose)
423 printf("RS: %s initialization error: %s\n", srv_to_string(rp),
424 init_strerror(result));
425 if (result == ERESTART)
426 rp->r_flags |= RS_REINCARNATE;
427 crash_service(rp); /* simulate crash */
428 return EDONTREPLY;
431 /* Mark the slot as no longer initializing. */
432 rp->r_flags &= ~RS_INITIALIZING;
433 rp->r_check_tm = 0;
434 getuptime(&rp->r_alive_tm);
436 /* Reply and unblock the service before doing anything else. */
437 m.m_type = OK;
438 reply(rpub->endpoint, rp, &m);
440 /* See if a late reply has to be sent. */
441 late_reply(rp, OK);
443 if(rs_verbose)
444 printf("RS: %s initialized\n", srv_to_string(rp));
446 /* If the service has completed initialization after a live
447 * update, end the update now.
449 if(rp->r_flags & RS_UPDATING) {
450 printf("RS: update succeeded\n");
451 end_update(OK, RS_DONTREPLY);
454 /* If the service has completed initialization after a crash
455 * make the new instance active and cleanup the old replica.
457 if(rp->r_prev_rp) {
458 cleanup_service(rp->r_prev_rp);
459 rp->r_prev_rp = NULL;
460 rp->r_restarts += 1;
462 if(rs_verbose)
463 printf("RS: %s completed restart\n", srv_to_string(rp));
466 /* If we must keep a replica of this system service, create it now. */
467 if(rpub->sys_flags & SF_USE_REPL) {
468 if ((r = clone_service(rp, RST_SYS_PROC)) != OK) {
469 printf("RS: warning: unable to clone %s\n", srv_to_string(rp));
473 return is_rs ? OK : EDONTREPLY; /* return what the caller expects */
476 /*===========================================================================*
477 * do_update *
478 *===========================================================================*/
479 int do_update(message *m_ptr)
481 struct rproc *rp;
482 struct rproc *new_rp;
483 struct rprocpub *rpub;
484 struct rs_start rs_start;
485 int noblock, do_self_update;
486 int s;
487 char label[RS_MAX_LABEL_LEN];
488 int lu_state;
489 int prepare_maxtime;
491 /* Copy the request structure. */
492 s = copy_rs_start(m_ptr->m_source, m_ptr->RS_CMD_ADDR, &rs_start);
493 if (s != OK) {
494 return s;
496 noblock = (rs_start.rss_flags & RSS_NOBLOCK);
497 do_self_update = (rs_start.rss_flags & RSS_SELF_LU);
498 s = check_request(&rs_start);
499 if (s != OK) {
500 return s;
503 /* Copy label. */
504 s = copy_label(m_ptr->m_source, rs_start.rss_label.l_addr,
505 rs_start.rss_label.l_len, label, sizeof(label));
506 if(s != OK) {
507 return s;
510 /* Lookup slot by label. */
511 rp = lookup_slot_by_label(label);
512 if(!rp) {
513 if(rs_verbose)
514 printf("RS: do_update: service '%s' not found\n", label);
515 return ESRCH;
517 rpub = rp->r_pub;
519 /* Check if the call can be allowed. */
520 if((s = check_call_permission(m_ptr->m_source, RS_UPDATE, rp)) != OK)
521 return s;
523 /* Retrieve live update state. */
524 lu_state = m_ptr->RS_LU_STATE;
525 if(lu_state == SEF_LU_STATE_NULL) {
526 return(EINVAL);
529 /* Retrieve prepare max time. */
530 prepare_maxtime = m_ptr->RS_LU_PREPARE_MAXTIME;
531 if(prepare_maxtime) {
532 if(prepare_maxtime < 0 || prepare_maxtime > RS_MAX_PREPARE_MAXTIME) {
533 return(EINVAL);
536 else {
537 prepare_maxtime = RS_DEFAULT_PREPARE_MAXTIME;
540 /* Make sure we are not already updating. */
541 if(rupdate.flags & RS_UPDATING) {
542 if(rs_verbose)
543 printf("RS: do_update: an update is already in progress\n");
544 return EBUSY;
547 /* A self update live updates a service instance into a replica, a regular
548 * update live updates a service instance into a new version, as specified
549 * by the given binary.
551 if(do_self_update) {
552 if(rs_verbose)
553 printf("RS: %s performs self update\n", srv_to_string(rp));
555 /* Clone the system service and use the replica as the new version. */
556 s = clone_service(rp, LU_SYS_PROC);
557 if(s != OK) {
558 printf("RS: do_update: unable to clone service: %d\n", s);
559 return s;
562 else {
563 if(rs_verbose)
564 printf("RS: %s performs regular update\n", srv_to_string(rp));
566 /* Allocate a system service slot for the new version. */
567 s = alloc_slot(&new_rp);
568 if(s != OK) {
569 printf("RS: do_update: unable to allocate a new slot: %d\n", s);
570 return s;
573 /* Initialize the slot as requested. */
574 s = init_slot(new_rp, &rs_start, m_ptr->m_source);
575 if(s != OK) {
576 printf("RS: do_update: unable to init the new slot: %d\n", s);
577 return s;
580 /* Let the new version inherit defaults from the old one. */
581 inherit_service_defaults(rp, new_rp);
583 /* Link the two versions. */
584 rp->r_new_rp = new_rp;
585 new_rp->r_old_rp = rp;
587 /* Create new version of the service but don't let it run. */
588 new_rp->r_priv.s_flags |= LU_SYS_PROC;
589 s = create_service(new_rp);
590 if(s != OK) {
591 printf("RS: do_update: unable to create a new service: %d\n", s);
592 return s;
596 /* Mark both versions as updating. */
597 rp->r_flags |= RS_UPDATING;
598 rp->r_new_rp->r_flags |= RS_UPDATING;
599 rupdate.flags |= RS_UPDATING;
600 getuptime(&rupdate.prepare_tm);
601 rupdate.prepare_maxtime = prepare_maxtime;
602 rupdate.rp = rp;
604 if(rs_verbose)
605 printf("RS: %s updating\n", srv_to_string(rp));
607 /* If RS is updating, set up signal managers for the new instance.
608 * The current RS instance must be made the backup signal manager to
609 * support rollback in case of a crash during initialization.
611 if(rp->r_priv.s_flags & ROOT_SYS_PROC) {
612 new_rp = rp->r_new_rp;
614 s = update_sig_mgrs(new_rp, SELF, new_rp->r_pub->endpoint);
615 if(s != OK) {
616 cleanup_service(new_rp);
617 return s;
621 if(noblock) {
622 /* Unblock the caller immediately if requested. */
623 m_ptr->m_type = OK;
624 reply(m_ptr->m_source, NULL, m_ptr);
626 else {
627 /* Send a reply when the new version completes initialization. */
628 rp->r_flags |= RS_LATEREPLY;
629 rp->r_caller = m_ptr->m_source;
630 rp->r_caller_request = RS_UPDATE;
633 /* Request to update. */
634 m_ptr->m_type = RS_LU_PREPARE;
635 if(rpub->endpoint == RS_PROC_NR) {
636 /* RS can process the request directly. */
637 do_sef_lu_request(m_ptr);
639 else {
640 /* Send request message to the system service. */
641 asynsend3(rpub->endpoint, m_ptr, AMF_NOREPLY);
644 return EDONTREPLY;
647 /*===========================================================================*
648 * do_upd_ready *
649 *===========================================================================*/
650 int do_upd_ready(message *m_ptr)
652 struct rproc *rp, *old_rp, *new_rp;
653 int who_p;
654 int result;
655 int is_rs;
656 int r;
658 who_p = _ENDPOINT_P(m_ptr->m_source);
659 rp = rproc_ptr[who_p];
660 result = m_ptr->RS_LU_RESULT;
661 is_rs = (m_ptr->m_source == RS_PROC_NR);
663 /* Make sure the originating service was requested to prepare for update. */
664 if(rp != rupdate.rp) {
665 if(rs_verbose)
666 printf("RS: do_upd_ready: got unexpected update ready msg from %d\n",
667 m_ptr->m_source);
668 return EINVAL;
671 /* Check if something went wrong and the service failed to prepare
672 * for the update. In that case, end the update process. The old version will
673 * be replied to and continue executing.
675 if(result != OK) {
676 end_update(result, RS_REPLY);
678 printf("RS: update failed: %s\n", lu_strerror(result));
679 return is_rs ? result : EDONTREPLY; /* return what the caller expects */
682 old_rp = rp;
683 new_rp = rp->r_new_rp;
685 /* If RS itself is updating, yield control to the new version immediately. */
686 if(is_rs) {
687 r = init_service(new_rp, SEF_INIT_LU);
688 if(r != OK) {
689 panic("unable to initialize the new RS instance: %d", r);
691 r = sys_privctl(new_rp->r_pub->endpoint, SYS_PRIV_YIELD, NULL);
692 if(r != OK) {
693 panic("unable to yield control to the new RS instance: %d", r);
695 /* If we get this far, the new version failed to initialize. Rollback. */
696 r = srv_update(RS_PROC_NR, new_rp->r_pub->endpoint);
697 assert(r == OK); /* can't fail */
698 end_update(ERESTART, RS_REPLY);
699 return ERESTART;
702 /* Perform the update. */
703 r = update_service(&old_rp, &new_rp, RS_SWAP);
704 if(r != OK) {
705 end_update(r, RS_REPLY);
706 printf("RS: update failed: error %d\n", r);
707 return EDONTREPLY;
710 /* Let the new version run. */
711 r = run_service(new_rp, SEF_INIT_LU);
712 if(r != OK) {
713 /* Something went wrong. Rollback. */
714 r = update_service(&new_rp, &old_rp, RS_SWAP);
715 assert(r == OK); /* can't fail */
716 end_update(r, RS_REPLY);
717 printf("RS: update failed: error %d\n", r);
718 return EDONTREPLY;
721 return EDONTREPLY;
724 /*===========================================================================*
725 * do_period *
726 *===========================================================================*/
727 void do_period(m_ptr)
728 message *m_ptr;
730 register struct rproc *rp;
731 register struct rprocpub *rpub;
732 clock_t now = m_ptr->NOTIFY_TIMESTAMP;
733 int s;
734 long period;
736 /* If an update is in progress, check its status. */
737 if(rupdate.flags & RS_UPDATING) {
738 update_period(m_ptr);
741 /* Search system services table. Only check slots that are in use and not
742 * updating.
744 for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
745 rpub = rp->r_pub;
746 if ((rp->r_flags & RS_ACTIVE) && !(rp->r_flags & RS_UPDATING)) {
748 /* Compute period. */
749 period = rp->r_period;
750 if(rp->r_flags & RS_INITIALIZING) {
751 period = RS_INIT_T;
754 /* If the service is to be revived (because it repeatedly exited,
755 * and was not directly restarted), the binary backoff field is
756 * greater than zero.
758 if (rp->r_backoff > 0) {
759 rp->r_backoff -= 1;
760 if (rp->r_backoff == 0) {
761 restart_service(rp);
765 /* If the service was signaled with a SIGTERM and fails to respond,
766 * kill the system service with a SIGKILL signal.
768 else if (rp->r_stop_tm > 0 && now - rp->r_stop_tm > 2*RS_DELTA_T
769 && rp->r_pid > 0) {
770 rp->r_stop_tm = 0;
771 crash_service(rp); /* simulate crash */
774 /* There seems to be no special conditions. If the service has a
775 * period assigned check its status.
777 else if (period > 0) {
779 /* Check if an answer to a status request is still pending. If
780 * the service didn't respond within time, kill it to simulate
781 * a crash. The failure will be detected and the service will
782 * be restarted automatically. Give the service a free pass if
783 * somebody is initializing. There may be some weird dependencies
784 * if another service is, for example, restarting at the same
785 * time.
787 if (rp->r_alive_tm < rp->r_check_tm) {
788 if (now - rp->r_alive_tm > 2*period &&
789 rp->r_pid > 0 && !(rp->r_flags & RS_NOPINGREPLY)) {
790 if(rs_verbose)
791 printf("RS: %s reported late\n", srv_to_string(rp));
792 if(lookup_slot_by_flags(RS_INITIALIZING)) {
793 /* Skip for now. */
794 if(rs_verbose)
795 printf("RS: %s gets a free pass\n",
796 srv_to_string(rp));
797 rp->r_alive_tm = now;
798 rp->r_check_tm = now+1;
799 continue;
801 rp->r_flags |= RS_NOPINGREPLY;
802 crash_service(rp); /* simulate crash */
806 /* No answer pending. Check if a period expired since the last
807 * check and, if so request the system service's status.
809 else if (now - rp->r_check_tm > rp->r_period) {
810 notify(rpub->endpoint); /* request status */
811 rp->r_check_tm = now; /* mark time */
817 /* Reschedule a synchronous alarm for the next period. */
818 if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
819 panic("couldn't set alarm: %d", s);
822 /*===========================================================================*
823 * do_sigchld *
824 *===========================================================================*/
825 void do_sigchld()
827 /* PM informed us that there are dead children to cleanup. Go get them. */
828 pid_t pid;
829 int status;
830 struct rproc *rp;
831 struct rproc **rps;
832 int i, nr_rps;
834 if(rs_verbose)
835 printf("RS: got SIGCHLD signal, cleaning up dead children\n");
837 while ( (pid = waitpid(-1, &status, WNOHANG)) != 0 ) {
838 rp = lookup_slot_by_pid(pid);
839 if(rp != NULL) {
841 if(rs_verbose)
842 printf("RS: %s exited via another signal manager\n",
843 srv_to_string(rp));
845 /* The slot is still there. This means RS is not the signal
846 * manager assigned to the process. Ignore the event but
847 * free slots for all the service instances and send a late
848 * reply if necessary.
850 get_service_instances(rp, &rps, &nr_rps);
851 for(i=0;i<nr_rps;i++) {
852 if(rupdate.flags & RS_UPDATING) {
853 rupdate.flags &= ~RS_UPDATING;
855 free_slot(rps[i]);
861 /*===========================================================================*
862 * do_getsysinfo *
863 *===========================================================================*/
864 int do_getsysinfo(m_ptr)
865 message *m_ptr;
867 vir_bytes src_addr, dst_addr;
868 int dst_proc;
869 size_t len;
870 int s;
872 /* Check if the call can be allowed. */
873 if((s = check_call_permission(m_ptr->m_source, 0, NULL)) != OK)
874 return s;
876 switch(m_ptr->SI_WHAT) {
877 case SI_PROC_TAB:
878 src_addr = (vir_bytes) rproc;
879 len = sizeof(struct rproc) * NR_SYS_PROCS;
880 break;
881 case SI_PROCPUB_TAB:
882 src_addr = (vir_bytes) rprocpub;
883 len = sizeof(struct rprocpub) * NR_SYS_PROCS;
884 break;
885 default:
886 return(EINVAL);
889 if (len != m_ptr->SI_SIZE)
890 return(EINVAL);
892 dst_proc = m_ptr->m_source;
893 dst_addr = (vir_bytes) m_ptr->SI_WHERE;
894 return sys_datacopy(SELF, src_addr, dst_proc, dst_addr, len);
897 /*===========================================================================*
898 * do_lookup *
899 *===========================================================================*/
900 int do_lookup(m_ptr)
901 message *m_ptr;
903 static char namebuf[100];
904 int len, r;
905 struct rproc *rrp;
906 struct rprocpub *rrpub;
908 len = m_ptr->RS_NAME_LEN;
910 if(len < 2 || len >= sizeof(namebuf)) {
911 printf("RS: len too weird (%d)\n", len);
912 return EINVAL;
915 if((r=sys_vircopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_NAME,
916 SELF, (vir_bytes) namebuf, len)) != OK) {
917 printf("RS: name copy failed\n");
918 return r;
922 namebuf[len] = '\0';
924 rrp = lookup_slot_by_label(namebuf);
925 if(!rrp) {
926 return ESRCH;
928 rrpub = rrp->r_pub;
929 m_ptr->RS_ENDPOINT = rrpub->endpoint;
931 return OK;
934 /*===========================================================================*
935 * check_request *
936 *===========================================================================*/
937 static int check_request(struct rs_start *rs_start)
939 /* Verify scheduling parameters */
940 if (rs_start->rss_scheduler != KERNEL &&
941 (rs_start->rss_scheduler < 0 ||
942 rs_start->rss_scheduler > LAST_SPECIAL_PROC_NR)) {
943 printf("RS: check_request: invalid scheduler %d\n",
944 rs_start->rss_scheduler);
945 return EINVAL;
947 if (rs_start->rss_priority >= NR_SCHED_QUEUES) {
948 printf("RS: check_request: priority %u out of range\n",
949 rs_start->rss_priority);
950 return EINVAL;
952 if (rs_start->rss_quantum <= 0) {
953 printf("RS: check_request: quantum %u out of range\n",
954 rs_start->rss_quantum);
955 return EINVAL;
958 if (rs_start->rss_cpu == RS_CPU_BSP)
959 rs_start->rss_cpu = machine.bsp_id;
960 else if (rs_start->rss_cpu == RS_CPU_DEFAULT) {
961 /* keep the default value */
962 } else if (rs_start->rss_cpu < 0)
963 return EINVAL;
964 else if (rs_start->rss_cpu > machine.processors_count) {
965 printf("RS: cpu number %d out of range 0-%d, using BSP\n",
966 rs_start->rss_cpu, machine.processors_count);
967 rs_start->rss_cpu = machine.bsp_id;
970 /* Verify signal manager. */
971 if (rs_start->rss_sigmgr != SELF &&
972 (rs_start->rss_sigmgr < 0 ||
973 rs_start->rss_sigmgr > LAST_SPECIAL_PROC_NR)) {
974 printf("RS: check_request: invalid signal manager %d\n",
975 rs_start->rss_sigmgr);
976 return EINVAL;
979 return OK;