Implement merging SYSINIT's from preloaded KLD modules. This means we

check off SYSINIT entries as they are run, and when more arrive, we re-sort
and restart (skipping the already-run entries).
This can *only* be done after KMEM (and malloc) is up and running - this is
fine because KLD is the only consumer of this and it's done after that.
The nice thing about this is that the SYSINIT's within preloaded KLD modules
are executed in their natural order.  It should be possible to register
devices for the probes which follow, etc.  (soon.. several key things
prevent this, such as use of linker sets for things like pci devices).
This commit is contained in:
Peter Wemm 1998-10-09 23:42:47 +00:00
parent cfb55a60f9
commit 94e9d7c12d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=40154

View File

@ -39,7 +39,7 @@
* SUCH DAMAGE.
*
* @(#)init_main.c 8.9 (Berkeley) 1/21/94
* $Id: init_main.c,v 1.96 1998/09/14 19:56:40 sos Exp $
* $Id: init_main.c,v 1.97 1998/10/06 11:55:40 dfr Exp $
*/
#include "opt_devfs.h"
@ -60,6 +60,7 @@
#include <sys/sysproto.h>
#include <sys/vmmeter.h>
#include <sys/unistd.h>
#include <sys/malloc.h>
#include <machine/cpu.h>
@ -122,6 +123,48 @@ void __main() {}
*/
SYSINIT(placeholder, SI_SUB_DUMMY,SI_ORDER_ANY, NULL, NULL)
/*
* The sysinit table itself. Items are checked off as the are run.
* If we want to register new sysinit types, add them to newsysinit.
*/
struct sysinit **sysinit = (struct sysinit **)sysinit_set.ls_items;
struct sysinit **newsysinit;
/*
* Merge a new sysinit set into the current set, reallocating it if
* necessary. This can only be called after malloc is running.
*/
void
sysinit_add(set)
struct sysinit **set;
{
struct sysinit **newset;
struct sysinit **sipp;
struct sysinit **xipp;
int count = 0;
for (sipp = sysinit; *sipp; sipp++)
count++;
for (sipp = set; *sipp; sipp++)
count++;
if (newsysinit)
for (sipp = set; *sipp; sipp++)
count++;
newset = malloc(count * sizeof(*sipp), M_TEMP, M_NOWAIT);
if (newset == NULL)
panic("cannot malloc for sysinit");
xipp = newset;
for (sipp = sysinit; *sipp; sipp++)
*xipp++ = *sipp;
for (sipp = set; *sipp; sipp++)
*xipp++ = *sipp;
if (newsysinit) {
for (sipp = newsysinit; *sipp; sipp++)
*xipp++ = *sipp;
free(newset, M_TEMP);
}
newsysinit = newset;
}
/*
* System startup; initialize the world, create process 0, mount root
@ -149,17 +192,15 @@ main(framep)
*/
init_framep = framep;
restart:
/*
* Perform a bubble sort of the system initialization objects by
* their subsystem (primary key) and order (secondary key).
*
* Since some things care about execution order, this is the
* operation which ensures continued function.
*/
for( sipp = (struct sysinit **)sysinit_set.ls_items; *sipp; sipp++) {
for( xipp = sipp + 1; *xipp; xipp++) {
if( (*sipp)->subsystem < (*xipp)->subsystem ||
( (*sipp)->subsystem == (*xipp)->subsystem &&
for (sipp = sysinit; *sipp; sipp++) {
for (xipp = sipp + 1; *xipp; xipp++) {
if ((*sipp)->subsystem < (*xipp)->subsystem ||
((*sipp)->subsystem == (*xipp)->subsystem &&
(*sipp)->order < (*xipp)->order))
continue; /* skip*/
save = *sipp;
@ -175,15 +216,18 @@ main(framep)
* The last item on the list is expected to be the scheduler,
* which will not return.
*/
for( sipp = (struct sysinit **)sysinit_set.ls_items; *sipp; sipp++) {
for (sipp = sysinit; *sipp; sipp++) {
if( (*sipp)->subsystem == SI_SUB_DUMMY)
if ((*sipp)->subsystem == SI_SUB_DUMMY)
continue; /* skip dummy task(s)*/
if ((*sipp)->subsystem == SI_SUB_DONE)
continue;
switch( (*sipp)->type) {
case SI_TYPE_DEFAULT:
/* no special processing*/
(*((*sipp)->func))( (*sipp)->udata);
(*((*sipp)->func))((*sipp)->udata);
break;
case SI_TYPE_KTHREAD:
@ -204,7 +248,19 @@ main(framep)
break;
default:
panic( "init_main: unrecognized init type");
panic("init_main: unrecognized init type");
}
/* Check off the one we're just done */
(*sipp)->subsystem = SI_SUB_DONE;
/* Check if we've installed more sysinit items via KLD */
if (newsysinit != NULL) {
if (sysinit != (struct sysinit **)sysinit_set.ls_items)
free(sysinit, M_TEMP);
sysinit = newsysinit;
newsysinit = NULL;
goto restart;
}
}