Skip to content

core/sched_round_robin: Add a simple round robin scheduler to core#15069

Closed
kfessel wants to merge 1 commit intoRIOT-OS:masterfrom
kfessel:sched_rr_core
Closed

core/sched_round_robin: Add a simple round robin scheduler to core#15069
kfessel wants to merge 1 commit intoRIOT-OS:masterfrom
kfessel:sched_rr_core

Conversation

@kfessel
Copy link
Copy Markdown
Contributor

@kfessel kfessel commented Sep 23, 2020

includes example
USEMODULE activate round robin for all not masked priorities

inspired by the comments on #14810 i created a core variant of a round robin scheduler

Contribution description

This contains a simple round robin for the core scheduler using xtimer to rearrange the run queue.

nothing special is done about fainess to keep this low in memory consumption.

Testing procedure

compile the example either with or without USEMODULE += sched_round_robin

without this module only one of the threads will run.
with this module they run parallel , sharing cpu time.

Issues/PRs references

similar but non core: #14810

@kfessel
Copy link
Copy Markdown
Contributor Author

kfessel commented Sep 23, 2020

maybe @maribu and @benpicco want to have a look at this since they where the most active reviewers on #14810

@maribu maribu requested review from benpicco and maribu September 23, 2020 13:42
Copy link
Copy Markdown
Member

@maribu maribu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some inline comments. I didn't look into the concepts or implementation details yet. Feel free to directly squash in all the style issues.

/**
* @brief masks off priorities that should not be scheduled default: 0 is masked
*/
#define SCHED_RR_MASK 1<<0
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#define SCHED_RR_MASK 1<<0
#define SCHED_RR_MASK (1 << 0)

Comment on lines +50 to +53
/**
* @brief setup the round robin timer for prio
*/
void set_sched_round_robin(uint8_t prio);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing documentation for parameter prio.

It would be nice if all functions would contain a common prefix. E.g. sched_rr_...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i will switch the function names around from "set_sched_round_robin" to "sched_round_robin_set"
since the is no need to keep set_.. public i will be static inline

if (current_rr_priority != 0xff) {
DEBUG_PUTS("Round_Robin_cb");
clist_lpoprpush(&sched_runqueues[current_rr_priority]);
thread_t * active_thread = thread_get_active();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
thread_t * active_thread = thread_get_active();
thread_t *active_thread = thread_get_active();

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i still not understand why you like to put the type close to the name and have no space between type and name

DEBUG_PUTS("Round_Robin_cb");
clist_lpoprpush(&sched_runqueues[current_rr_priority]);
thread_t * active_thread = thread_get_active();
if(active_thread){
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if(active_thread){
if (active_thread) {

thread_t * active_thread = thread_get_active();
if(active_thread){
uint8_t active_priority = active_thread->priority;
if(active_priority == current_rr_priority){
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if(active_priority == current_rr_priority){
if (active_priority == current_rr_priority) {

if(current_rr_priority == prio){
remove_sched_round_robin();
thread_t * active_thread = thread_get_active();
if(active_thread){
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if(active_thread){
if (active_thread) {

}


void * thread_bad(void * d)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
void * thread_bad(void * d)
void * thread_bad(void *d)

{
xtimer_usleep64(200 * 1000); /*allways be nice at start*/
#ifdef DEVELHELP
const char * name = thread_get_active()->name;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const char * name = thread_get_active()->name;
const char *name = thread_get_active()->name;

#endif

uint32_t w = 0;
uint32_t work = * (uint32_t *) d;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
uint32_t work = * (uint32_t *) d;
uint32_t work = *((uint32_t *)d);

Comment on lines +56 to +59
/**
* @brief setup round robin for priority if possible an sensible
*/
void check_set_sched_round_robin(uint8_t prio);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the documentation it is not clear what the difference is to set_sched_round_robin(). Do we really need two functions?

IMO we should try not to provide largely overlapping functions to the public. It will confuse users (they have to decide on a specific version of a function-family) and it increases the maintenance burden.

(Note: I'm certainly a huge fan of many small internal functions that help de-duplicating and structuring code. My comment above only applies for the public APIs.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are right i already thought about making set_sched_round_robin() static an suggest inlineing to the compiler

includes example
USEMODULE activate round robin for all not masked prioritys
@kfessel
Copy link
Copy Markdown
Contributor Author

kfessel commented Sep 23, 2020

added style changes and squashed

@fjmolinas
Copy link
Copy Markdown
Contributor

I'm personally against adding a dependency to xtimer in core.

@fjmolinas
Copy link
Copy Markdown
Contributor

I'm personally against adding a dependency to xtimer in core.

I know this is why @kfessel had included this functionality in sys in the initial PR, so I agree with his initial thought.

@maribu
Copy link
Copy Markdown
Member

maribu commented Sep 24, 2020

I'm personally against adding a dependency to xtimer in core.

I know this is why @kfessel had included this functionality in sys in the initial PR, so I agree with his initial thought.

How about extending core/sched with the required round robin primitives. An implementation in sys could then use this public API in conjunction with xtimer to implement round robin scheduling.

I'm personally strongly against code outside of core (and to some degree cpu) touching any internals in core. This had led to quite some pain before.

@kfessel
Copy link
Copy Markdown
Contributor Author

kfessel commented Sep 24, 2020

It would be very difficult to split this thing right at the calls to xtimer the result would be a xtimer like interface on top of it wich would also have to reside in sys since it uses xtimer and would be called from core since there is the RR logic, one could add something like shed_cb to call in case of any timer function work which would make implementing scheduler modules in sys possible but this would also require the sys to manipulate the core structures like sys/sched_rr did; we could extend the interfaces to the runqueues in core and use them from sys. which would mean it is either very specific to RR (eg provide a function that switches to the next task in a runqueue) or very inefficient (maybe both at the same time)

this core variant has some advantages over the sys version (not running when it is not needed) through to deeper integration <- i like that;
the sys variant has asside from manipulating core structures very low impact on the rest of the code <- i like that;
I am hassitant to do a deep interating thing which is than keept in sys.
We could instead of deepending on xtimer depend on a generic timer implementation which we keep in core like some systick an decide on the hardware base which implementation to take. i think such a thing could be a littlebit simpler than x/ztimer but i dont think i would be much.

@kfessel
Copy link
Copy Markdown
Contributor Author

kfessel commented Sep 25, 2020

There some features in core that depend on sys-modules being present they are activated when the sys-module is configured: auto_init (depends on sys/auto-init) and panic-ps-printing (depends on sys/ps) and panic usb-board-reset (depends on sys/usb_board_reset), ps also reads internal core structures, and board reset will certainly change them (considdering this i could move the core variant to sys (but i don't think this wold be more readable).
For statistics there is a real clean single purpose interface created for one sys-module (which can be replaced by another user)

I know this i quiet a stretch to argument that there are already dependancies of core on sys, but i can also add a && MODULE_XTIMER to the if defs deactivating the feature if no xtimer is present making it just a configurable core feature that only get activated when xtimer is present (like panic-ps).

There is another example a very hard dependency from core to sys: libc is considered sys as far as i can see and it is used by core not only a single function but also many types, this dependency is never questioned (no #ifdef) it is always a given that there is a libc in sys and core uses it.

@kfessel
Copy link
Copy Markdown
Contributor Author

kfessel commented Mar 17, 2021

Closing this in favor of #16126 please continue the review there

@kfessel kfessel closed this Mar 17, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants