• Ingo Molnar's avatar
    · 873cbfcf
    Ingo Molnar authored
    - i've extended the scheduler context-switch mechanism with the following
      per-arch defines:
    
            prepare_arch_schedule(prev_task);
            finish_arch_schedule(prev_task);
            prepare_arch_switch(rq);
            finish_arch_switch(rq);
    
    - plus switch_to() takes 3 parameters again:
    
            switch_to(prev, next, last);
    
    - schedule_tail() has the 'prev' task parameter again, it must be passed
      over in switch_to() and passed in to the fork() startup path.
    
    architectures that need to unlock the runqueue before doing the switch can
    do the following:
    
     #define prepare_arch_schedule(prev)             task_lock(prev)
     #define finish_arch_schedule(prev)              task_unlock(prev)
     #define prepare_arch_switch(rq)                 spin_unlock(&(rq)->lock)
     #define finish_arch_switch(rq)                  __sti()
    
    this way the task-lock makes sure that a task is not scheduled on some
    other CPU before the switch-out finishes, but the runqueue lock is
    dropped. (Local interrupts are kept disabled in this variant, just to
    exclude things like TLB flushes - if that matters.)
    
    architectures that can hold the runqueue lock during context-switch can do
    the following simplification:
    
     #define prepare_arch_schedule(prev)             do { } while(0)
     #define finish_arch_schedule(prev)              do { } while(0)
     #define prepare_arch_switch(rq)                 do { } while(0)
     #define finish_arch_switch(rq)                  spin_unlock_irq(&(rq)->lock)
    
    further optimizations possible in the 'simple' variant:
    
    - an architecture does not have to handle the 'last' parameter in
      switch_to() if the 'prev' parameter is unused in finish_arch_schedule().
      This way the inlined return value of context_switch() too gets optimized
      away at compile-time.
    
    - an architecture does not have to pass the 'prev' pointer to
      schedule_tail(), if the 'prev' parameter is unused in
      finish_arch_schedule().
    
    the x86 architecture makes use of these optimizations.
    
    Via this solution we have a reasonably flexible context-switch setup which
    falls back to the current (faster) code on x86, but on other platforms the
    runqueue lock can be dropped before doing the context-switch as well.
    
            Ingo
    
    NOTE: i have coded and tested the 'complex' variant on x86 as well to make
          sure it works for you on Sparc64 - but since x86's switch_mm() is
          not too subtle it can use the simpler variant. [ The following
          things had to be done to make x86 arch use the complex variant: the
          4 complex macros have to be used in system.h, entry.S has to
          'pushl %ebx' and 'addl $4, %esp' around the call to schedule_tail(),
          and switch_to() had to be reverted to the 3-parameter variant
          present in the 2.4 kernels.
    
    NOTE2: prepare_to_switch() functionality has been moved into the
           prepare_arch_switch() macro.
    
    NOTE3: please use macros for prepare|finish_arch_switch() so that we can
           keep the scheduler data structures internal to sched.c.
    873cbfcf
entry.S 17.2 KB