summaryrefslogtreecommitdiffstats
path: root/sys/kern/init_main.c
diff options
context:
space:
mode:
authormiod <miod@openbsd.org>2004-11-23 19:08:52 +0000
committermiod <miod@openbsd.org>2004-11-23 19:08:52 +0000
commit240d2236f811b7e984e86e20a9440443c13d6a1d (patch)
tree1ea05aa989f00b03b0e9838d68df71bd97532a7e /sys/kern/init_main.c
parentsync (diff)
downloadwireguard-openbsd-240d2236f811b7e984e86e20a9440443c13d6a1d.tar.xz
wireguard-openbsd-240d2236f811b7e984e86e20a9440443c13d6a1d.zip
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/kern/init_main.c')
-rw-r--r--sys/kern/init_main.c88
1 files changed, 66 insertions, 22 deletions
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);
/*