RS: support for endpoint-changing driver restarts

This commit is contained in:
David van Moolenbroek 2011-12-05 10:51:30 +01:00
parent 01015cc0e2
commit ba19c83fd6
6 changed files with 65 additions and 11 deletions

View file

@ -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 */

View file

@ -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;

View file

@ -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;

View file

@ -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;i<nr_rps;i++) {
cleanup_service(rps[i]);
}
/* If the service is reincarnating, its slot has not been cleaned up.
* Check for this flag now, and attempt to start the service again.
* If this fails, start_service() itself will perform cleanup.
*/
if (rp->r_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; i<rp->r_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; i<rp->r_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,

View file

@ -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;
}

View file

@ -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];