Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Add a `config_pending' semaphore to block mounting of th...
details: https://anonhg.NetBSD.org/src/rev/8d6b888ba892
branches: trunk
changeset: 481199:8d6b888ba892
user: thorpej <thorpej%NetBSD.org@localhost>
date: Mon Jan 24 18:03:19 2000 +0000
description:
Add a `config_pending' semaphore to block mounting of the root file system
until all device driver discovery threads have had a chance to do their
work. This in turn blocks initproc's exec of init(8) until root is
mounted and process start times and CWD info has been fixed up.
Addresses kern/9247.
diffstat:
sys/kern/init_main.c | 101 +++++++++++++++++++++++++++++++++++-----------
sys/kern/subr_autoconf.c | 31 +++++++++++++-
sys/sys/device.h | 6 ++-
3 files changed, 112 insertions(+), 26 deletions(-)
diffs (266 lines):
diff -r e4232d57f735 -r 8d6b888ba892 sys/kern/init_main.c
--- a/sys/kern/init_main.c Mon Jan 24 17:57:34 2000 +0000
+++ b/sys/kern/init_main.c Mon Jan 24 18:03:19 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: init_main.c,v 1.162 2000/01/19 20:05:50 thorpej Exp $ */
+/* $NetBSD: init_main.c,v 1.163 2000/01/24 18:03:19 thorpej Exp $ */
/*
* Copyright (c) 1995 Christopher G. Demetriou. All rights reserved.
@@ -139,6 +139,8 @@
struct timeval boottime;
struct timeval runtime;
+__volatile int start_init_exec; /* semaphore for start_init() */
+
static void check_console __P((struct proc *p));
static void start_init __P((void *));
static void start_pagedaemon __P((void *));
@@ -367,11 +369,50 @@
kmstartup();
#endif
+ /*
+ * Initialize signal-related data structures, and signal state
+ * for proc0.
+ */
+ signal_init();
+ p->p_sigacts = &sigacts0;
+ siginit(p);
+
/* Kick off timeout driven events by calling first time. */
roundrobin(NULL);
schedcpu(NULL);
- /* Determine the root and dump devices. */
+ /*
+ * 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, 0, SIGCHLD, NULL, 0, NULL, &initproc))
+ panic("fork init");
+ cpu_set_kpc(initproc, start_init, initproc);
+
+ /*
+ * 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);
+
+ /*
+ * Now that autoconfiguration has completed, we can determine
+ * the root and dump devices.
+ */
cpu_rootconf();
cpu_dumpconf();
@@ -400,49 +441,55 @@
VREF(cwdi0.cwdi_cdir);
VOP_UNLOCK(rootvnode, 0);
cwdi0.cwdi_rdir = NULL;
- uvm_swap_init();
+
+ /*
+ * 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_cwdi->cwdi_cdir = rootvnode;
+ VREF(initproc->p_cwdi->cwdi_cdir);
+ initproc->p_cwdi->cwdi_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.
*/
- p->p_stats->p_start = runtime = mono_time = boottime = time;
- p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0;
+ proclist_lock_read();
+ s = splclock(); /* so we can read time */
+ for (p = LIST_FIRST(&allproc); p != NULL;
+ p = LIST_NEXT(p, p_list)) {
+ p->p_stats->p_start = runtime = mono_time = boottime = time;
+ p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0;
+ }
+ splx(s);
+ proclist_unlock_read();
- /*
- * Initialize signal-related data structures, and signal state
- * for proc0.
- */
- signal_init();
- p->p_sigacts = &sigacts0;
- siginit(p);
-
- /* Create process 1 (init(8)). */
- if (fork1(p, 0, SIGCHLD, NULL, 0, NULL, &initproc))
- panic("fork init");
- cpu_set_kpc(initproc, start_init, initproc);
-
- /* Create process 2, the pageout daemon kernel thread. */
+ /* Create the pageout daemon kernel thread. */
+ uvm_swap_init();
if (kthread_create1(start_pagedaemon, NULL, NULL, "pagedaemon"))
panic("fork pagedaemon");
- /* Create process 3, the process reaper kernel thread. */
+ /* Create the process reaper kernel thread. */
if (kthread_create1(start_reaper, NULL, NULL, "reaper"))
panic("fork reaper");
- /* Create process 4, the filesystem syncer */
+ /* Create the filesystem syncer kernel thread. */
if (kthread_create1(sched_sync, NULL, NULL, "ioflush"))
panic("fork syncer");
- /* Create any other deferred kernel threads. */
- kthread_run_deferred_queue();
-
#if defined(MULTIPROCESSOR)
/* Boot the secondary processors. */
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 */
@@ -501,6 +548,12 @@
strncpy(p->p_comm, "init", MAXCOMLEN);
/*
+ * 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);
+
+ /*
* This is not the right way to do this. We really should
* hand-craft a descriptor onto /dev/console to hand to init,
* but that's a _lot_ more work, and the benefit from this easy
diff -r e4232d57f735 -r 8d6b888ba892 sys/kern/subr_autoconf.c
--- a/sys/kern/subr_autoconf.c Mon Jan 24 17:57:34 2000 +0000
+++ b/sys/kern/subr_autoconf.c Mon Jan 24 18:03:19 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: subr_autoconf.c,v 1.46 2000/01/18 07:45:04 cgd Exp $ */
+/* $NetBSD: subr_autoconf.c,v 1.47 2000/01/24 18:03:19 thorpej Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -52,6 +52,7 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/errno.h>
+#include <sys/proc.h>
#include <machine/limits.h>
/*
@@ -95,6 +96,8 @@
struct devicelist alldevs; /* list of all devices */
struct evcntlist allevents; /* list of all event counters */
+__volatile int config_pending; /* semaphore for mountroot */
+
/*
* Configure the system's hardware.
*/
@@ -611,6 +614,7 @@
dc->dc_dev = dev;
dc->dc_func = func;
TAILQ_INSERT_TAIL(&deferred_config_queue, dc, dc_queue);
+ config_pending_incr();
}
/*
@@ -647,6 +651,7 @@
dc->dc_dev = dev;
dc->dc_func = func;
TAILQ_INSERT_TAIL(&interrupt_config_queue, dc, dc_queue);
+ config_pending_incr();
}
/*
@@ -665,11 +670,35 @@
TAILQ_REMOVE(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()
+{
+
+ config_pending++;
+}
+
+void
+config_pending_decr()
+{
+
+#ifdef DIAGNOSTIC
+ if (config_pending == 0)
+ panic("config_pending_decr: config_pending == 0");
+#endif
+ config_pending--;
+ if (config_pending == 0)
+ wakeup((void *)&config_pending);
+}
+
+/*
* Attach an event. These must come from initially-zero space (see
* commented-out assignments below), but that occurs naturally for
* device instance variables.
diff -r e4232d57f735 -r 8d6b888ba892 sys/sys/device.h
--- a/sys/sys/device.h Mon Jan 24 17:57:34 2000 +0000
+++ b/sys/sys/device.h Mon Jan 24 18:03:19 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: device.h,v 1.35 1999/09/23 15:14:58 minoura Exp $ */
+/* $NetBSD: device.h,v 1.36 2000/01/24 18:03:20 thorpej Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -171,6 +171,8 @@
extern struct devicelist alldevs; /* list of all devices */
extern struct evcntlist allevents; /* list of all event counters */
+extern __volatile int config_pending; /* semaphore for mountroot */
+
void configure __P((void));
struct cfdata *config_search __P((cfmatch_t, struct device *, void *));
struct cfdata *config_rootsearch __P((cfmatch_t, char *, void *));
@@ -184,6 +186,8 @@
int config_deactivate __P((struct device *));
void config_defer __P((struct device *, void (*)(struct device *)));
void config_interrupts __P((struct device *, void (*)(struct device *)));
+void config_pending_incr __P((void));
+void config_pending_decr __P((void));
#if defined(__alpha__) || defined(hp300) || defined(__i386__) || \
defined(__sparc__) || defined(__vax__) || defined(x68k)
void device_register __P((struct device *, void *));
Home |
Main Index |
Thread Index |
Old Index