diff --git a/src/libs/compat/freebsd_network/Jamfile b/src/libs/compat/freebsd_network/Jamfile index 1e0e6d0741..7280b5919b 100644 --- a/src/libs/compat/freebsd_network/Jamfile +++ b/src/libs/compat/freebsd_network/Jamfile @@ -47,6 +47,7 @@ KernelStaticLibrary libfreebsd_network.a : subr_autoconf.cpp synch.c systm.cpp + sysinit.c taskqueue.c unit.cpp ; diff --git a/src/libs/compat/freebsd_network/compat/sys/kernel.h b/src/libs/compat/freebsd_network/compat/sys/kernel.h index 2494b15828..2524baaf42 100644 --- a/src/libs/compat/freebsd_network/compat/sys/kernel.h +++ b/src/libs/compat/freebsd_network/compat/sys/kernel.h @@ -32,24 +32,45 @@ int32_t get_ticks(); #define usecs_to_ticks(t) (((bigtime_t)t*hz) / 1000000) -typedef void (*system_init_func_t)(void *); - -struct __system_init { - system_init_func_t func; +/* sysinit */ +enum sysinit_elem_order { + SI_ORDER_FIRST = 0x0000000, + SI_ORDER_SECOND = 0x0000001, + SI_ORDER_THIRD = 0x0000002, + SI_ORDER_FOURTH = 0x0000003, + SI_ORDER_MIDDLE = 0x1000000, + SI_ORDER_ANY = 0xfffffff /* last */ }; -/* TODO implement SYSINIT/SYSUNINIT subsystem */ -#define SYSINIT(uniquifier, subsystem, order, func, ident) \ - struct __system_init __init_##uniquifier = { (system_init_func_t) func } +typedef void (*system_init_func_t)(void *); -#define SYSUNINIT(uniquifier, subsystem, order, func, ident) \ - struct __system_init __uninit_##uniquifier = { (system_init_func_t) func } - - -#define TUNABLE_INT(path, var) -#define TUNABLE_INT_FETCH(path, var) +struct sysinit { + const char* name; + enum sysinit_elem_order order; + system_init_func_t func; + const void* arg; +}; + +#define SYSINIT(uniquifier, subsystem, _order, _func, ident) \ +static struct sysinit sysinit_##uniquifier = { \ + .name = #uniquifier, \ + .order = _order, \ + .func = _func, \ + .arg = ident, \ +}; \ +DATA_SET(__freebsd_sysinit, sysinit_##uniquifier) + +#define SYSUNINIT(uniquifier, subsystem, _order, _func, ident) \ +static struct sysinit sysuninit_##uniquifier = { \ + .name = #uniquifier, \ + .order = _order, \ + .func = _func, \ + .arg = ident, \ +}; \ +DATA_SET(__freebsd_sysuninit, sysuninit_##uniquifier) +/* confighooks */ typedef void (*ich_func_t)(void *_arg); struct intr_config_hook { @@ -62,4 +83,9 @@ int config_intrhook_establish(struct intr_config_hook *hook); void config_intrhook_disestablish(struct intr_config_hook *hook); +/* misc. */ +#define TUNABLE_INT(path, var) +#define TUNABLE_INT_FETCH(path, var) + + #endif // _FBSD_COMPAT_SYS_KERNEL_H_ diff --git a/src/libs/compat/freebsd_network/driver.c b/src/libs/compat/freebsd_network/driver.c index 05a3f26e4b..50d7d4373c 100644 --- a/src/libs/compat/freebsd_network/driver.c +++ b/src/libs/compat/freebsd_network/driver.c @@ -13,6 +13,7 @@ #include "device.h" +#include "sysinit.h" #include #include @@ -133,6 +134,8 @@ _fbsd_init_drivers(driver_t *drivers[]) goto err5; } + init_sysinit(); + status = init_wlan_stack(); if (status < B_OK) goto err6; @@ -194,9 +197,11 @@ err7: uninit_wlan_stack(); err6: + uninit_sysinit(); if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) uninit_taskqueues(); err5: + uninit_bounce_pages(); uninit_callout(); err4: uninit_mbufs(); @@ -224,6 +229,7 @@ _fbsd_uninit_drivers(driver_t *drivers[]) } uninit_wlan_stack(); + uninit_sysinit(); if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) uninit_taskqueues(); uninit_bounce_pages(); diff --git a/src/libs/compat/freebsd_network/sysinit.c b/src/libs/compat/freebsd_network/sysinit.c new file mode 100644 index 0000000000..107beb3f3b --- /dev/null +++ b/src/libs/compat/freebsd_network/sysinit.c @@ -0,0 +1,68 @@ +/* + * Copyright 2018, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#include "sysinit.h" + +#include +#include + + +//#define TRACE_SYSINIT +#ifdef TRACE_SYSINIT +# define TRACE(x...) dprintf(x) +#else +# define TRACE(x...) +#endif + + +/* linker sets */ +SET_DECLARE(__freebsd_sysinit, struct sysinit); +SET_DECLARE(__freebsd_sysuninit, struct sysinit); + +/* make sure there's something in both linker sets, so we can link */ +SYSINIT(__dummy, 0, 0, NULL, NULL); +SYSUNINIT(__dummy, 0, 0, NULL, NULL); + + +void +init_sysinit() +{ + struct sysinit* const* initee; + const enum sysinit_elem_order orders[6] = { + SI_ORDER_FIRST, SI_ORDER_SECOND, SI_ORDER_THIRD, SI_ORDER_FOURTH, + SI_ORDER_MIDDLE, SI_ORDER_ANY, + }; + uint32 i; + + for (i = 0; i < 6; i++) { + SET_FOREACH(initee, __freebsd_sysinit) { + if ((*initee)->order != orders[i] || (*initee)->func == NULL) + continue; + TRACE("sysinit: %d, %d, %s\n", orders[i], (*initee)->order, + (*initee)->name); + (*initee)->func((*initee)->arg); + } + } +} + + +void +uninit_sysinit() +{ + struct sysinit* const* initee; + const enum sysinit_elem_order orders[6] = { + SI_ORDER_FIRST, SI_ORDER_SECOND, SI_ORDER_THIRD, SI_ORDER_FOURTH, + SI_ORDER_MIDDLE, SI_ORDER_ANY, + }; + uint32 i; + + for (i = 5; i >= 0; i--) { + SET_FOREACH(initee, __freebsd_sysuninit) { + if ((*initee)->order != orders[i] || (*initee)->func == NULL) + continue; + TRACE("sysinit: de-initializing %s\n", (*initee)->name); + (*initee)->func((*initee)->arg); + } + } +} diff --git a/src/libs/compat/freebsd_network/sysinit.h b/src/libs/compat/freebsd_network/sysinit.h new file mode 100644 index 0000000000..b1bda3a077 --- /dev/null +++ b/src/libs/compat/freebsd_network/sysinit.h @@ -0,0 +1,13 @@ +/* + * Copyright 2018, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef SYSINIT_H +#define SYSINIT_H + + +void init_sysinit(); +void uninit_sysinit(); + + +#endif /* SYSINIT_H */