diff --git a/makefiles/app_dirs.blacklist b/makefiles/app_dirs.blacklist index b5b1d30e212e..99a6270cb4c2 100644 --- a/makefiles/app_dirs.blacklist +++ b/makefiles/app_dirs.blacklist @@ -20,4 +20,5 @@ tests/pkg/tflite-micro/external_modules/ tests/pkg/utensor/external_modules/ tests/pkg/wolfcrypt-ed25519-verify/ tests/sys/suit_manifest/native_flashpage/ +tests/sys/event_thread_shared/external_modules/ tests/unittests/ diff --git a/makefiles/utils/strings.mk b/makefiles/utils/strings.mk index cbc280fcf005..c25e544da8fc 100644 --- a/makefiles/utils/strings.mk +++ b/makefiles/utils/strings.mk @@ -46,3 +46,8 @@ _is_equal = $(if $(and $(findstring $(1),$(2)),$(findstring $(2),$(1))),1,) version_is_greater_or_equal = $(or \ $(call _is_greater,$(call _padded_version,$1),$(call _padded_version,$2)),\ $(call _is_equal,$(call _padded_version,$1),$(call _padded_version,$2))) + +# Get the maximum number of the natural numbers given as $1 +# $1: A list of natural numbers separated by white space +# Return: The value of the highest natural number in $1 +max_number = $(shell echo $1 | awk 'BEGIN{max=0} {for(i=1;i<=NF;i++){x=$$i; if (x > max){max = x}}} END{print max}') diff --git a/makefiles/utils/test-strings.mk b/makefiles/utils/test-strings.mk index 56e48c60692e..9ca6b7cca544 100644 --- a/makefiles/utils/test-strings.mk +++ b/makefiles/utils/test-strings.mk @@ -35,3 +35,11 @@ test-version_is_greater_or_equal: $(Q)test 1 = "$(call version_is_greater_or_equal,$(TEST_VERSION_4),$(TEST_VERSION_3))" || { echo ERROR: "$(TEST_VERSION_3)" \< "$(TEST_VERSION_4)"; exit 1; } $(Q)test "" = "$(call version_is_greater_or_equal,$(TEST_VERSION_3),$(TEST_VERSION_4))" || { echo ERROR: Test should fail, "$(TEST_VERSION_4)" is not \< "$(TEST_VERSION_3)"; exit 1; } $(Q)test "" = "$(call version_is_greater_or_equal,$(TEST_VERSION_1),$(TEST_VERSION_4))" || { echo ERROR: Test should fail, "$(TEST_VERSION_1)" is not \< "$(TEST_VERSION_4)"; exit 1; } + +test-max_number: + $(Q)test "8" = "$(call max_number, 7 4 8 0 1 3)" + $(Q)test "42" = "$(call max_number, 42 4 8 0 1 3)" + $(Q)test "1337" = "$(call max_number, 42 4 8 0 1 1337)" + $(Q)test "0" = "$(call max_number, 0 0 0 0 0)" + $(Q)test "13" = "$(call max_number, 13)" + $(Q)test "0" = "$(call max_number,)" diff --git a/sys/Makefile.include b/sys/Makefile.include index 280e0851db68..80d51b4f12df 100644 --- a/sys/Makefile.include +++ b/sys/Makefile.include @@ -212,3 +212,7 @@ endif ifneq (,$(filter unicoap,$(USEMODULE))) include $(RIOTBASE)/sys/net/application_layer/unicoap/Makefile.include endif + +ifneq (,$(filter event,$(USEMODULE))) + include $(RIOTBASE)/sys/event/Makefile.include +endif diff --git a/sys/event/Makefile.include b/sys/event/Makefile.include new file mode 100644 index 000000000000..c986438e5ab2 --- /dev/null +++ b/sys/event/Makefile.include @@ -0,0 +1,35 @@ +include $(RIOTMAKE)/utils/strings.mk + +# This applies to all thread stacks +ifneq (, $(EVENT_THREAD_STACKSIZE_MIN)) + EVENT_THREAD_STACKSIZE_MIN := $(call max_number,$(EVENT_THREAD_STACKSIZE_MIN)) +endif + +ifeq (,$(filter event_thread_highest, $(USEMODULE))) + # No highest priority event thread, so the highest prio queue is handled by + # the same thread handling the medium priority queue. So we "trickle down" + # the requirements here + EVENT_THREAD_MEDIUM_STACKSIZE_MIN += $(EVENT_THREAD_HIGHEST_STACKSIZE_MIN) +else + ifneq (, $(EVENT_THREAD_HIGHEST_STACKSIZE_MIN)) + EVENT_THREAD_HIGHEST_STACKSIZE_MIN := $(call max_number,$(EVENT_THREAD_HIGHEST_STACKSIZE_MIN) $(EVENT_THREAD_STACKSIZE_MIN)) + CFLAGS += -DEVENT_THREAD_HIGHEST_STACKSIZE=$(EVENT_THREAD_HIGHEST_STACKSIZE_MIN) + endif +endif + +ifeq (,$(filter event_thread_medium, $(USEMODULE))) + # No medium priority event thread, so the medium prio queue is handled by + # the same thread handling the lowest priority queue. So we "trickle down" + # the requirements here + EVENT_THREAD_LOWEST_STACKSIZE_MIN += $(EVENT_THREAD_MEDIUM_STACKSIZE_MIN) +else + ifneq (, $(EVENT_THREAD_MEDIUM_STACKSIZE_MIN)) + EVENT_THREAD_MEDIUM_STACKSIZE_MIN := $(call max_number,$(EVENT_THREAD_MEDIUM_STACKSIZE_MIN) $(EVENT_THREAD_STACKSIZE_MIN)) + CFLAGS += -DEVENT_THREAD_MEDIUM_STACKSIZE=$(EVENT_THREAD_MEDIUM_STACKSIZE_MIN) + endif +endif + +ifneq (, $(EVENT_THREAD_LOWEST_STACKSIZE_MIN)) + EVENT_THREAD_LOWEST_STACKSIZE_MIN := $(call max_number,$(EVENT_THREAD_LOWEST_STACKSIZE_MIN) $(EVENT_THREAD_STACKSIZE_MIN)) + CFLAGS += -DEVENT_THREAD_LOWEST_STACKSIZE=$(EVENT_THREAD_LOWEST_STACKSIZE_MIN) +endif diff --git a/sys/include/event/thread.h b/sys/include/event/thread.h index 1e277bee4089..f76c0852aadc 100644 --- a/sys/include/event/thread.h +++ b/sys/include/event/thread.h @@ -44,6 +44,32 @@ * event queue gets its own thread. So higher priority events will always * preempt events of lower priority in this case. * + * Managing Stack Size Requirements + * -------------------------------- + * + * A module using the medium priority event queue might require a certain + * minimum stack size, say 1024, to operate correctly. Instead of just adding + * `CFLAGS += -DDEVENT_THREAD_MEDIUM_STACKSIZE=1024`, it can instead add the + * following to its `Makefile.dep`: + * + * ```Makefile + * EVENT_THREAD_MEDIUM_STACKSIZE_MIN += 1024 + * ``` + * + * In the `Makefile.include` of `sys/event` the highest value of the minimum + * requirements declared by any module will be picked and added to the + * `CFLAGS`. + * + * @note `EVENT_THREAD_MEDIUM_STACKSIZE_MIN` and + * `EVENT_THREAD_HIGHEST_STACKSIZE_MIN` always apply to the thread + * managing the medium priority queue. + * @details E.g. without the module `event_thread_medium` the lowest priority + * and medium priority queues are both handled by the lowest priority + * even thread. In that case, `EVENT_THREAD_MEDIUM_STACKSIZE_MIN` would + * ensure a minimum thread statck size on the lowest priority even + * thread. With `event_thread_medium` in use, it would instead apply + * to the stack of the dedicated medium event queue thread. + * * @{ * * @file diff --git a/tests/build_system/utils/Makefile b/tests/build_system/utils/Makefile index fad162b0e76d..e376f0a641a6 100644 --- a/tests/build_system/utils/Makefile +++ b/tests/build_system/utils/Makefile @@ -24,6 +24,7 @@ COMPILE_TESTS += test-uppercase COMPILE_TESTS += test-uppercase_and_underscore COMPILE_TESTS += test-version_is_greater COMPILE_TESTS += test-version_is_greater_or_equal +COMPILE_TESTS += test-max_number # Tests will be run both in the host machine and in `docker` all: build-system-utils-tests @@ -59,3 +60,6 @@ test-version_is_greater: test-version_is_greater_or_equal: $(Q)$(call command_should_succeed,"$(MAKE)" -C $(MAKEFILES_UTILS) -f test-strings.mk test-version_is_greater_or_equal) + +test-max_number: + $(Q)$(call command_should_succeed,"$(MAKE)" -C $(MAKEFILES_UTILS) -f test-strings.mk test-max_number) diff --git a/tests/sys/event_thread_shared/Makefile b/tests/sys/event_thread_shared/Makefile index 39c389aa57b4..b7774b59a175 100644 --- a/tests/sys/event_thread_shared/Makefile +++ b/tests/sys/event_thread_shared/Makefile @@ -2,4 +2,12 @@ include ../Makefile.sys_common USEMODULE += event_thread +# Test that selecting event thread size works from the modules `Makefile.dep` +# work as expected by including a bunch of empty test module +EXTERNAL_MODULE_DIRS += external_modules +USEMODULE += test_module_a +USEMODULE += test_module_b +USEMODULE += test_module_c +USEMODULE += test_module_d + include $(RIOTBASE)/Makefile.include diff --git a/tests/sys/event_thread_shared/external_modules/test_module_a/Makefile b/tests/sys/event_thread_shared/external_modules/test_module_a/Makefile new file mode 100644 index 000000000000..48422e909a47 --- /dev/null +++ b/tests/sys/event_thread_shared/external_modules/test_module_a/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/tests/sys/event_thread_shared/external_modules/test_module_a/Makefile.dep b/tests/sys/event_thread_shared/external_modules/test_module_a/Makefile.dep new file mode 100644 index 000000000000..f83f3a04cd74 --- /dev/null +++ b/tests/sys/event_thread_shared/external_modules/test_module_a/Makefile.dep @@ -0,0 +1 @@ +EVENT_THREAD_HIGHEST_STACKSIZE_MIN += 3 diff --git a/tests/sys/event_thread_shared/external_modules/test_module_b/Makefile b/tests/sys/event_thread_shared/external_modules/test_module_b/Makefile new file mode 100644 index 000000000000..48422e909a47 --- /dev/null +++ b/tests/sys/event_thread_shared/external_modules/test_module_b/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/tests/sys/event_thread_shared/external_modules/test_module_b/Makefile.dep b/tests/sys/event_thread_shared/external_modules/test_module_b/Makefile.dep new file mode 100644 index 000000000000..145df9317779 --- /dev/null +++ b/tests/sys/event_thread_shared/external_modules/test_module_b/Makefile.dep @@ -0,0 +1 @@ +EVENT_THREAD_HIGHEST_STACKSIZE_MIN += 300 diff --git a/tests/sys/event_thread_shared/external_modules/test_module_c/Makefile b/tests/sys/event_thread_shared/external_modules/test_module_c/Makefile new file mode 100644 index 000000000000..48422e909a47 --- /dev/null +++ b/tests/sys/event_thread_shared/external_modules/test_module_c/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/tests/sys/event_thread_shared/external_modules/test_module_c/Makefile.dep b/tests/sys/event_thread_shared/external_modules/test_module_c/Makefile.dep new file mode 100644 index 000000000000..82ff829e45a5 --- /dev/null +++ b/tests/sys/event_thread_shared/external_modules/test_module_c/Makefile.dep @@ -0,0 +1 @@ +EVENT_THREAD_HIGHEST_STACKSIZE_MIN += 567 diff --git a/tests/sys/event_thread_shared/external_modules/test_module_d/Makefile b/tests/sys/event_thread_shared/external_modules/test_module_d/Makefile new file mode 100644 index 000000000000..48422e909a47 --- /dev/null +++ b/tests/sys/event_thread_shared/external_modules/test_module_d/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/tests/sys/event_thread_shared/external_modules/test_module_d/Makefile.dep b/tests/sys/event_thread_shared/external_modules/test_module_d/Makefile.dep new file mode 100644 index 000000000000..015b5fd83305 --- /dev/null +++ b/tests/sys/event_thread_shared/external_modules/test_module_d/Makefile.dep @@ -0,0 +1 @@ +EVENT_THREAD_HIGHEST_STACKSIZE_MIN += 256 diff --git a/tests/sys/event_thread_shared/main.c b/tests/sys/event_thread_shared/main.c index 5945bbfce15e..c187da847be4 100644 --- a/tests/sys/event_thread_shared/main.c +++ b/tests/sys/event_thread_shared/main.c @@ -17,11 +17,17 @@ * @} */ +#include #include #include "thread.h" #include "event/thread.h" +static_assert(EVENT_THREAD_LOWEST_STACKSIZE == 567, + "Selecting highest of the minimum stack size requirements " + "declared via `EVENT_THREAD_HIGHEST_STACKSIZE_MIN += ` " + "must work correctly"); + static void _handler_high(event_t *event) { (void)event; puts("high");