From ba19c83fd63825da5c2028bd8554e0220b682f82 Mon Sep 17 00:00:00 2001 From: David van Moolenbroek Date: Mon, 5 Dec 2011 10:51:30 +0100 Subject: [PATCH] RS: support for endpoint-changing driver restarts --- servers/rs/const.h | 1 + servers/rs/exec.c | 6 ++--- servers/rs/main.c | 2 +- servers/rs/manager.c | 59 ++++++++++++++++++++++++++++++++++++++------ servers/rs/request.c | 2 ++ servers/rs/type.h | 6 +++++ 6 files changed, 65 insertions(+), 11 deletions(-) diff --git a/servers/rs/const.h b/servers/rs/const.h index 9b0be8e26..87733ef6e 100644 --- a/servers/rs/const.h +++ b/servers/rs/const.h @@ -33,6 +33,7 @@ #define RS_INITIALIZING 0x040 /* set when init is in progress */ #define RS_UPDATING 0x080 /* set when update is in progress */ #define RS_ACTIVE 0x100 /* set for the active instance of a service */ +#define RS_REINCARNATE 0x200 /* after exit, restart with a new endpoint */ /* Sys flag values. */ #define SF_CORE_SRV 0x001 /* set for core system services */ diff --git a/servers/rs/exec.c b/servers/rs/exec.c index 57a24ced6..1e5556b54 100644 --- a/servers/rs/exec.c +++ b/servers/rs/exec.c @@ -23,16 +23,16 @@ static int load_aout(struct exec_info *execi); static int load_elf(struct exec_info *execi); /* Array of loaders for different object formats */ -struct exec_loaders { +static struct exec_loaders { int (*load_object)(struct exec_info *); -} static const exec_loaders[] = { +} const exec_loaders[] = { { load_aout }, { load_elf }, { NULL } }; int srv_execve(int proc_e, char *exec, size_t exec_len, char **argv, - char **Xenvp) + char **UNUSED(Xenvp)) { char * const *ap; char * const *ep; diff --git a/servers/rs/main.c b/servers/rs/main.c index fa1d55b02..34b376b22 100644 --- a/servers/rs/main.c +++ b/servers/rs/main.c @@ -161,7 +161,7 @@ PRIVATE void sef_local_startup() /*===========================================================================* * sef_cb_init_fresh * *===========================================================================*/ -PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info) +PRIVATE int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info)) { /* Initialize the reincarnation server. */ struct boot_image *ip; diff --git a/servers/rs/manager.c b/servers/rs/manager.c index c5eba016e..d9dd58075 100644 --- a/servers/rs/manager.c +++ b/servers/rs/manager.c @@ -423,8 +423,9 @@ struct rproc *rp; srv_kill(rp->r_pid, SIGKILL); } - /* Free slot */ - free_slot(rp); + /* Free slot, unless we're about to reuse it */ + if (!(rp->r_flags & RS_REINCARNATE)) + free_slot(rp); } /*===========================================================================* @@ -941,6 +942,40 @@ PUBLIC void activate_service(struct rproc *rp, struct rproc *ex_rp) } } +/*===========================================================================* + * reincarnate_service * + *===========================================================================*/ +PUBLIC void reincarnate_service(struct rproc *rp) +{ +/* Restart a service as if it were never started before. */ + struct rprocpub *rpub; + int i; + + rpub = rp->r_pub; + + rp->r_flags &= RS_IN_USE; + rp->r_pid = -1; + rproc_ptr[_ENDPOINT_P(rpub->endpoint)] = NULL; + + /* Restore original IRQ and I/O range tables in the priv struct. This is the + * only part of the privilege structure that can be modified by processes + * other than RS itself. + */ + rp->r_priv.s_nr_irq = rp->r_nr_irq; + for (i = 0; i < rp->r_nr_irq; i++) + rp->r_priv.s_irq_tab[i] = rp->r_irq_tab[i]; + rp->r_priv.s_nr_io_range = rp->r_nr_io_range; + for (i = 0; i < rp->r_nr_io_range; i++) + rp->r_priv.s_io_tab[i] = rp->r_io_tab[i]; + + rp->r_old_rp = NULL; + rp->r_new_rp = NULL; + rp->r_prev_rp = NULL; + rp->r_next_rp = NULL; + + start_service(rp); +} + /*===========================================================================* * terminate_service * *===========================================================================*/ @@ -959,9 +994,10 @@ PUBLIC void terminate_service(struct rproc *rp) /* Deal with failures during initialization. */ if(rp->r_flags & RS_INITIALIZING) { - printf("RS: service '%s' exited during initialization\n", rpub->label); + if(rs_verbose) + printf("RS: service '%s' exited during initialization\n", + rpub->label); rp->r_flags |= RS_EXITING; /* don't restart. */ - sys_sysctl_stacktrace(rp->r_pub->endpoint); /* If updating, rollback. */ if(rp->r_flags & RS_UPDATING) { @@ -995,6 +1031,14 @@ PUBLIC void terminate_service(struct rproc *rp) for(i=0;ir_flags & RS_REINCARNATE) { + reincarnate_service(rp); + } } else if(rp->r_flags & RS_REFRESHING) { /* Restart service. */ @@ -1335,9 +1379,9 @@ endpoint_t source; printf("RS: edit_slot: too many IRQs requested\n"); return EINVAL; } - rp->r_priv.s_nr_irq= rs_start->rss_nr_irq; + rp->r_nr_irq= rp->r_priv.s_nr_irq= rs_start->rss_nr_irq; for (i= 0; ir_priv.s_nr_irq; i++) { - rp->r_priv.s_irq_tab[i]= rs_start->rss_irq[i]; + rp->r_irq_tab[i]= rp->r_priv.s_irq_tab[i]= rs_start->rss_irq[i]; if(rs_verbose) printf("RS: edit_slot: IRQ %d\n", rp->r_priv.s_irq_tab[i]); } @@ -1353,11 +1397,12 @@ endpoint_t source; printf("RS: edit_slot: too many I/O ranges requested\n"); return EINVAL; } - rp->r_priv.s_nr_io_range= rs_start->rss_nr_io; + rp->r_nr_io_range= rp->r_priv.s_nr_io_range= rs_start->rss_nr_io; for (i= 0; ir_priv.s_nr_io_range; i++) { rp->r_priv.s_io_tab[i].ior_base= rs_start->rss_io[i].base; rp->r_priv.s_io_tab[i].ior_limit= rs_start->rss_io[i].base+rs_start->rss_io[i].len-1; + rp->r_io_tab[i] = rp->r_priv.s_io_tab[i]; if(rs_verbose) printf("RS: edit_slot: I/O [%x..%x]\n", rp->r_priv.s_io_tab[i].ior_base, diff --git a/servers/rs/request.c b/servers/rs/request.c index eccf60ed5..f664f357d 100755 --- a/servers/rs/request.c +++ b/servers/rs/request.c @@ -426,6 +426,8 @@ PUBLIC int do_init_ready(message *m_ptr) if(rs_verbose) printf("RS: %s initialization error: %s\n", srv_to_string(rp), init_strerror(result)); + if (result == ERESTART) + rp->r_flags |= RS_REINCARNATE; crash_service(rp); /* simulate crash */ return EDONTREPLY; } diff --git a/servers/rs/type.h b/servers/rs/type.h index 378f26198..17e92d1d2 100644 --- a/servers/rs/type.h +++ b/servers/rs/type.h @@ -67,6 +67,12 @@ struct rproc { int r_quantum; int r_cpu; + /* Backup values from the privilege structure. */ + struct io_range r_io_tab[NR_IO_RANGE]; + int r_nr_io_range; + int r_irq_tab[NR_IRQ]; + int r_nr_irq; + char r_ipc_list[MAX_IPC_LIST]; int r_nr_control; char r_control[RS_NR_CONTROL][RS_MAX_LABEL_LEN]; -- 2.44.0