|
- /*-
- * Copyright 2022 John-Mark Gurney.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
- #include <stdbool.h>
- #include <stdint.h>
- #include <stdlib.h>
- #include <sysinit.h>
-
- SET_DECLARE(sysinit_set, struct sysinit);
-
- void __attribute__ ((constructor))
- sysinit_run(void)
- {
- const int cnt = SET_COUNT(sysinit_set);
- uint16_t *idxarray = alloca(sizeof(uint16_t) * cnt);
- #if defined(VERBOSE_SYSINIT)
- uint16_t last;
- bool verbose;
- #endif
- int i;
-
- for (i = 0; i < cnt; i++)
- idxarray[i] = i;
-
- /*
- * following mostly copied from FreeBSD sys/kern/init_main.c
- * which has license:
- * SPDX-License-Identifier: BSD-4-Clause
- *
- * Copyright (c) 1995 Terrence R. Lambert
- * All rights reserved.
- *
- * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993
- * The Regents of the University of California. All rights reserved.
- * (c) UNIX System Laboratories, Inc.
- *
- * as copying this to RAM might be expensive, use a stack
- * allocated indirection array to do the sorting instead.
- */
- uint16_t *sipp;
- uint16_t *xipp;
- uint16_t save;
-
- /*
- * Perform a bubble sort of the system initialization objects by
- * their subsystem (primary key) and order (secondary key).
- */
- #define GI(x) (SET_BEGIN(sysinit_set)[(x)])
- #define GI_SUBSYSORDER(x) (GI((x))->si_subsys_order)
- #define GI_SUBSYS(x) (GET_SUBSYS(GI_SUBSYSORDER(x)))
- #define GI_ORDER(x) (GET_ORDER(GI_SUBSYSORDER(x)))
-
- for (sipp = &idxarray[0]; sipp < &idxarray[cnt]; sipp++) {
- for (xipp = sipp + 1; xipp < &idxarray[cnt]; xipp++) {
- if (GI_SUBSYS(*sipp) < GI_SUBSYS(*xipp) ||
- (GI_SUBSYS(*sipp) == GI_SUBSYS(*xipp) &&
- GI_ORDER(*sipp) <= GI_ORDER(*xipp)))
- continue; /* skip*/
- save = *sipp;
- *sipp = *xipp;
- *xipp = save;
- }
- }
-
- #if defined(VERBOSE_SYSINIT)
- last = SI_SUB_COPYRIGHT;
- verbose = 0;
- #endif
- /*
- * Traverse the (now) ordered list of system initialization tasks.
- * Perform each task, and continue on to the next task.
- */
- for (sipp = &idxarray[0]; sipp < &idxarray[cnt]; sipp++) {
- if (GI_SUBSYS(*sipp) == SI_SUB_DUMMY)
- continue; /* skip dummy task(s)*/
-
- #if defined(VERBOSE_SYSINIT)
- if (GI_SUBSYS(*sipp) > last && verbose_sysinit != 0) {
- verbose = 1;
- last = GI_SUBSYS(*sipp);
- printf("subsystem %x\n", last);
- }
- if (verbose) {
- printf(" %p(%p)... ", GI(*sipp)->func,
- GI(*sipp)->udata);
- }
- #endif
-
- /* Call function */
- (GI(*sipp)->si_func)(GI(*sipp)->si_udata);
-
- #if defined(VERBOSE_SYSINIT)
- if (verbose)
- printf("done.\n");
- #endif
- }
- }
|