diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2004-11-23 19:08:56 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2004-11-23 19:08:56 +0000 |
commit | 17ea3d00ad6ab51534668f0fa412c36101fa7229 (patch) | |
tree | eb0194f91fff140acba852d73e1785ae62e67581 /sys | |
parent | 6506a735d9eb4cb6f15cdff9ad2e4fff2e0e8bdb (diff) |
Create the init process earlier, before the root filesystem is mounted,
and have it stall on a semaphore. This allows all kthread creations which
could have been requested during autoconf to be processed before root
is mounted as well.
This causes umass devices attached to any usb with flags 1 (such as on macppc)
to configure properly instead of panicing the kernel at mountroot time.
From NetBSD; tested by various.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/compat/linux/linux_sched.c | 5 | ||||
-rw-r--r-- | sys/compat/netbsd/netbsd_misc.c | 4 | ||||
-rw-r--r-- | sys/dev/usb/usb_port.h | 5 | ||||
-rw-r--r-- | sys/kern/init_main.c | 88 | ||||
-rw-r--r-- | sys/kern/kern_fork.c | 25 | ||||
-rw-r--r-- | sys/kern/kern_kthread.c | 9 | ||||
-rw-r--r-- | sys/kern/subr_autoconf.c | 30 | ||||
-rw-r--r-- | sys/sys/device.h | 5 | ||||
-rw-r--r-- | sys/sys/proc.h | 4 |
9 files changed, 128 insertions, 47 deletions
diff --git a/sys/compat/linux/linux_sched.c b/sys/compat/linux/linux_sched.c index c5b1b008db9..4521fee96e6 100644 --- a/sys/compat/linux/linux_sched.c +++ b/sys/compat/linux/linux_sched.c @@ -1,4 +1,4 @@ -/* $OpenBSD: linux_sched.c,v 1.4 2004/06/13 21:49:23 niklas Exp $ */ +/* $OpenBSD: linux_sched.c,v 1.5 2004/11/23 19:08:52 miod Exp $ */ /* $NetBSD: linux_sched.c,v 1.6 2000/05/28 05:49:05 thorpej Exp $ */ /*- @@ -96,7 +96,8 @@ linux_sys_clone(p, v, retval) * or down. So, we pass a stack size of 0, so that the code * that makes this adjustment is a noop. */ - return (fork1(p, sig, flags, SCARG(uap, stack), 0, NULL, NULL, retval)); + return (fork1(p, sig, flags, SCARG(uap, stack), 0, NULL, NULL, retval, + NULL)); } int diff --git a/sys/compat/netbsd/netbsd_misc.c b/sys/compat/netbsd/netbsd_misc.c index b8a7b984103..627c5cb1d83 100644 --- a/sys/compat/netbsd/netbsd_misc.c +++ b/sys/compat/netbsd/netbsd_misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: netbsd_misc.c,v 1.13 2003/06/02 23:28:00 millert Exp $ */ +/* $OpenBSD: netbsd_misc.c,v 1.14 2004/11/23 19:08:54 miod Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1991, 1993 @@ -57,7 +57,7 @@ netbsd_sys___vfork14(p, v, retval) register_t *retval; { return (fork1(p, SIGCHLD, FORK_PPWAIT|FORK_SHAREVM, NULL, 0, NULL, - NULL, retval)); + NULL, retval, NULL)); } /* XXX syncs whole file */ diff --git a/sys/dev/usb/usb_port.h b/sys/dev/usb/usb_port.h index c830e6e1820..dab4ad72e3a 100644 --- a/sys/dev/usb/usb_port.h +++ b/sys/dev/usb/usb_port.h @@ -1,4 +1,4 @@ -/* $OpenBSD: usb_port.h,v 1.52 2004/11/08 22:01:02 dlg Exp $ */ +/* $OpenBSD: usb_port.h,v 1.53 2004/11/23 19:08:54 miod Exp $ */ /* $NetBSD: usb_port.h,v 1.62 2003/02/15 18:33:30 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/usb_port.h,v 1.21 1999/11/17 22:33:47 n_hibma Exp $ */ @@ -279,9 +279,6 @@ typedef struct proc *usb_proc_ptr; #define usb_kthread_create1 kthread_create #define usb_kthread_create kthread_create_deferred -#define config_pending_incr() -#define config_pending_decr() - typedef int usb_malloc_type; #define Ether_ifattach(ifp, eaddr) ether_ifattach(ifp) diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index 196065727d4..119bcecce17 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: init_main.c,v 1.119 2004/07/28 17:15:12 tholo Exp $ */ +/* $OpenBSD: init_main.c,v 1.120 2004/11/23 19:08:55 miod Exp $ */ /* $NetBSD: init_main.c,v 1.84.4.1 1996/06/02 09:08:06 mrg Exp $ */ /* @@ -126,6 +126,7 @@ struct timeval boottime; struct timeval runtime; #endif int ncpus = 1; +__volatile int start_init_exec; /* semaphore for start_init() */ #if !defined(NO_PROPOLICE) long __guard[8]; @@ -185,7 +186,6 @@ main(framep) struct timeval rtv; quad_t lim; int s, i; - register_t rval[2]; extern struct pdevinit pdevinit[]; extern void scheduler_start(void); extern void disk_init(void); @@ -399,6 +399,34 @@ main(framep) /* Start the scheduler */ scheduler_start(); + /* + * Create process 1 (init(8)). We do this now, as Unix has + * historically had init be process 1, and changing this would + * probably upset a lot of people. + * + * Note that process 1 won't immediately exec init(8), but will + * wait for us to inform it that the root file system has been + * mounted. + */ + if (fork1(p, SIGCHLD, FORK_FORK, NULL, 0, start_init, NULL, NULL, + &initproc)) + panic("fork init"); + + /* + * Create any kernel threads who's creation was deferred because + * initproc had not yet been created. + */ + kthread_run_deferred_queue(); + + /* + * Now that device driver threads have been created, wait for + * them to finish any deferred autoconfiguration. Note we don't + * need to lock this semaphore, since we haven't booted any + * secondary processors, yet. + */ + while (config_pending) + (void) tsleep((void *)&config_pending, PWAIT, "cfpend", 0); + dostartuphooks(); /* Configure root/swap devices */ @@ -419,6 +447,15 @@ main(framep) p->p_fd->fd_rdir = NULL; /* + * Now that root is mounted, we can fixup initproc's CWD + * info. All other processes are kthreads, which merely + * share proc0's CWD info. + */ + initproc->p_fd->fd_cdir = rootvnode; + VREF(initproc->p_fd->fd_cdir); + initproc->p_fd->fd_rdir = NULL; + + /* * Now can look at time, having had a chance to verify the time * from the file system. Reset p->p_rtime as it may have been * munched in mi_switch() after the time got set. @@ -428,49 +465,45 @@ main(framep) #else boottime = mono_time = time; #endif - p->p_stats->p_start = boottime; -#ifdef __HAVE_CPUINFO - microuptime(&p->p_cpu->ci_schedstate.spc_runtime); -#else +#ifndef __HAVE_CPUINFO microuptime(&runtime); #endif - p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0; + LIST_FOREACH(p, &allproc, p_list) { + p->p_stats->p_start = boottime; +#ifdef __HAVE_CPUINFO + microuptime(&p->p_cpu->ci_schedstate.spc_runtime); +#endif + p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0; + } uvm_swap_init(); - /* Create process 1 (init(8)). */ - if (fork1(p, SIGCHLD, FORK_FORK, NULL, 0, start_init, NULL, rval)) - panic("fork init"); - - /* Create process 2, the pageout daemon kernel thread. */ + /* Create the pageout daemon kernel thread. */ if (kthread_create(uvm_pageout, NULL, NULL, "pagedaemon")) panic("fork pagedaemon"); - /* Create process 3, the reaper daemon kernel thread. */ + /* Create the reaper daemon kernel thread. */ if (kthread_create(start_reaper, NULL, NULL, "reaper")) panic("fork reaper"); - /* Create process 4, the cleaner daemon kernel thread. */ + /* Create the cleaner daemon kernel thread. */ if (kthread_create(start_cleaner, NULL, NULL, "cleaner")) panic("fork cleaner"); - /* Create process 5, the update daemon kernel thread. */ + /* Create the update daemon kernel thread. */ if (kthread_create(start_update, NULL, NULL, "update")) panic("fork update"); - /* Create process 6, the aiodone daemon kernel thread. */ + /* Create the aiodone daemon kernel thread. */ if (kthread_create(uvm_aiodone_daemon, NULL, NULL, "aiodoned")) panic("fork aiodoned"); #ifdef CRYPTO - /* Create process 7, the crypto kernel thread. */ + /* Create the crypto kernel thread. */ if (kthread_create(start_crypto, NULL, NULL, "crypto")) panic("crypto thread"); #endif /* CRYPTO */ - /* Create any other deferred kernel threads. */ - kthread_run_deferred_queue(); - microtime(&rtv); srandom((u_long)(rtv.tv_sec ^ rtv.tv_usec)); @@ -481,6 +514,12 @@ main(framep) cpu_boot_secondary_processors(); #endif + /* + * Okay, now we can let init(8) exec! It's off to userland! + */ + start_init_exec = 1; + wakeup((void *)&start_init_exec); + /* The scheduler is an infinite loop. */ uvm_scheduler(); /* NOTREACHED */ @@ -535,11 +574,16 @@ start_init(arg) char flags[4], *flagsp; char **pathp, *path, *ucp, **uap, *arg0, *arg1 = NULL; - initproc = p; - /* * Now in process 1. */ + + /* + * Wait for main() to tell us that it's safe to exec. + */ + while (start_init_exec == 0) + (void) tsleep((void *)&start_init_exec, PWAIT, "initexec", 0); + check_console(p); /* diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 4fc2dd5c8f0..eee21a8231c 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_fork.c,v 1.72 2004/08/06 22:31:30 mickey Exp $ */ +/* $OpenBSD: kern_fork.c,v 1.73 2004/11/23 19:08:55 miod Exp $ */ /* $NetBSD: kern_fork.c,v 1.29 1996/02/09 18:59:34 christos Exp $ */ /* @@ -75,7 +75,8 @@ int pidtaken(pid_t); int sys_fork(struct proc *p, void *v, register_t *retval) { - return (fork1(p, SIGCHLD, FORK_FORK, NULL, 0, NULL, NULL, retval)); + return (fork1(p, SIGCHLD, FORK_FORK, NULL, 0, NULL, + NULL, retval, NULL)); } /*ARGSUSED*/ @@ -83,7 +84,7 @@ int sys_vfork(struct proc *p, void *v, register_t *retval) { return (fork1(p, SIGCHLD, FORK_VFORK|FORK_PPWAIT, NULL, 0, NULL, - NULL, retval)); + NULL, retval, NULL)); } int @@ -121,7 +122,7 @@ sys_rfork(struct proc *p, void *v, register_t *retval) if (rforkflags & RFMEM) flags |= FORK_SHAREVM; - return (fork1(p, SIGCHLD, flags, NULL, 0, NULL, NULL, retval)); + return (fork1(p, SIGCHLD, flags, NULL, 0, NULL, NULL, retval, NULL)); } /* print the 'table full' message once per 10 seconds */ @@ -129,7 +130,8 @@ struct timeval fork_tfmrate = { 10, 0 }; int fork1(struct proc *p1, int exitsig, int flags, void *stack, size_t stacksize, - void (*func)(void *), void *arg, register_t *retval) + void (*func)(void *), void *arg, register_t *retval, + struct proc **rnewprocp) { struct proc *p2; uid_t uid; @@ -354,6 +356,14 @@ fork1(struct proc *p1, int exitsig, int flags, void *stack, size_t stacksize, */ PRELE(p1); + /* + * Notify any interested parties about the new process. + */ + KNOTE(&p1->p_klist, NOTE_FORK | p2->p_pid); + + /* + * Update stats now that we know the fork was successfull. + */ uvmexp.forks++; if (flags & FORK_PPWAIT) uvmexp.forks_ppwait++; @@ -361,9 +371,10 @@ fork1(struct proc *p1, int exitsig, int flags, void *stack, size_t stacksize, uvmexp.forks_sharevm++; /* - * tell any interested parties about the new process + * Pass a pointer to the new process to the caller. */ - KNOTE(&p1->p_klist, NOTE_FORK | p2->p_pid); + if (rnewprocp != NULL) + *rnewprocp = p2; /* * Preserve synchronization semantics of vfork. If waiting for diff --git a/sys/kern/kern_kthread.c b/sys/kern/kern_kthread.c index 44c85d176a3..721c440c999 100644 --- a/sys/kern/kern_kthread.c +++ b/sys/kern/kern_kthread.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_kthread.c,v 1.22 2004/05/04 16:59:32 grange Exp $ */ +/* $OpenBSD: kern_kthread.c,v 1.23 2004/11/23 19:08:55 miod Exp $ */ /* $NetBSD: kern_kthread.c,v 1.3 1998/12/22 21:21:36 kleink Exp $ */ /*- @@ -65,7 +65,6 @@ kthread_create(void (*func)(void *), void *arg, struct proc **newpp, const char *fmt, ...) { struct proc *p2; - register_t rv[2]; int error; va_list ap; @@ -74,13 +73,11 @@ kthread_create(void (*func)(void *), void *arg, * descriptors and don't leave the exit status around for the * parent to wait for. */ - error = fork1(&proc0, 0, - FORK_SHAREVM|FORK_NOZOMBIE|FORK_SIGHAND, NULL, 0, func, arg, rv); + error = fork1(&proc0, 0, FORK_SHAREVM |FORK_NOZOMBIE |FORK_SIGHAND, + NULL, 0, func, arg, NULL, &p2); if (error) return (error); - p2 = pfind(rv[0]); - /* * Mark it as a system process and not a candidate for * swapping. diff --git a/sys/kern/subr_autoconf.c b/sys/kern/subr_autoconf.c index c378eac10e2..9cb03dbf82d 100644 --- a/sys/kern/subr_autoconf.c +++ b/sys/kern/subr_autoconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: subr_autoconf.c,v 1.38 2004/08/03 17:49:04 pefo Exp $ */ +/* $OpenBSD: subr_autoconf.c,v 1.39 2004/11/23 19:08:55 miod Exp $ */ /* $NetBSD: subr_autoconf.c,v 1.21 1996/04/04 06:06:18 cgd Exp $ */ /* @@ -51,6 +51,7 @@ #include <sys/systm.h> /* Extra stuff from Matthias Drochner <drochner@zelux6.zel.kfa-juelich.de> */ #include <sys/queue.h> +#include <sys/proc.h> #include "hotplug.h" @@ -101,6 +102,8 @@ void config_process_deferred_children(struct device *); struct devicelist alldevs; /* list of all devices */ struct evcntlist allevents; /* list of all event counters */ +__volatile int config_pending; /* semaphore for mountroot */ + /* * Initialize autoconfiguration data structures. This occurs before console * initialization as that might require use of this subsystem. Furthermore @@ -691,6 +694,7 @@ config_defer(dev, func) dc->dc_dev = dev; dc->dc_func = func; TAILQ_INSERT_TAIL(&deferred_config_queue, dc, dc_queue); + config_pending_incr(); } /* @@ -709,10 +713,34 @@ config_process_deferred_children(parent) TAILQ_REMOVE(&deferred_config_queue, dc, dc_queue); (*dc->dc_func)(dc->dc_dev); free(dc, M_DEVBUF); + config_pending_decr(); } } } +/* + * Manipulate the config_pending semaphore. + */ +void +config_pending_incr(void) +{ + + config_pending++; +} + +void +config_pending_decr(void) +{ + +#ifdef DIAGNOSTIC + if (config_pending == 0) + panic("config_pending_decr: config_pending == 0"); +#endif + config_pending--; + if (config_pending == 0) + wakeup((void *)&config_pending); +} + int config_detach_children(parent, flags) struct device *parent; diff --git a/sys/sys/device.h b/sys/sys/device.h index c06c4bc2831..95ea9f12939 100644 --- a/sys/sys/device.h +++ b/sys/sys/device.h @@ -1,4 +1,4 @@ -/* $OpenBSD: device.h,v 1.28 2004/11/17 14:12:59 deraadt Exp $ */ +/* $OpenBSD: device.h,v 1.29 2004/11/23 19:08:55 miod Exp $ */ /* $NetBSD: device.h,v 1.15 1996/04/09 20:55:24 cgd Exp $ */ /* @@ -185,6 +185,7 @@ extern struct devicelist alldevs; /* list of all devices */ extern struct evcntlist allevents; /* list of all event counters */ extern int autoconf_verbose; +extern __volatile int config_pending; /* semaphore for mountroot */ void config_init(void); void *config_search(cfmatch_t, struct device *, void *); @@ -203,6 +204,8 @@ struct device *config_make_softc(struct device *parent, struct cfdata *cf); void config_defer(struct device *, void (*)(struct device *)); void evcnt_attach(struct device *, const char *, struct evcnt *); +void config_pending_incr(void); +void config_pending_decr(void); struct device *device_lookup(struct cfdriver *, int unit); void device_ref(struct device *); diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 4ab6cfe9c9c..a8746d3eecf 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: proc.h,v 1.75 2004/07/22 15:42:11 art Exp $ */ +/* $OpenBSD: proc.h,v 1.76 2004/11/23 19:08:55 miod Exp $ */ /* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */ /*- @@ -421,7 +421,7 @@ void reaper(void); void exit1(struct proc *, int); void exit2(struct proc *); int fork1(struct proc *, int, int, void *, size_t, void (*)(void *), - void *, register_t *); + void *, register_t *, struct proc **); void rqinit(void); int groupmember(gid_t, struct ucred *); #if !defined(cpu_switch) |