Hi Gabriele,

On 04/04/25 10:45, Gabriele Monaco wrote:
> Add a per-task monitor for task switches as part of the sched model:
> 
> * srs:
>     Monitor to describe conditions for different types of task switch.
>     This monitor enforces rules such as preempt after setting need
>     for reschedule and suspend after setting a task to sleepable.
> 
> This new monitor implies the previously introduced snroc (set non
> runnable on its own context), so replace that monitor with srs.
> 
> Cc: Ingo Molnar <[email protected]>
> Cc: Peter Zijlstra <[email protected]>
> Signed-off-by: Gabriele Monaco <[email protected]>
> ---

...

> +Monitor srs
> +-----------
> +
> +The switch after resched or sleep (srs) monitor describes conditions for
> +different types of task switch. This is a complex model, below we are going 
> to

Quite the ASCII art indeed. :-)

> +explain it step by step. Unfortunately splitting this into smaller monitor is
> +not trivial due to some shared events such as ``switch_in``::

Not splitting, but maybe providing several separate diagrams for the key
cases and transitions might help grasping the complete picture? Not
sure, just a thought.

In the below, set_{sleepable,runnable} corresponds to set_state_
{sleepable,runnable} in the code, does it? Not a big deal, but I was
confused at first.

Thanks,
Juri

