sys/sched_rr: Add a simple round robin scheduler module#14810
sys/sched_rr: Add a simple round robin scheduler module#14810kfessel wants to merge 10 commits intoRIOT-OS:masterfrom
Conversation
|
Would probably be a good idea to include the test application with this PR. |
sys/sched_rr/sched_rr.c
Outdated
| //this will try to reorder the current priority | ||
| //(put the current thread at the end of the list) | ||
| thread_t * active_thread = thread_get_active(); | ||
| if(active_thread != NULL){ |
There was a problem hiding this comment.
Makes me wonder: Can't we simply turn off the sched tick when we enter the idle state?
And turn it back on when we leave idle?
There was a problem hiding this comment.
it would be possible to do that (turn off on idle) or to check when switching priority if there is more than one thread in that priority run queue. That would need a little more integration with the existing scheduler.
active_thread == NULL is not a case for idle but for a thread ended and no new one is scheduled yet
|
@maribu may also like to look at this |
|
I will add a small example of the thread_duel to the PR |
maribu
left a comment
There was a problem hiding this comment.
Some inline comments mostly regarding coding style.
In addition, I think that this should be in core, as it needs to access scheduler internal data structures. IMO there should be no accesses to internals of core outside of core, only APIs should be used from outside. (An alternative to moving this to core would be to provide APIs as needed. But new core APIs need extra care for maintaining, so IMO it is better to move this to core.)
|
|
||
| /** | ||
| * @defgroup Sched_RR | ||
| * @ingroup sys |
There was a problem hiding this comment.
IMO scheduler and everything strongly coupled to it should be in core.
| /** | ||
| * time between rond robin calls default 1ms | ||
| */ | ||
| #ifndef SCHED_RR_TIMER | ||
| #define SCHED_RR_TIMER 1000 | ||
| #endif |
There was a problem hiding this comment.
| /** | |
| * time between rond robin calls default 1ms | |
| */ | |
| #ifndef SCHED_RR_TIMER | |
| #define SCHED_RR_TIMER 1000 | |
| #endif | |
| #if !defined(SCHED_RR_TIMER) || defined(DOXYGEN) | |
| /** | |
| * @brief Time between round robin calls in µs | |
| * | |
| * @details Defaults to 1ms | |
| */ | |
| #define SCHED_RR_TIMER 1000 | |
| #endif |
- You should always use the
@briefcommand. - The doxygen comment should be right before the macro it applies to
- In order to appear in the Doxygen documentation regardless of whether
SCHED_RR_TIMERis previously defined, it is best to add an|| defined(DOXYGEN).
Also: Please align the text that comes after @brief, @details etc.
| /** | ||
| * masks off priorities that should not be scheduled default 0 | ||
| */ | ||
| #ifndef SCHED_RR_MASK | ||
| #define SCHED_RR_MASK 1<<0 | ||
| #endif |
There was a problem hiding this comment.
| /** | |
| * masks off priorities that should not be scheduled default 0 | |
| */ | |
| #ifndef SCHED_RR_MASK | |
| #define SCHED_RR_MASK 1<<0 | |
| #endif | |
| #if !defined(SCHED_RR_MASK) || defined(DOXYGEN) | |
| /** | |
| * @brief masks off priorities that should not be scheduled default 0 | |
| */ | |
| #define SCHED_RR_MASK BIT0 | |
| #endif |
The macro BIT0 is provided in bitarithm.h
There was a problem hiding this comment.
i do no bitarithmetics so i rather not like to include bitarithm.h in the header (especially since its prone to conflict with other similar definitions)
i would go for #define SCHED_RR_MASK 1<<PRIO_HIGHEST if there is such a thing
| thread_t * active_thread = thread_get_active(); | ||
| if(active_thread != NULL){ | ||
| if(! (SCHED_RR_MASK & 1 << active_thread->priority)){ | ||
| clist_lpoprpush(&sched_runqueues[active_thread->priority]); |
There was a problem hiding this comment.
As this is accesses scheduler internal data structures, this should be IMO
a) Either moved to core
b) core_sched should be extended to provide a public API that this could use
I'm personally for a)
There was a problem hiding this comment.
I am not sure: wouldn't moving this to core make this not a module?
This uses xtimer which is not part of core maybe this would be a blocker for it being in core.
Aside from that i am all for it:
If we move this to core we could also go for a little bit more integration
(e.g.: switching RR on and off depending on if the current queue needs it or at least stop it on idle as @benpicco said)
There was a problem hiding this comment.
core is indeed a single module, which contains submodules. E.g. core_thread_flags enables an optional feature, which is part of core. If this would be part of core, it could be named e.g. core_sched_round_robin. (I think the extra verbosity in the module name doesn't hurt.)
This using a high level timer is to my understanding not a blocker for this being part of core. E.g. stdio is used in core for debugging and for panic(), but is not part of core.
sys/sched_rr/sched_rr.c
Outdated
| // this lets the current thread give way | ||
| // simple RoundRobin |
There was a problem hiding this comment.
Please use C style comments (e.g. /* ... */), instead of C++ style. (I'm aware that recent versions of C also support C++ style comments, but the coding conventions wants C style comments.)
The comment seems content-wise a bit confusing to me. Maybe you could rephrase it.
|
Fixed comments and coding style |
|
Probably worth adding a note that this scheduler does not attempt to be fair. e.g. you could have Here |
|
you are right i went for a as simple as possible approach to get this started |
|
what does linux do: |
|
I did some more fair RR attempt which can be seen in https://github.com/kfessel/riot-thread-duel, it uses the shed_cb to monitor the used cpu time and prefers to run the thread with the least used time. |
maribu
left a comment
There was a problem hiding this comment.
Some inline comments. You might want to consider giving uncrustify a try ;-) There is a configuration for uncrustify in the root of the RIOT repo that automatically formats your code as required by the coding convention (with some minor issues).
examples/thread-duell/main.c
Outdated
| { | ||
| int size = THREAD_STACKSIZE_DEFAULT ; | ||
| char * wech = malloc(size + 4); | ||
| * (uint32_t *) wech = 3; /* 0-10 workness*/ |
There was a problem hiding this comment.
| * (uint32_t *) wech = 3; /* 0-10 workness*/ | |
| *(uint32_t *)wech = 3; /* 0-10 workness*/ |
Also: It would improve readability if you don't abuse the stack for this, but just use distinct variables for this.
| thread_t * active_thread = thread_get_active(); | ||
| if(active_thread != NULL){ | ||
| if(! (SCHED_RR_MASK & 1 << active_thread->priority)){ | ||
| clist_lpoprpush(&sched_runqueues[active_thread->priority]); |
There was a problem hiding this comment.
core is indeed a single module, which contains submodules. E.g. core_thread_flags enables an optional feature, which is part of core. If this would be part of core, it could be named e.g. core_sched_round_robin. (I think the extra verbosity in the module name doesn't hurt.)
This using a high level timer is to my understanding not a blocker for this being part of core. E.g. stdio is used in core for debugging and for panic(), but is not part of core.
examples/thread-duell/README.md
Outdated
| Thread_Duel | ||
| ============ | ||
|
|
||
| this is a thread duell application to test RIOTS mutithreading abblities |
There was a problem hiding this comment.
Test applications should be placed in tests/
There was a problem hiding this comment.
its not a test in a unit-test sense but i replaced the word
|
should got to /Makefile.dep |
It should be in |
|
moved the the dependancy |
|
Closing this in favor of #16126 please continue the review there |
I would like to use RIOT with multiple threads at the same priority,
that might not cooperate but should share CPU time.
Contribution description
This contains a simple round robin scheduler module using xtimer to rearrange the current run queue
Testing procedure
create multiple threads of same priority that should work in parallel
without this module only one of them will run.
with this module and calling
start_schedule_rr()form#include "sched_rr.h"they run parallel , sharing cpu time.
see https://github.com/kfessel/riot-thread-duel for a demonstration.
Issues/PRs references
non yet