Hi Juan,

On 06/12/2018 12:27 PM, Juan Ignacio Carrano wrote:
> The current RIOT scheduler will only switch between threads with the
> same priority if there is an explicit yield, or if there occurs a
> preemption by a higher priority thread.

RIOT's scheduler used to work like that: any preemption by a higher
priority thread would advance the current priority's circular runqueue.
That has been fixed years ago.
Nowadays, only if a thread calls explicit thread_yield() or it blocks,
it's "friends" will be scheduled.

> Coroutines make it possible to program asynchronous code in a 
> blocking style - see "await". This is more natural and easier that
> using callbacks.
How does it compare to sending / receiving messages?

> This is almost cooperative multithreading (within the same "priority
> group"), except there is no guarantee that after a thread in a group is
> preempted, it will be that thread an not another with the same priority
> that will get resumed. Maybe that is the current behavior, but I'm
> having some trouble understanding the scheduler code.

It *should* be current behaviour, but I'm sure there are both platforms
and modules that call "thread_yield()" instead of "thread_yield_higher()".

>> Assigning the same priority to two or more threads is usually not a
>> good idea.

Can't really argue with that, can you? ;)
More seriously, that note can definitely be improved.

> A good starting point would be to guarantee threads with the same
> priority get cooperatively scheduled 100% of the time. This means that
> if one thread is preempted by a higher priority task, then no other
> thread but that one will get resumed. In other words, the only way to
> switch between threads with the same priority is explicitly yielding
> from one.

As said, that guarantee *should* be in place, if calling a blocking
function can be considered "yielding".

We might consider to make even blocking of a thread not advance that
thread priority's run queue, but I'd be reluctant to change the
semantics that much.

> Coroutines / Fibers do not have to be full fledged threads. The TCB can
> be simpler and some objects can be shared with other fibers. 

I count 12 bytes minimum for the TCB on 32bit architectures. There's not
much more that can be shaved off, and it would not have significant
impact, as already the stack space necessary for a thread's registers
when storing the context, apart from a stack itself, is the largest part
of a thread's overhead.

> See the PR
> on a thread-safe implementation of newlib
> (https://github.com/RIOT-OS/RIOT/pull/8619) for an idea of the overhead
> that thread-safety imposes.

This is not the overhead of thread-safety per se, but of the C library
functions that were designed to save state in global variables, when
there was no multi-threading. There are thread-safe alternatives to each
one of them in the C library, which do not impose the overhead.

Kaspar

_______________________________________________
devel mailing list
devel@riot-os.org
https://lists.riot-os.org/mailman/listinfo/devel

Reply via email to