core: Make support for multi-tasking optional#11226
core: Make support for multi-tasking optional#11226maribu wants to merge 5 commits intoRIOT-OS:masterfrom
Conversation
|
Rebased to fix merge conflict |
The bss memory isn't saved, as it is mostly stack memory, which in the single-task case is not displayed. 800b code on arm, is that worth the extra complexity? |
This only partly true. The idle-thread is gone and so is the stack of the idle thread. Also the scheduler requires > 100B RAM with multi-tasking, and 2B / 4B (AVR/ARM) in single-threading. E.g. on ARM Cortex M
This is a good question. I didn't touch any platform specific code and did not look into any. If I had to guess, I would bet that the compiler was able to identify unreachable code in AVR in the single-tasked version, that is used by the scheduler in the multi-tasked version.
The stats on this PR look more frightening that the changes actually are. E.g. by splitting up |
|
I think it makes more sense to also have |
|
OK, I did so now and added a few additional workarounds to get MSP430 and PIC32 compiling. If this approach is considered for including, the platform specific code can be adapted to no longer need the workarounds, which could yield some additional bytes of ROM/RAM - or none if the compiler already elides such features as functions to save and restore context. |
cpu/msp430_common/cpu.c
Outdated
| { | ||
| sched_active_thread = sched_threads[0]; | ||
| /* FIXME: This line seems to be unneeded. Is this true? */ | ||
| /* sched_active_thread = sched_threads[0]; */ |
There was a problem hiding this comment.
TODO: Does this line of code have a purpose? sched_run() will set sched_active_thread anyway, right?
Well, they look like most of core/ has two versions now. @maribu, as is, I'll NACK this PR. Let's please first remove the (need for the) idle thread, then see from there. |
|
Update: Added some |
You miscounted ;-) There are two versions of The things not having two versions are: |
`void cpu_switch_context_exit(void)` assigns `sched_active_thread` just before calling `sched_run()`. This is unneeded, as `sched_run()` will updated that anyway. Also generally speaking, changing internal scheduler data from outside the scheduler is a risky thing to do.
|
Fore reference: The old state is backed up here: https://github.com/maribu/RIOT/tree/single_tasking_bak |
I agree that this is clearly beneficial I'll sure help with that. But I don't see the relation to this PR. Removing the idle thread will lower resource requirements in the multi-tasking scenario. But this PR tries to introduce a single-task scenario. Both ideas have the common goal of reducing resource requirements, but I do not see any dependency between them. I changed this PR to keep the folder structure as is. I had to add a bit of preprocessor magic to The mock scheduler stuff is also still in place to allow compiling on ARM/AVR/MSP430/MIPS. (For ESP the linker is fine with unresolved symbols, so I did not add workarounds there.) If this approach is considered for merging, the workarounds can be dropped once the architecture specific code is prepared for non-multi-tasking mode, which likely will shrink the firmware a bit more. Having riotboot as use case in mind, there seem to be a need for this. Allowing a "single-threaded" mode with official APIs instead of overwriting @miri64: Could you have a look if this approach could be an alternative for #10971? The current implementation allows for |
|
I'm wondering what someone's intention might be to use a multi-threaded system like RIOT if it does not require multitasking. Realizing a single-task system which can be integrated in a RIOT network can't be the intention since networking requires multi-threading. So, the only intention I see is that someone could want to use the pool of drivers. But is this really a use case which is worth to restructure the kernel and to adapt all MCU implementations? At least for ESPs I can say, that they will never work as single task systems since SDK libraries already require multi-tasking. |
I think this would go further: the PR tries to make it possible to remove the multithreading parts. I think of it as in "what applications would benefit". none comes to mind. |
The idle thread is the single largest unneeded RAM consumer when multithreading is enabled but only a single thread is used, having it removed benefits all deployments and makes disabling multithreading less attractive. |
|
@gschorcht: I agree that on the ESP platform it is impossible and also unreasonable, as even the ESP8266 have plenty of flash and RAM. The idea is to allow specialized single purpose applications to be written with RIOT with minimal resource requirements. One use case is riotboot, as users will want to spend as little flash as possible for the boot loader. ~1KiB flash saving is really nice to have there. |
riotboot is already using only a fraction of the multithreading code. It would benefit much more from much simpler changes which would also benefit a wider range of deployments. E.g., #10767 reduces its size from ~2.6K flash to 1.2k. |
|
@maribu This PR might affect PRs #10934, #10943, and #10944. They all rely on the fact that system is always operating on thread stacks or on the ISR stack, and the standard stack is no longer used once |
|
I personally wouldn't take this PR into account for others, regardless if it will be considered for inclusion. If single threaded mode will be added, it will only be used in very specific scenarios where the user has to expect things to break. I personally would just add to the documentation, that |
Agreed. Approaches that can yield more benefit and apply to more use cases should get priority. |
|
Let's close this PR for now. If there is still a reason to add this once other approaches to reduce RIOT's footprint for simple tasks have been merge, it can be opened again. |
|
Now that |
|
Not really. With only a single thread, idling becomes rather trivial: Just call If you want to push for this route, a series of smaller and less scary PRs might be what is needed. |
Contribution description
Summary
Made multi-tasking support optional via module
multi_taskingand enabled it by default. Added alternative implementations of parts of thethreadAPI and themutexAPI that are used when multi-tasking is disabled. These implementations heavily exploit the fact that only a single thread is present then.To avoid resolving complex dependencies between core and architecture depend code in a single PR, this PR adds some workaround code to mock the scheduler API. This is not intended to stay
How to Use
Build with your application using
(
core_msgneeds to be disabled as well, as it depends on multi-tasking supportand will pull
multi_taskingback in if not disabled as well.)Concept
The idea is that most code not requiring multi-tasking support can be compiled unmodified with multi-tasking disabled. This can only be achieved by providing all RIOT APIs that can be used more or less reasonable in a single-tasking environment. The implementation of these APIs range from total mock versions (e.g.
thread_yield()) that simple don't do anything to specialized implementations (e.g.mutex), that exploit the fact that code can only run in two contexts: In the single thread or in ISR context.Outlook
Currently mock APIs for internal stuff like
sched_context_switch_requestandsched_task_exit()andsched_run()are also provided, as the platform specific code relies on their existence. By making the platform depended code aware of single-tasking, a lot of code could be elided there as well. This would ultimately allow to drop the mock APIs fromsched.hfor the single-tasking flavour of RIOT.Numbers
(OUTDATED!)
textdatabssnucleo-f303rearduino-uno(Negative numbers sizes means disabling multi tasking resulted in lower memory footprint, positive means memory footprint increased. I compilied with
BUILD_IN_DOCKER=1.)Testing procedure
Everything but
examples/hello-worldshould compile and run as nothing ever happened, as multi-tasking support is enabled by default. Inexamples/hello-worldmulti tasking support has been disabled, but it hopefully still compiles and runs as beforeIssues/PRs references
#11199
Depends on and includes
Update 1: Updated description to match the code changes
Update 2: #11228 is merged, rebase against master is still needed