diff options
author | peter <peter@FreeBSD.org> | 2001-06-13 10:58:39 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 2001-06-13 10:58:39 +0000 |
commit | f10fa038c14063eaf2da32ed734e644e5f569694 (patch) | |
tree | 88aef8097c80f09c2f725d61b6da4d433a595a61 /sys/kern/init_main.c | |
parent | 2514663dd721b9ac234d35a4dac65dfc457ff6bc (diff) | |
download | FreeBSD-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.c | 44 |
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; } } |