> +
> +                                                      set_runnable
> +                                  |                        wakeup +---+
> +                                  |                   switch_vain |   |
> +                                  v                               |   v      
> wakeup
> +                         #================================================#  
> set_runnable
> +      switch_in          H                                                H 
> <----------+
> +    +------------------> H                    running                     H  
>           |
> +    |                    H                                                H 
> -----+     |
> +    |                    #================================================#  
>     |     |
> +    |                         |        |                |         ^    ^     
>     |     |
> +    |                         |  switch_yield      need_resched   |    |     
>     |     |
> +    |                         |        |      need_resched_lazy   |    |     
>     |     |
> +    |                set_sleepable     v                |         |    |     
>     |     |
> +    |                         |      +-------------+    |         |    |     
>     |     |
> +    |                +--------+----> |  preempted  | ---+- switch_in   |     
>     |     |
> +    |                |        |      +-------------+    |              |     
>     |     |
> +    |        switch_preempt   |        |                |              |     
>     |     |
> +    |        switch_yield     |   need_resched          |   +- switch_vain   
>     |     |
> +    |                |        |        v                |   |                
>     |     |
> +    |                |        |      +-------------+    |   |                
>     |     |
> +    |  need_resched -+--------+----> | resched_out |    |   |                
>     |     |
> +    |  |             |        |      +-------------+    |   |                
>     |     |
> +    |  |             |        |        |                |   |     
> need_resched   |     |
> +    |  |             |        |    switch_in            |   |     wakeup     
>     |     |
> +    |  |             |        |        v                v   |     
> set_runnable   |     |
> +    |  |             |        |      +--------------------------+ -------+   
>     |     |
> +    |  |             |        |      |                          |        |   
>     |     |
> +    |  |             +--------+----- |       rescheduling       | <------+   
>     |     |
> +    |  |                      |      |                          |            
>     |     |
> +    |  |                      |      +--------------------------+ 
> -----------+   |     |
> +    |  |                      |        |           ^ wakeup                  
> |   |     |
> +    |  |                      |  set_sleepable   set_runnable                
> |   |     |
> +    |  |                      |        v           |                         
> |   |     |
> +    |  |   +------------------+----- +---------------------------+           
> |   |     |
> +    |  |   |                  |      |                           |           
> |   |     |
> + +--+--+---+------------------+----> |     resched_sleepable     | ---+      
> |   |     |
> + |  |  |   |                  |      |                           |    |      
> |   |     |
> + |  |  |   |    +-------------+----> +---------------------------+    |      
> |   |     |
> + |  |  |   |    |             |        |           ^      |           |      
> |   |     |
> + |  |  |   |    |             |  switch_preempt    | need_resched     |      
> |   |     |
> + |  |  |   |    |             |        |           | set_sleepable    |      
> |   |     |
> + |  |  |   |    |             |        v           +------+           |      
> |   |     |
> + |  |  |   |    |             |       +---------------------------+ 
> --+------+---+-----+--+
> + |  |  |   |    |             |       |    preempted_sleepable    |   |      
> |   |     |  |
> + |  |  |   |    |             |       +---------------------------+ 
> --+------+---+--+  |  |
> + |  |  |   |    |             |         |             ^               |      
> |   |  |  |  |
> + |  |  |   |    |             |     switch_in   switch_preempt        |      
> |   |  |  |  |
> + |  |  |   |    |             |         v             |          switch_vain 
> |   |  |  |  |
> + |  |  |   |    |             |        +-------------------------+    |      
> |   |  |  |  |
> + |  |  |   |    |             +------> |                         | <--+      
> |   |  |  |  |
> + |  |  |   |    |                      |        sleepable        |           
> |   |  |  |  |
> + |  |  |   |    +- need_resched------- |                         | 
> ----------+---+--+--+  |
> + |  |  |   |       need_resched_lazy   +-------------------------+           
> |   |  |     |
> + |  |  |   |                              |      ^      |          
> switch_block  |  |     |
> + |  |  |   |                              |      | set_sleepable             
> |   |  |     |
> + |  |  |   |                      switch_block   | switch_vain    
> +----------+   |  |     |
> + |  |  |   |                    switch_suspend   +------+         |          
>     |  |     |
> + |  |  |   |                              v                       v          
>     |  |     |
> + |  |  |   |   switch_block          +-----------------------------+  
> switch_block  |     |
> + |  |  |   +-switch_suspend--------> |          sleeping           | 
> <-----------+  |     |
> + |  |  |                             +-----------------------------+         
>        |     |
> + |  |  |                               | wakeup                              
>        |     |
> + |  |  |                               v                                     
>        |     |
> + |  |  +- need_resched ------------- +-------------+  wakeup                 
>        |     |
> + |  |                                |   waking    | 
> <------------------------------+     |
> + |  +------------------------------- +-------------+                         
>              |
> + |                                                                           
>              |
> + |                         +-----------------------+                         
>              |
> + +----- switch_in -------- | resched_out_sleepable | <-- sched_need_resched 
> --------------+
> +                           +-----------------------+
> +
> +Types of switches:
> +
> +* ``switch_in``:
> +  a non running task is scheduled in, this leads to ``running`` if the task 
> is
> +  runnable and ``sleepable`` if the task was preempted before sleeping.
> +* ``switch_suspend``:
> +  a task puts itself to sleep, this can happen only after explicitly setting
> +  the task to ``sleepable``. After a task is suspended, it needs to be woken 
> up
> +  (``waking`` state) before being switched in again. The task can be set to
> +  ``resched_sleepable`` via a ``need_resched`` but not preempted, in which 
> case it
> +  is equivalent to ``sleepable``.
> +  Setting the task's state to ``sleepable`` can be reverted before switching 
> if it
> +  is woken up or set to runnable.
> +* ``switch_blocked``:
> +  a special case of a ``switch_suspend`` where the task is waiting on a
> +  sleeping RT lock (``PREEMPT_RT`` only), it is common to see wakeup and set
> +  state events racing with each other and this leads the model to perceive 
> this
> +  type of switch when the task is not set to sleepable. This is a limitation 
> of
> +  the model in SMP system and workarounds may require to slow down the
> +  scheduler.
> +* ``switch_yield``:
> +  a task explicitly calls the scheduler, this looks like a preemption as the
> +  task is still runnable but the ``need_resched`` flag is not set. It can
> +  happen after a ``yield`` system call or from the idle task.
> +* ``switch_preempt``:
> +  a task is ``preempted``, this can happen after the need for 
> ``rescheduling``
> +  has been set, also in its ``lazy`` flavour. ``need_resched`` can be set as 
> a
> +  flag to the task or in the per-core preemption count, either of them can
> +  trigger a preemption.
> +  The task was previously running and can be switched in directly, but it is
> +  possible that a task is preempted after it sets itself as ``sleepable``
> +  (``preempted_sleepable``), in this condition, once the task is switched 
> back
> +  in, it will not be ``running`` but continue its sleeping process in
> +  ``sleepable``.
> +* ``switch_vain``:
> +  a task goes through the scheduler but it is picked as the next task to run,
> +  hence no real task switch occurs. Since we run the scheduler, this clears 
> the
> +  need to reschedule.
> +

...

> +enum events_srs {
> +     sched_need_resched_srs = 0,
> +     sched_need_resched_lazy_srs,
> +     sched_set_state_runnable_srs,
> +     sched_set_state_sleepable_srs,
> +     sched_switch_blocking_srs,
> +     sched_switch_in_srs,
> +     sched_switch_preempt_srs,
> +     sched_switch_suspend_srs,
> +     sched_switch_vain_srs,
> +     sched_switch_yield_srs,
> +     sched_wakeup_srs,
> +     event_max_srs
> +};
> +


Reply via email to