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