Oliver Kowalke
2015-09-09 0:19 GMT+02:00 Giovanni Piero Deretta
: the scheduler maintains several queues (waiting ,ready ,...) containing fiber context's depending on their state (waiting, ready ,...).
why are the wait queues part of the scheduler itself? Shouldn't they be a property of the waitable primitive?
the scheduler has a wait queue as well as each waitable primitve has a wait queue. the wait queue inside the scheduler is especially required for detached fibers at termination (~scheduler())
if a scheduler would be schedulable, it would have been a context - a scheduler would then schedule itself. I'm uncertain how your schedulable schedulers would fit in this pattern (probably not very well).
One option is scheduling schedulable entities. [...]
but there are of course advantages in knowing that each schedulable is a contex as you can swapcontext to it.
the scheduler simply know which fiber can be resuemd next. if fiber f1 has to suspend (maybe joins another fiber) it calls the scheduler to select the next fiber f2 and transfer execution control to fiber f2 (context switch). the process of selecting the next fiber and calling the context switch are running inside fiber f1. that means that we have a call chain between fibers.
I'm uncertain what schedulable::run() should execute if the schedulable is a scheduler and a context switch is called (what doesn't make sense to me).
That's up to the scheduler. But the base class is not really necessary. A nested scheduler schedule loop can be run from another fiber (let's call it the scheduler fiber). To do that it would save the original (parent) thread local scheduler pointer and replace it with the nested scheduler. When control reaches back the scheduler fiber, it would restore the original scheduler and yield. If there are no parent schedulers, the scheduler fiber is simply the underlying thread main fiber. The parent pointer is null and the scheduler wouldn't be replaced. I ask is to remove that the assumption that the scheduler is fixed. If you think about it, the system has already two schedulers: the kernel scheduler and the boost.fiber scheduler. The boost.fiber scheduler runs inside a kernel level fiber (a.k.a a thread).
Ok, I went and looked at the code. I see that on wakeup, the context is simply marked as ready. The main scheduler loop, after each scheduling event goes through the wait list and moves ready contextes to the main thread.
not main thread - it moves fibers, that have been signaled as ready, from the waiting queue to the ready queue (that is sched_algorithm::awakened() is used for). sched_algorithm::pick_next() selects a fiber from its internal ready-queue.
sorry it was a typo, s/main thread/ready queue/. -- gpd