Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/init_main.c
Show First 20 Lines • Show All 154 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
SYSINIT(placeholder, SI_SUB_DUMMY, SI_ORDER_ANY, NULL, NULL); | SYSINIT(placeholder, SI_SUB_DUMMY, SI_ORDER_ANY, NULL, NULL); | ||||
/* | /* | ||||
* The sysinit table itself. Items are checked off as the are run. | * The sysinit table itself. Items are checked off as the are run. | ||||
* If we want to register new sysinit types, add them to newsysinit. | * If we want to register new sysinit types, add them to newsysinit. | ||||
*/ | */ | ||||
SET_DECLARE(sysinit_set, struct sysinit); | SET_DECLARE(sysinit_set, struct sysinit); | ||||
struct sysinit **sysinit, **sysinit_end; | static struct sysinit **sysinit, **sysinit_end; | ||||
struct sysinit **newsysinit, **newsysinit_end; | static struct sysinit **newsysinit, **newsysinit_end; | ||||
/* | /* | ||||
* Compare two sysinit structures. | |||||
*/ | |||||
static int | |||||
sysinit_compare(struct sysinit **ppa, struct sysinit **ppb) | |||||
{ | |||||
if (ppa[0][0].subsystem > ppb[0][0].subsystem) | |||||
return (1); | |||||
else if (ppa[0][0].subsystem < ppb[0][0].subsystem) | |||||
return (-1); | |||||
else if (ppa[0][0].order > ppb[0][0].order) | |||||
return (1); | |||||
else if (ppa[0][0].order < ppb[0][0].order) | |||||
return (-1); | |||||
else | |||||
return (0); | |||||
} | |||||
/* | |||||
* Merge a new sysinit set into the current set, reallocating it if | * Merge a new sysinit set into the current set, reallocating it if | ||||
* necessary. This can only be called after malloc is running. | * necessary. This can only be called after malloc is running. | ||||
*/ | */ | ||||
void | void | ||||
sysinit_add(struct sysinit **set, struct sysinit **set_end) | sysinit_add(struct sysinit **set, struct sysinit **set_end) | ||||
{ | { | ||||
struct sysinit **newset; | struct sysinit **newset; | ||||
struct sysinit **sipp; | struct sysinit **ppa; | ||||
struct sysinit **xipp; | struct sysinit **ppb; | ||||
struct sysinit **ppc; | |||||
struct sysinit **end; | |||||
int count; | int count; | ||||
count = set_end - set; | count = set_end - set; | ||||
if (newsysinit) | if (newsysinit) | ||||
count += newsysinit_end - newsysinit; | count += newsysinit_end - newsysinit; | ||||
else | else | ||||
count += sysinit_end - sysinit; | count += sysinit_end - sysinit; | ||||
newset = malloc(count * sizeof(*sipp), M_TEMP, M_NOWAIT); | newset = malloc(count * sizeof(*newset), M_TEMP, M_NOWAIT); | ||||
if (newset == NULL) | if (newset == NULL) | ||||
panic("cannot malloc for sysinit"); | panic("Cannot allocate memory for sysinit_add()"); | ||||
xipp = newset; | |||||
if (newsysinit) | ppa = set; | ||||
for (sipp = newsysinit; sipp < newsysinit_end; sipp++) | ppb = newsysinit ? newsysinit : sysinit; | ||||
*xipp++ = *sipp; | end = newsysinit ? newsysinit_end : sysinit_end; | ||||
else | ppc = newset; | ||||
for (sipp = sysinit; sipp < sysinit_end; sipp++) | |||||
*xipp++ = *sipp; | /* Merge two sorted lists by picking the lowest element first. */ | ||||
for (sipp = set; sipp < set_end; sipp++) | |||||
*xipp++ = *sipp; | while (ppa != set_end && ppb != end) { | ||||
if (newsysinit) | switch (sysinit_compare(ppa, ppb)) { | ||||
case -1: | |||||
*ppc++ = *ppa++; | |||||
break; | |||||
case 0: | |||||
*ppc++ = *ppa++; | |||||
*ppc++ = *ppb++; | |||||
break; | |||||
default: | |||||
*ppc++ = *ppb++; | |||||
break; | |||||
} | |||||
} | |||||
while (ppa != set_end) | |||||
*ppc++ = *ppa++; | |||||
while (ppb != end) | |||||
*ppc++ = *ppb++; | |||||
free(newsysinit, M_TEMP); | free(newsysinit, M_TEMP); | ||||
newsysinit = newset; | newsysinit = newset; | ||||
newsysinit_end = newset + count; | newsysinit_end = newset + count; | ||||
} | } | ||||
/* | |||||
* Sort a sysinit or sysuninit set. The entries should already have | |||||
* been sorted, and this function is basically a O(N) dummy operation! | |||||
imp: Won't klds create unsorted entries at the end? | |||||
hselaskyAuthorUnsubmitted Done Inline ActionsThe KLDs loaded at boot, also have a sorted init and uninit section after my change. That's why I modified sysinit_add() to merge two sorted lists, instead of just concatenating the lists. When you merge two sorted lists, the resulting list also becomes sorted, and then no further sorting is needed. hselasky: The KLDs loaded at boot, also have a sorted init and uninit section after my change.
That's… | |||||
*/ | |||||
void | |||||
sysinit_sort(struct sysinit **start, struct sysinit **stop) | |||||
{ | |||||
struct sysinit **sipp, **xipp, *save; | |||||
/* check for empty set */ | |||||
if (start == stop) | |||||
return; | |||||
TSENTER2("insertionsort"); | |||||
/* | |||||
* Sort all entries by their subsystem (primary key) and order | |||||
* (secondary key). | |||||
*/ | |||||
for (sipp = start + 1; sipp != stop; sipp++) { | |||||
for (xipp = sipp; xipp != start && | |||||
sysinit_compare(xipp - 1, xipp) > 0; xipp--) { | |||||
save = *(xipp - 1); | |||||
*(xipp - 1) = *xipp; | |||||
*xipp = save; | |||||
} | |||||
} | |||||
TSEXIT2("insertionsort"); | |||||
} | |||||
#if defined (DDB) && defined(VERBOSE_SYSINIT) | #if defined (DDB) && defined(VERBOSE_SYSINIT) | ||||
static const char * | static const char * | ||||
symbol_name(vm_offset_t va, db_strategy_t strategy) | symbol_name(vm_offset_t va, db_strategy_t strategy) | ||||
{ | { | ||||
const char *name; | const char *name; | ||||
c_db_sym_t sym; | c_db_sym_t sym; | ||||
db_expr_t offset; | db_expr_t offset; | ||||
Show All 18 Lines | |||||
* (for instance, a scheduler, kernel profiler, or VM system) by object | * (for instance, a scheduler, kernel profiler, or VM system) by object | ||||
* module. Finally, it allows for optional "kernel threads". | * module. Finally, it allows for optional "kernel threads". | ||||
*/ | */ | ||||
void | void | ||||
mi_startup(void) | mi_startup(void) | ||||
{ | { | ||||
struct sysinit **sipp; /* system initialization*/ | struct sysinit **sipp; /* system initialization*/ | ||||
struct sysinit **xipp; /* interior loop of sort*/ | |||||
struct sysinit *save; /* bubble*/ | |||||
int last; | int last; | ||||
#if defined(VERBOSE_SYSINIT) | #if defined(VERBOSE_SYSINIT) | ||||
int verbose; | int verbose; | ||||
#endif | #endif | ||||
TSENTER(); | TSENTER(); | ||||
if (boothowto & RB_VERBOSE) | if (boothowto & RB_VERBOSE) | ||||
bootverbose++; | bootverbose++; | ||||
if (sysinit == NULL) { | if (sysinit == NULL) { | ||||
sysinit = SET_BEGIN(sysinit_set); | sysinit = SET_BEGIN(sysinit_set); | ||||
sysinit_end = SET_LIMIT(sysinit_set); | sysinit_end = SET_LIMIT(sysinit_set); | ||||
} | } | ||||
restart: | restart: | ||||
/* | sysinit_sort(sysinit, sysinit_end); | ||||
* Perform a bubble sort of the system initialization objects by | |||||
* their subsystem (primary key) and order (secondary key). | |||||
*/ | |||||
TSENTER2("bubblesort"); | |||||
for (sipp = sysinit; sipp < sysinit_end; sipp++) { | |||||
for (xipp = sipp + 1; xipp < sysinit_end; xipp++) { | |||||
if ((*sipp)->subsystem < (*xipp)->subsystem || | |||||
((*sipp)->subsystem == (*xipp)->subsystem && | |||||
(*sipp)->order <= (*xipp)->order)) | |||||
continue; /* skip*/ | |||||
save = *sipp; | |||||
*sipp = *xipp; | |||||
*xipp = save; | |||||
} | |||||
} | |||||
TSEXIT2("bubblesort"); | |||||
last = SI_SUB_COPYRIGHT; | last = SI_SUB_COPYRIGHT; | ||||
#if defined(VERBOSE_SYSINIT) | #if defined(VERBOSE_SYSINIT) | ||||
verbose = 0; | verbose = 0; | ||||
#if !defined(DDB) | #if !defined(DDB) | ||||
printf("VERBOSE_SYSINIT: DDB not enabled, symbol lookups disabled.\n"); | printf("VERBOSE_SYSINIT: DDB not enabled, symbol lookups disabled.\n"); | ||||
#endif | #endif | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | |||||
#if defined(VERBOSE_SYSINIT) | #if defined(VERBOSE_SYSINIT) | ||||
if (verbose) | if (verbose) | ||||
printf("done.\n"); | printf("done.\n"); | ||||
#endif | #endif | ||||
/* Check off the one we're just done */ | /* Check off the one we're just done */ | ||||
last = (*sipp)->subsystem; | last = (*sipp)->subsystem; | ||||
(*sipp)->subsystem = SI_SUB_DONE; | (*sipp)->subsystem = SI_SUB_DONE; | ||||
/* Clear the order to avoid re-sorting the already executed sysinits */ | |||||
(*sipp)->order = SI_ORDER_FIRST; | |||||
/* Check if we've installed more sysinit items via KLD */ | /* Check if we've installed more sysinit items via KLD */ | ||||
if (newsysinit != NULL) { | if (newsysinit != NULL) { | ||||
if (sysinit != SET_BEGIN(sysinit_set)) | if (sysinit != SET_BEGIN(sysinit_set)) | ||||
free(sysinit, M_TEMP); | free(sysinit, M_TEMP); | ||||
sysinit = newsysinit; | sysinit = newsysinit; | ||||
sysinit_end = newsysinit_end; | sysinit_end = newsysinit_end; | ||||
newsysinit = NULL; | newsysinit = NULL; | ||||
▲ Show 20 Lines • Show All 575 Lines • Show Last 20 Lines |
Won't klds create unsorted entries at the end?