summaryrefslogtreecommitdiffstats
path: root/sys/kern/init_main.c
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2001-06-13 10:58:39 +0000
committerpeter <peter@FreeBSD.org>2001-06-13 10:58:39 +0000
commitf10fa038c14063eaf2da32ed734e644e5f569694 (patch)
tree88aef8097c80f09c2f725d61b6da4d433a595a61 /sys/kern/init_main.c
parent2514663dd721b9ac234d35a4dac65dfc457ff6bc (diff)
downloadFreeBSD-src-f10fa038c14063eaf2da32ed734e644e5f569694.zip
FreeBSD-src-f10fa038c14063eaf2da32ed734e644e5f569694.tar.gz
With this commit, I hereby pronounce gensetdefs past its use-by date.
Replace the a.out emulation of 'struct linker_set' with something a little more flexible. <sys/linker_set.h> now provides macros for accessing elements and completely hides the implementation. The linker_set.h macros have been on the back burner in various forms since 1998 and has ideas and code from Mike Smith (SET_FOREACH()), John Polstra (ELF clue) and myself (cleaned up API and the conversion of the rest of the kernel to use it). The macros declare a strongly typed set. They return elements with the type that you declare the set with, rather than a generic void *. For ELF, we use the magic ld symbols (__start_<setname> and __stop_<setname>). Thanks to Richard Henderson <rth@redhat.com> for the trick about how to force ld to provide them for kld's. For a.out, we use the old linker_set struct. NOTE: the item lists are no longer null terminated. This is why the code impact is high in certain areas. The runtime linker has a new method to find the linker set boundaries depending on which backend format is in use. linker sets are still module/kld unfriendly and should never be used for anything that may be modular one day. Reviewed by: eivind
Diffstat (limited to 'sys/kern/init_main.c')
-rw-r--r--sys/kern/init_main.c44
1 files changed, 23 insertions, 21 deletions
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index 9698983..aa1fa74 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -77,8 +77,6 @@
#include <sys/user.h>
#include <sys/copyright.h>
-extern struct linker_set sysinit_set; /* XXX */
-
void mi_startup(void); /* Should be elsewhere */
/* Components of the first process -- never freed. */
@@ -112,46 +110,43 @@ 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;
+SET_DECLARE(sysinit_set, struct sysinit);
+struct sysinit **sysinit, **sysinit_end;
+struct sysinit **newsysinit, **newsysinit_end;
/*
* 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(struct sysinit **set)
+sysinit_add(struct sysinit **set, struct sysinit **set_end)
{
struct sysinit **newset;
struct sysinit **sipp;
struct sysinit **xipp;
- int count = 0;
+ int count;
+ count = set_end - set;
if (newsysinit)
- for (sipp = newsysinit; *sipp; sipp++)
- count++;
+ count += newsysinit_end - newsysinit;
else
- for (sipp = sysinit; *sipp; sipp++)
- count++;
- for (sipp = set; *sipp; sipp++)
- count++;
- count++; /* Trailing NULL */
+ count += sysinit_end - sysinit;
newset = malloc(count * sizeof(*sipp), M_TEMP, M_NOWAIT);
if (newset == NULL)
panic("cannot malloc for sysinit");
xipp = newset;
if (newsysinit)
- for (sipp = newsysinit; *sipp; sipp++)
+ for (sipp = newsysinit; sipp < newsysinit_end; sipp++)
*xipp++ = *sipp;
else
- for (sipp = sysinit; *sipp; sipp++)
+ for (sipp = sysinit; sipp < sysinit_end; sipp++)
*xipp++ = *sipp;
- for (sipp = set; *sipp; sipp++)
+ for (sipp = set; sipp < set_end; sipp++)
*xipp++ = *sipp;
- *xipp = NULL;
if (newsysinit)
free(newsysinit, M_TEMP);
newsysinit = newset;
+ newsysinit_end = newset + count;
}
/*
@@ -173,13 +168,18 @@ mi_startup(void)
register struct sysinit **xipp; /* interior loop of sort*/
register struct sysinit *save; /* bubble*/
+ if (sysinit == NULL) {
+ sysinit = SET_BEGIN(sysinit_set);
+ sysinit_end = SET_LIMIT(sysinit_set);
+ }
+
restart:
/*
* Perform a bubble sort of the system initialization objects by
* their subsystem (primary key) and order (secondary key).
*/
- for (sipp = sysinit; *sipp; sipp++) {
- for (xipp = sipp + 1; *xipp; xipp++) {
+ 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))
@@ -197,7 +197,7 @@ restart:
* The last item on the list is expected to be the scheduler,
* which will not return.
*/
- for (sipp = sysinit; *sipp; sipp++) {
+ for (sipp = sysinit; sipp < sysinit_end; sipp++) {
if ((*sipp)->subsystem == SI_SUB_DUMMY)
continue; /* skip dummy task(s)*/
@@ -213,10 +213,12 @@ restart:
/* Check if we've installed more sysinit items via KLD */
if (newsysinit != NULL) {
- if (sysinit != (struct sysinit **)sysinit_set.ls_items)
+ if (sysinit != SET_BEGIN(sysinit_set))
free(sysinit, M_TEMP);
sysinit = newsysinit;
+ sysinit_end = newsysinit_end;
newsysinit = NULL;
+ newsysinit_end = NULL;
goto restart;
}
}
OpenPOWER on IntegriCloud