How about another alternative?
Rather than using .ctor/dtor for _MODULE mode, and a link-set for the
built-in mode, we could extend the modinfo_t structure to include two new
members:
char *mi_ctor_section, *mi_dtor_section
Then the module's code can continue to use the link_set paradigm, and the
module loader can use the names provided rather than hard-coding ".ctor" and
".dtor". And that means that (this part of) the module doesn't need to be
aware of whether it is built-in or not.
This would also mean that net80211 module no longer needs its own code to
process the __link_set_foreach(), since the module loader would take care of
this automatically?
Of course, this would definitely require a kernel version bump, since
module_t would be changing. And I would propose we use a MODULE_NEW
declaration, and redefine MODULE to specify NULL values for the two new
members.
/* Module header structure. */
typedef struct modinfo {
u_int mi_version;
modclass_t mi_class;
int (*mi_modcmd)(modcmd_t, void *);
const char *mi_name;
const char *mi_required;
const char *mi_ctor_section;
const char *mi_dtor_section;
} const modinfo_t;
...
/*
* Per-module linkage. Loadable modules have a `link_set_modules' section
* containing only one entry, pointing to the module's modinfo_t record.
* For the kernel, `link_set_modules' can contain multiple entries and
* records all modules built into the kernel at link time.
*/
#define MODULE(class, name, required) \
MODULE_NEW(class, name, required, NULL, NULL)
#define MODULE_NEW(class, name, required, ctor, dtor) \
static int name##_modcmd(modcmd_t, void *); \
static const modinfo_t name##_modinfo = { \
.mi_version = __NetBSD_Version__, \
.mi_class = (class), \
.mi_modcmd = name##_modcmd, \
.mi_name = #name, \
.mi_required = (required), \
.mi_ctor_section = ctor, \
.mi_dtor_section = dtor \
}; \