summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1998-11-10 08:49:28 +0000
committerpeter <peter@FreeBSD.org>1998-11-10 08:49:28 +0000
commitb8784ef1750330bf06be7cd66106d137faba55b7 (patch)
treeefd933e931ccf344f0cb88178eb82fd200c191c9 /sys
parent0f95240d58e95f72af7231f521da0616cf35fa6d (diff)
downloadFreeBSD-src-b8784ef1750330bf06be7cd66106d137faba55b7.zip
FreeBSD-src-b8784ef1750330bf06be7cd66106d137faba55b7.tar.gz
Arrange for unload-time linker set hooks to be called. While cut/pasting
some code, I changed the original to be consistant with the rest of the file rather than duplicating the problems.
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/kern_linker.c85
1 files changed, 71 insertions, 14 deletions
diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c
index d4698ad..6d0665bf 100644
--- a/sys/kern/kern_linker.c
+++ b/sys/kern/kern_linker.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: kern_linker.c,v 1.14 1998/11/04 15:20:56 peter Exp $
+ * $Id: kern_linker.c,v 1.15 1998/11/06 15:10:17 peter Exp $
*/
#include "opt_ddb.h"
@@ -123,11 +123,11 @@ linker_file_sysinit(linker_file_t lf)
* Since some things care about execution order, this is the
* operation which ensures continued function.
*/
- for( sipp = (struct sysinit **)sysinits->ls_items; *sipp; sipp++) {
- for( xipp = sipp + 1; *xipp; xipp++) {
- if( (*sipp)->subsystem < (*xipp)->subsystem ||
- ( (*sipp)->subsystem == (*xipp)->subsystem &&
- (*sipp)->order < (*xipp)->order))
+ for (sipp = (struct sysinit **)sysinits->ls_items; *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;
*sipp = *xipp;
@@ -139,18 +139,15 @@ linker_file_sysinit(linker_file_t lf)
/*
* Traverse the (now) ordered list of system initialization tasks.
* Perform each task, and continue on to the next task.
- *
- * The last item on the list is expected to be the scheduler,
- * which will not return.
*/
- for( sipp = (struct sysinit **)sysinits->ls_items; *sipp; sipp++) {
- if( (*sipp)->subsystem == SI_SUB_DUMMY)
+ for (sipp = (struct sysinit **)sysinits->ls_items; *sipp; sipp++) {
+ if ((*sipp)->subsystem == SI_SUB_DUMMY)
continue; /* skip dummy task(s)*/
- switch( (*sipp)->type) {
+ switch ((*sipp)->type) {
case SI_TYPE_DEFAULT:
/* no special processing*/
- (*((*sipp)->func))( (*sipp)->udata);
+ (*((*sipp)->func))((*sipp)->udata);
break;
case SI_TYPE_KTHREAD:
@@ -172,7 +169,65 @@ linker_file_sysinit(linker_file_t lf)
break;
default:
- panic( "linker_file_sysinit: unrecognized init type");
+ panic ("linker_file_sysinit: unrecognized init type");
+ }
+ }
+}
+
+static void
+linker_file_sysuninit(linker_file_t lf)
+{
+ struct linker_set* sysuninits;
+ struct sysinit** sipp;
+ struct sysinit** xipp;
+ struct sysinit* save;
+
+ KLD_DPF(FILE, ("linker_file_sysuninit: calling SYSUNINITs for %s\n",
+ lf->filename));
+
+ sysuninits = (struct linker_set*)
+ linker_file_lookup_symbol(lf, "sysuninit_set", 0);
+
+ KLD_DPF(FILE, ("linker_file_sysuninit: SYSUNINITs %p\n", sysuninits));
+ if (!sysuninits)
+ return;
+
+ /*
+ * Perform a reverse 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 **)sysuninits->ls_items; *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;
+ *sipp = *xipp;
+ *xipp = save;
+ }
+ }
+
+
+ /*
+ * Traverse the (now) ordered list of system initialization tasks.
+ * Perform each task, and continue on to the next task.
+ */
+ for (sipp = (struct sysinit **)sysuninits->ls_items; *sipp; sipp++) {
+ if ((*sipp)->subsystem == SI_SUB_DUMMY)
+ continue; /* skip dummy task(s)*/
+
+ switch ((*sipp)->type) {
+ case SI_TYPE_DEFAULT:
+ /* no special processing*/
+ (*((*sipp)->func))((*sipp)->udata);
+ break;
+
+ default:
+ panic("linker_file_sysuninit: unrecognized uninit type");
}
}
}
@@ -344,6 +399,8 @@ linker_file_unload(linker_file_t file)
goto out;
}
+ linker_file_sysuninit(file);
+
TAILQ_REMOVE(&files, file, link);
lockmgr(&lock, LK_RELEASE, 0, curproc);
OpenPOWER on IntegriCloud