Page MenuHomeFreeBSD

D40463.id122933.diff
No OneTemporary

D40463.id122933.diff

diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -149,57 +149,106 @@
#endif
/*
- * This ensures that there is at least one entry so that the sysinit_set
- * symbol is not undefined. A sybsystem ID of SI_SUB_DUMMY is never
- * executed.
+ * Declare the list of function pointers, to init the kernel.
*/
-static void
-placeholder(void)
+SET_DECLARE(ctors, sysinit_func_t);
+
+/*
+ * Declare the list of function pointers, to shutdown the kernel.
+ */
+SET_DECLARE(dtors, sysinit_func_t);
+
+/*
+ * Compare two sysinit structures.
+ */
+static int
+sysinit_compare(const struct sysinit *pa, const struct sysinit *pb, int neg)
{
+ if (pa->subsystem > pb->subsystem)
+ return (neg);
+ else if (pa->subsystem < pb->subsystem)
+ return (-neg);
+ else if (pa->order > pb->order)
+ return (neg);
+ else if (pa->order < pb->order)
+ return (-neg);
+ else
+ return (0);
}
-SYSINIT(placeholder, SI_SUB_DUMMY, SI_ORDER_ANY, placeholder);
+
+SYSINIT_DECLARE_HEAD(sysinit_head);
+SYSINIT_DECLARE_HEAD(sysuninit_head);
/*
- * The sysinit table itself. Items are checked off as the are run.
- * If we want to register new sysinit types, add them to newsysinit.
+ * Insert a sysinit structure into a list sorted by subsystem and order.
+ *
+ * @param ptr Pointer to the sysinit structure to be inserted.
+ * @param phead Pointer to the head structure for the sysinits.
+ * @param neg 1: Ascending order -1: Descending order
*/
-SET_DECLARE(sysinit_set, struct sysinit);
-struct sysinit **sysinit, **sysinit_end;
-struct sysinit **newsysinit, **newsysinit_end;
+void
+sysinit_insert_sorted(struct sysinit *ptr, sysinit_head_t *phead, int neg)
+{
+ /* don't insert reserved entries */
+ if (ptr->subsystem == SI_SUB_DUMMY)
+ return;
+
+ if (TAILQ_FIRST(&phead->h) == NULL) {
+ TAILQ_INSERT_TAIL(&phead->h, ptr, entry);
+ } else {
+ for (;;) {
+ struct sysinit *pnext;
+ int cmp;
+
+ pnext = TAILQ_NEXT(phead->l, entry);
+
+ cmp = sysinit_compare(ptr, phead->l, neg);
+ if (cmp < 0) {
+ /* search from beginning */
+ phead->l = TAILQ_FIRST(&phead->h);
+ } else if (pnext == NULL || sysinit_compare(ptr, pnext, neg) < 0) {
+ /* insert after last element */
+ TAILQ_INSERT_AFTER(&phead->h, phead->l, ptr, entry);
+ break;
+ } else {
+ /* advance to next element */
+ phead->l = pnext;
+ }
+ }
+ }
+ phead->l = ptr;
+}
/*
- * Merge a new sysinit set into the current set, reallocating it if
- * necessary. This can only be called after malloc is running.
+ * Remove a sysinit structure from a list.
+
+ * @param ptr Pointer to the sysinit structure to be removed
+ * @param phead Pointer to the head structure for the sysinits
*/
void
-sysinit_add(struct sysinit **set, struct sysinit **set_end)
+sysinit_remove(struct sysinit *ptr, sysinit_head_t *phead)
{
- struct sysinit **newset;
- struct sysinit **sipp;
- struct sysinit **xipp;
- int count;
-
- count = set_end - set;
- if (newsysinit)
- count += newsysinit_end - newsysinit;
- else
- 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 < newsysinit_end; sipp++)
- *xipp++ = *sipp;
- else
- for (sipp = sysinit; sipp < sysinit_end; sipp++)
- *xipp++ = *sipp;
- for (sipp = set; sipp < set_end; sipp++)
- *xipp++ = *sipp;
- if (newsysinit)
- free(newsysinit, M_TEMP);
- newsysinit = newset;
- newsysinit_end = newset + count;
+ /* update last pointer to next element, if it was removed */
+ if (phead->l == ptr)
+ phead->l = TAILQ_NEXT(ptr, entry);
+
+ TAILQ_REMOVE(&phead->h, ptr, entry);
+
+ /* in case TAILQ_NEXT() returned NULL, reset the last pointer */
+ if (phead->l == NULL)
+ phead->l = TAILQ_FIRST(&phead->h);
+}
+
+void
+sysinit_constructor_register(struct sysinit *ptr)
+{
+ sysinit_insert_sorted(ptr, &sysinit_head, 1);
+}
+
+void
+sysinit_destructor_register(struct sysinit *ptr)
+{
+ sysinit_insert_sorted(ptr, &sysuninit_head, -1);
}
#if defined (DDB) && defined(VERBOSE_SYSINIT)
@@ -220,128 +269,88 @@
}
#endif
-/*
- * System startup; initialize the world, create process 0, mount root
- * filesystem, and fork to create init and pagedaemon. Most of the
- * hard work is done in the lower-level initialization routines including
- * startup(), which does memory initialization and autoconfiguration.
- *
- * This allows simple addition of new kernel subsystems that require
- * boot time initialization. It also allows substitution of subsystem
- * (for instance, a scheduler, kernel profiler, or VM system) by object
- * module. Finally, it allows for optional "kernel threads".
- */
void
-mi_startup(void)
+sysinit_execute(sysinit_head_t *phead, const char *fname)
{
-
- struct sysinit **sipp; /* system initialization*/
- struct sysinit **xipp; /* interior loop of sort*/
- struct sysinit *save; /* bubble*/
-
- int last;
+ struct sysinit *ptr;
+ enum sysinit_sub_id last = SI_SUB_DUMMY;
#if defined(VERBOSE_SYSINIT)
- int verbose;
+ bool verbose = false;
#endif
- TSENTER();
+ while ((ptr = TAILQ_FIRST(&phead->h))) {
+ sysinit_remove(ptr, phead);
- if (boothowto & RB_VERBOSE)
- bootverbose++;
-
- 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).
- */
- 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");
+ if (last != ptr->subsystem) {
+ last = ptr->subsystem;
+ BOOTTRACE("%s: sysinit execute 0x%3X", fname, last);
- last = SI_SUB_COPYRIGHT;
#if defined(VERBOSE_SYSINIT)
- verbose = 0;
-#if !defined(DDB)
- printf("VERBOSE_SYSINIT: DDB not enabled, symbol lookups disabled.\n");
+ verbose = (last > SI_SUB_COPYRIGHT);
+ if (verbose)
+ printf("subsystem 0x%03X\n", last);
#endif
-#endif
-
- /*
- * Traverse the (now) ordered list of system initialization tasks.
- * Perform each task, and continue on to the next task.
- */
- for (sipp = sysinit; sipp < sysinit_end; sipp++) {
- if ((*sipp)->subsystem == SI_SUB_DUMMY)
- continue; /* skip dummy task(s)*/
-
- if ((*sipp)->subsystem == SI_SUB_DONE)
- continue;
-
- if ((*sipp)->subsystem > last)
- BOOTTRACE_INIT("sysinit 0x%7x", (*sipp)->subsystem);
+ }
#if defined(VERBOSE_SYSINIT)
- if ((*sipp)->subsystem > last && verbose_sysinit != 0) {
- verbose = 1;
- printf("subsystem %x\n", last);
- }
if (verbose) {
#if defined(DDB)
- const char *func, *data;
+ const char *func;
- func = symbol_name((vm_offset_t)(*sipp)->func,
+ func = symbol_name((vm_offset_t)ptr->func,
DB_STGY_PROC);
- data = symbol_name((vm_offset_t)(*sipp)->udata,
- DB_STGY_ANY);
- if (func != NULL && data != NULL)
- printf(" %s(&%s)... ", func, data);
- else if (func != NULL)
- printf(" %s(%p)... ", func, (*sipp)->udata);
+ if (func != NULL)
+ printf(" %s()... ", func);
else
#endif
- printf(" %p(%p)... ", (*sipp)->func,
- (*sipp)->udata);
+ printf(" %p()... ", ptr->func);
}
#endif
-
- /* Call function */
- (*((*sipp)->func))((*sipp)->udata);
+ /* execute sysinit */
+ ptr->func();
#if defined(VERBOSE_SYSINIT)
if (verbose)
printf("done.\n");
#endif
-
- /* Check off the one we're just done */
- last = (*sipp)->subsystem;
- (*sipp)->subsystem = SI_SUB_DONE;
-
- /* Check if we've installed more sysinit items via KLD */
- if (newsysinit != NULL) {
- if (sysinit != SET_BEGIN(sysinit_set))
- free(sysinit, M_TEMP);
- sysinit = newsysinit;
- sysinit_end = newsysinit_end;
- newsysinit = NULL;
- newsysinit_end = NULL;
- goto restart;
- }
}
+}
+
+/*
+ * System startup; initialize the world, create process 0, mount root
+ * filesystem, and fork to create init and pagedaemon. Most of the
+ * hard work is done in the lower-level initialization routines including
+ * startup(), which does memory initialization and autoconfiguration.
+ *
+ * This allows simple addition of new kernel subsystems that require
+ * boot time initialization. It also allows substitution of subsystem
+ * (for instance, a scheduler, kernel profiler, or VM system) by object
+ * module. Finally, it allows for optional "kernel threads".
+ */
+void
+mi_startup(void)
+{
+ sysinit_func_t * const * si_start;
+ sysinit_func_t * const * si_stop;
+
+ TSENTER();
+
+ if (boothowto & RB_VERBOSE)
+ bootverbose++;
+
+ si_start = SET_BEGIN(ctors);
+ si_stop = SET_LIMIT(ctors);
+
+#if defined(VERBOSE_SYSINIT) && !defined(DDB)
+ printf("VERBOSE_SYSINIT: DDB not enabled, symbol lookups disabled.\n");
+#endif
+
+ /* run all the kernel constructors */
+ for (; si_start != si_stop; si_start++)
+ (*si_start)();
+
+ /* execute all the sysinits */
+ sysinit_execute(&sysinit_head, "kernel");
TSEXIT(); /* Here so we don't overlap with start_init. */
BOOTTRACE("mi_startup done");
@@ -871,9 +880,9 @@
*/
#ifdef DDB
static void
-db_show_print_syinit(struct sysinit *sip, bool ddb)
+db_show_print_function(sysinit_func_t *func, bool ddb)
{
- const char *sname, *funcname;
+ const char *funcname;
c_db_sym_t sym;
db_expr_t offset;
@@ -883,31 +892,44 @@
else \
printf(__VA_ARGS__)
- if (sip == NULL) {
- xprint("%s: no sysinit * given\n", __func__);
+ if (func == NULL) {
+ xprint("%s: no function given\n", __func__);
return;
}
- sym = db_search_symbol((vm_offset_t)sip, DB_STGY_ANY, &offset);
- db_symbol_values(sym, &sname, NULL);
- sym = db_search_symbol((vm_offset_t)sip->func, DB_STGY_PROC, &offset);
+ sym = db_search_symbol((vm_offset_t)func, DB_STGY_PROC, &offset);
db_symbol_values(sym, &funcname, NULL);
- xprint("%s(%p)\n", (sname != NULL) ? sname : "", sip);
- xprint(" %#08x %#08x\n", sip->subsystem, sip->order);
- xprint(" %p(%s)(%p)\n",
- sip->func, (funcname != NULL) ? funcname : "", sip->udata);
+ xprint("%s(%p)\n", funcname, func);
#undef xprint
}
-DB_SHOW_COMMAND_FLAGS(sysinit, db_show_sysinit, DB_CMD_MEMSAFE)
+DB_SHOW_COMMAND_FLAGS(constructors, db_show_constructors, DB_CMD_MEMSAFE)
{
- struct sysinit **sipp;
+ sysinit_func_t * const * si_start;
+ sysinit_func_t * const * si_stop;
+
+ si_start = SET_BEGIN(ctors);
+ si_stop = SET_LIMIT(ctors);
+
+ db_printf("CONSTRUCTORS vs Name(Ptr)\n");
+ for (; si_start != si_stop; si_start++) {
+ db_show_print_function(*si_start, true);
+ if (db_pager_quit)
+ break;
+ }
+}
+
+DB_SHOW_COMMAND_FLAGS(destructors, db_show_destructors, DB_CMD_MEMSAFE)
+{
+ sysinit_func_t * const * si_start;
+ sysinit_func_t * const * si_stop;
+
+ si_start = SET_BEGIN(dtors);
+ si_stop = SET_LIMIT(dtors);
- db_printf("SYSINIT vs Name(Ptr)\n");
- db_printf(" Subsystem Order\n");
- db_printf(" Function(Name)(Arg)\n");
- for (sipp = sysinit; sipp < sysinit_end; sipp++) {
- db_show_print_syinit(*sipp, true);
+ db_printf("DESTRUCTORS vs Name(Ptr)\n");
+ for (; si_start != si_stop; si_start++) {
+ db_show_print_function(*si_start, true);
if (db_pager_quit)
break;
}
diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c
--- a/sys/kern/kern_linker.c
+++ b/sys/kern/kern_linker.c
@@ -195,54 +195,27 @@
static void
linker_file_sysinit(linker_file_t lf)
{
- struct sysinit **start, **stop, **sipp, **xipp, *save;
- int last;
+ sysinit_func_t * const * si_start;
+ sysinit_func_t * const * si_stop;
- KLD_DPF(FILE, ("linker_file_sysinit: calling SYSINITs for %s\n",
+ KLD_DPF(FILE, ("linker_file_sysinit: calling constructors for %s\n",
lf->filename));
sx_assert(&kld_sx, SA_XLOCKED);
- if (linker_file_lookup_set(lf, "sysinit_set", &start, &stop, NULL) != 0)
+ if (linker_file_lookup_set(lf, ".ctors", &si_start, &si_stop, NULL) != 0)
return;
- /*
- * Perform a 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 = start; sipp < stop; sipp++) {
- for (xipp = sipp + 1; xipp < stop; 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.
- */
- last = SI_SUB_DUMMY;
sx_xunlock(&kld_sx);
mtx_lock(&Giant);
- for (sipp = start; sipp < stop; sipp++) {
- if ((*sipp)->subsystem == SI_SUB_DUMMY)
- continue; /* skip dummy task(s) */
- if ((*sipp)->subsystem > last)
- BOOTTRACE("%s: sysinit 0x%7x", lf->filename,
- (*sipp)->subsystem);
+ /* run all the constructors provided by the kernel module */
+ for (; si_start != si_stop; si_start++)
+ (*si_start)();
+
+ /* run all the registered SYSINITs */
+ sysinit_execute(&sysinit_head, lf->filename);
- /* Call function */
- (*((*sipp)->func)) ((*sipp)->udata);
- last = (*sipp)->subsystem;
- }
mtx_unlock(&Giant);
sx_xlock(&kld_sx);
}
@@ -250,56 +223,27 @@
static void
linker_file_sysuninit(linker_file_t lf)
{
- struct sysinit **start, **stop, **sipp, **xipp, *save;
- int last;
+ sysinit_func_t * const * si_start;
+ sysinit_func_t * const * si_stop;
- KLD_DPF(FILE, ("linker_file_sysuninit: calling SYSUNINITs for %s\n",
+ KLD_DPF(FILE, ("linker_file_sysuninit: calling destructors for %s\n",
lf->filename));
sx_assert(&kld_sx, SA_XLOCKED);
- if (linker_file_lookup_set(lf, "sysuninit_set", &start, &stop,
- NULL) != 0)
+ if (linker_file_lookup_set(lf, ".dtors", &si_start, &si_stop, NULL) != 0)
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 = start; sipp < stop; sipp++) {
- for (xipp = sipp + 1; xipp < stop; 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.
- */
sx_xunlock(&kld_sx);
mtx_lock(&Giant);
- last = SI_SUB_DUMMY;
- for (sipp = start; sipp < stop; sipp++) {
- if ((*sipp)->subsystem == SI_SUB_DUMMY)
- continue; /* skip dummy task(s) */
-
- if ((*sipp)->subsystem > last)
- BOOTTRACE("%s: sysuninit 0x%7x", lf->filename,
- (*sipp)->subsystem);
-
- /* Call function */
- (*((*sipp)->func)) ((*sipp)->udata);
- last = (*sipp)->subsystem;
- }
+
+ /* run all the destructors provided by the kernel module */
+ for (; si_start != si_stop; si_start++)
+ (*si_start)();
+
+ /* run all the registered SYSUNINITs */
+ sysinit_execute(&sysuninit_head, lf->filename);
+
mtx_unlock(&Giant);
sx_xlock(&kld_sx);
}
@@ -1581,7 +1525,8 @@
int nver;
int resolves;
modlist_t mod;
- struct sysinit **si_start, **si_stop;
+ sysinit_func_t * const * si_start;
+ sysinit_func_t * const * si_stop;
TAILQ_INIT(&loaded_files);
TAILQ_INIT(&depended_files);
@@ -1762,9 +1707,10 @@
linker_file_register_modules(lf);
if (!TAILQ_EMPTY(&lf->modules))
lf->flags |= LINKER_FILE_MODULES;
- if (linker_file_lookup_set(lf, "sysinit_set", &si_start,
- &si_stop, NULL) == 0)
- sysinit_add(si_start, si_stop);
+ if (linker_file_lookup_set(lf, ".ctors", &si_start, &si_stop, NULL) == 0) {
+ for (; si_start != si_stop; si_start++)
+ (*si_start)();
+ }
linker_file_register_sysctls(lf, true);
lf->flags |= LINKER_FILE_LINKED;
continue;
diff --git a/sys/net/vnet.h b/sys/net/vnet.h
--- a/sys/net/vnet.h
+++ b/sys/net/vnet.h
@@ -320,6 +320,8 @@
*/
#include <sys/kernel.h>
+typedef void (*sysinit_cfunc_t)(const void *);
+
/*
* SYSINIT/SYSUNINIT variants that provide per-vnet constructors and
* destructors.
diff --git a/sys/sys/kernel.h b/sys/sys/kernel.h
--- a/sys/sys/kernel.h
+++ b/sys/sys/kernel.h
@@ -49,11 +49,10 @@
#include <sys/linker_set.h>
-#ifdef _KERNEL
-
-/* for intrhook below */
#include <sys/queue.h>
+#ifdef _KERNEL
+
/* for timestamping SYSINITs; other files may assume this is included here */
#include <sys/tslog.h>
@@ -88,7 +87,6 @@
*/
enum sysinit_sub_id {
SI_SUB_DUMMY = 0x000, /* not executed; for linker */
- SI_SUB_DONE = 0x00C, /* processed */
SI_SUB_TUNABLES = 0x018, /* establish tunable values */
SI_SUB_COPYRIGHT = 0x024, /* first use of console */
SI_SUB_VM = 0x030, /* virtual memory system init */
@@ -192,37 +190,28 @@
SI_ORDER_ANY = 0x3f /* last */
};
-/*
- * A system initialization call instance
- *
- * At the moment there is one instance of sysinit. We probably do not
- * want two which is why this code is if'd out, but we definitely want
- * to discern SYSINIT's which take non-constant data pointers and
- * SYSINIT's which take constant data pointers,
- *
- * The C_* macros take functions expecting const void * arguments
- * while the non-C_* macros take functions expecting just void * arguments.
- *
- * With -Wcast-qual on, the compiler issues warnings:
- * - if we pass non-const data or functions taking non-const data
- * to a C_* macro.
- *
- * - if we pass const data to the normal macros
- *
- * However, no warning is issued if we pass a function taking const data
- * through a normal non-const macro. This is ok because the function is
- * saying it won't modify the data so we don't care whether the data is
- * modifiable or not.
- */
+struct sysinit;
+
+typedef struct {
+ TAILQ_HEAD(, sysinit) h;
+ struct sysinit *l; /* last entry added - to optimise sorted insertion */
+} sysinit_head_t;
+
+#define SYSINIT_DECLARE_HEAD(name) \
+ sysinit_head_t name = { .h = TAILQ_HEAD_INITIALIZER(name.h), .l = NULL }
+
+#define SYSINIT_FOREACH(ptr, head) \
+ TAILQ_FOREACH(ptr, &(head)->h, entry)
+
+typedef TAILQ_ENTRY(sysinit) sysinit_entry_t;
-typedef void (*sysinit_nfunc_t)(void *);
-typedef void (*sysinit_cfunc_t)(const void *);
+typedef void (sysinit_func_t)(void);
struct sysinit {
- enum sysinit_sub_id subsystem; /* subsystem identifier*/
- enum sysinit_elem_order order; /* init order within subsystem*/
- sysinit_cfunc_t func; /* function */
- const void *udata; /* multiplexer/argument */
+ sysinit_entry_t entry; /* entry for list */
+ sysinit_func_t *func; /* function pointer */
+ enum sysinit_sub_id subsystem; /* subsystem identifier */
+ enum sysinit_elem_order order; /* init order within subsystem */
};
/*
@@ -243,11 +232,17 @@
do { } while (0)
#endif
+#define __SI_PRIORITY(sub, order) \
+ (((sub) * (SI_ORDER_ANY + 1)) + (order))
+
+_Static_assert(__SI_PRIORITY(SI_SUB_LAST, SI_ORDER_ANY) <= 65535,
+ "The maximum constructor priority exceeds 65535");
+
/*
* Explanation of arguments for the __SI_REGISTER() macro:
*
* @param uniq An identifier for the needed functions and structures.
- * @param type sysinit_set or sysuninit_set, depending on use case.
+ * @param type constructor or destructor, depending on use case.
* @param _sub SI_SUB_XXX enum.
* @param _order SI_ORDER_XXX enum.
* @param _func Pointer to callback function.
@@ -259,41 +254,51 @@
* pointer casting between types is avoided entirely.
*/
#define __SI_REGISTER(uniq, type, _sub, _order, _func, ...) \
-_Static_assert((_sub) > SI_SUB_DONE && (_sub) <= SI_SUB_LAST, \
+_Static_assert((_sub) > SI_SUB_DUMMY && (_sub) <= SI_SUB_LAST, \
"Subsystem is out of range"); \
_Static_assert((_order) >= 0 && (_order) <= SI_ORDER_ANY, \
"Order is out of range"); \
+_Static_assert(__SI_PRIORITY(_sub, _order) >= 100, \
+ "Priorities below 100 are reserved"); \
static void \
-type##_##uniq##_shim(const void *arg __unused) \
+type##_##uniq##_shim(void) \
{ \
__SI_FUNCTION_PRE(type, _func); \
(_func)(__VA_ARGS__); \
__SI_FUNCTION_POST(type, _func); \
} \
-static struct sysinit type##_##uniq = { \
- .subsystem = _sub, \
- .order = _order, \
- .func = &type##_##uniq##_shim, \
- .udata = NULL, \
-}; \
-DATA_WSET(type, type##_##uniq); \
+static void __attribute__((type(__SI_PRIORITY(_sub, _order)))) \
+ type##_##uniq##_register(void) { \
+ static struct sysinit __data = { \
+ .subsystem = _sub, \
+ .order = _order, \
+ .func = &type##_##uniq##_shim, \
+ }; \
+ sysinit_##type##_register(&__data); \
+} \
struct __hack
/*
* Sysinit API macro, called on kernel or module load:
*/
#define SYSINIT(uniq, sub, order, ...) \
- __SI_REGISTER(uniq, sysinit_set, sub, order, __VA_ARGS__)
+ __SI_REGISTER(uniq, constructor, sub, order, __VA_ARGS__)
/*
* Sysuninit API macros, called on kernel shutdown or module unload:
*/
#define SYSUNINIT(uniq, sub, order, ...) \
- __SI_REGISTER(uniq, sysuinit_set, sub, order, __VA_ARGS__)
-
-void sysinit_add(struct sysinit **set, struct sysinit **set_end);
+ __SI_REGISTER(uniq, destructor, sub, order, __VA_ARGS__)
#ifdef _KERNEL
+extern sysinit_head_t sysinit_head;
+extern sysinit_head_t sysuninit_head;
+
+void sysinit_insert_sorted(struct sysinit *, sysinit_head_t *, int neg);
+void sysinit_remove(struct sysinit *, sysinit_head_t *);
+void sysinit_constructor_register(struct sysinit *);
+void sysinit_destructor_register(struct sysinit *);
+void sysinit_execute(sysinit_head_t *, const char *);
/*
* Infrastructure for tunable 'constants'. Value may be specified at compile

File Metadata

Mime Type
text/plain
Expires
Sat, Apr 4, 11:53 AM (2 h, 54 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30760225
Default Alt Text
D40463.id122933.diff (21 KB)

Event Timeline