Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F150703149
D40463.id122933.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
21 KB
Referenced Files
None
Subscribers
None
D40463.id122933.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D40463: kernel: Use the compiler supported constructor and destructor attributes to register sysinits.
Attached
Detach File
Event Timeline
Log In to Comment