ia64/xen-unstable

changeset 17473:6cd0d4d1baa3

minios: simplify schedule()
- Merge the search, wakeup, and timeout loops.
- Avoid unnecessarily switching to the idle thread.
- Perform stack release _after_ we get out of it.

Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Apr 16 10:06:34 2008 +0100 (2008-04-16)
parents e35a379e7fe9
children 774e38a40d01
files extras/mini-os/sched.c
line diff
     1.1 --- a/extras/mini-os/sched.c	Wed Apr 16 10:06:19 2008 +0100
     1.2 +++ b/extras/mini-os/sched.c	Wed Apr 16 10:06:34 2008 +0100
     1.3 @@ -70,62 +70,15 @@ void inline print_runqueue(void)
     1.4      printk("\n");
     1.5  }
     1.6  
     1.7 -/* Find the time when the next timeout expires. If this is more than
     1.8 -   10 seconds from now, return 10 seconds from now. */
     1.9 -static s_time_t blocking_time(void)
    1.10 -{
    1.11 -    struct thread *thread;
    1.12 -    struct list_head *iterator;
    1.13 -    s_time_t min_wakeup_time;
    1.14 -    unsigned long flags;
    1.15 -    local_irq_save(flags);
    1.16 -    /* default-block the domain for 10 seconds: */
    1.17 -    min_wakeup_time = NOW() + SECONDS(10);
    1.18 -
    1.19 -    /* Thread list needs to be protected */
    1.20 -    list_for_each(iterator, &idle_thread->thread_list)
    1.21 -    {
    1.22 -        thread = list_entry(iterator, struct thread, thread_list);
    1.23 -        if(!is_runnable(thread) && thread->wakeup_time != 0LL)
    1.24 -        {
    1.25 -            if(thread->wakeup_time < min_wakeup_time)
    1.26 -            {
    1.27 -                min_wakeup_time = thread->wakeup_time;
    1.28 -            }
    1.29 -        }
    1.30 -    }
    1.31 -    local_irq_restore(flags);
    1.32 -    return(min_wakeup_time);
    1.33 -}
    1.34 -
    1.35 -/* Wake up all threads with expired timeouts. */
    1.36 -static void wake_expired(void)
    1.37 -{
    1.38 -    struct thread *thread;
    1.39 -    struct list_head *iterator;
    1.40 -    s_time_t now = NOW();
    1.41 -    unsigned long flags;
    1.42 -    local_irq_save(flags);
    1.43 -    /* Thread list needs to be protected */
    1.44 -    list_for_each(iterator, &idle_thread->thread_list)
    1.45 -    {
    1.46 -        thread = list_entry(iterator, struct thread, thread_list);
    1.47 -        if(!is_runnable(thread) && thread->wakeup_time != 0LL)
    1.48 -        {
    1.49 -            if(thread->wakeup_time <= now)
    1.50 -                wake(thread);
    1.51 -        }
    1.52 -    }
    1.53 -    local_irq_restore(flags);
    1.54 -}
    1.55 -
    1.56  void schedule(void)
    1.57  {
    1.58      struct thread *prev, *next, *thread;
    1.59      struct list_head *iterator;
    1.60      unsigned long flags;
    1.61 +
    1.62      prev = current;
    1.63      local_irq_save(flags); 
    1.64 +
    1.65      if (in_callback) {
    1.66          printk("Must not call schedule() from a callback\n");
    1.67          BUG();
    1.68 @@ -134,6 +87,45 @@ void schedule(void)
    1.69          printk("Must not call schedule() with IRQs disabled\n");
    1.70          BUG();
    1.71      }
    1.72 +
    1.73 +    do {
    1.74 +        /* Examine all threads.
    1.75 +           Find a runnable thread, but also wake up expired ones and find the
    1.76 +           time when the next timeout expires, else use 10 seconds. */
    1.77 +        s_time_t now = NOW();
    1.78 +        s_time_t min_wakeup_time = now + SECONDS(10);
    1.79 +        next = NULL;   
    1.80 +        list_for_each(iterator, &idle_thread->thread_list)
    1.81 +        {
    1.82 +            thread = list_entry(iterator, struct thread, thread_list);
    1.83 +            if (!is_runnable(thread) && thread->wakeup_time != 0LL)
    1.84 +            {
    1.85 +                if (thread->wakeup_time <= now)
    1.86 +                    wake(thread);
    1.87 +                else if (thread->wakeup_time < min_wakeup_time)
    1.88 +                    min_wakeup_time = thread->wakeup_time;
    1.89 +            }
    1.90 +            if(is_runnable(thread)) 
    1.91 +            {
    1.92 +                next = thread;
    1.93 +                /* Put this thread on the end of the list */
    1.94 +                list_del(&thread->thread_list);
    1.95 +                list_add_tail(&thread->thread_list, &idle_thread->thread_list);
    1.96 +                break;
    1.97 +            }
    1.98 +        }
    1.99 +        if (next)
   1.100 +            break;
   1.101 +        /* block until the next timeout expires, or for 10 secs, whichever comes first */
   1.102 +        block_domain(min_wakeup_time);
   1.103 +        /* handle pending events if any */
   1.104 +        force_evtchn_callback();
   1.105 +    } while(1);
   1.106 +    local_irq_restore(flags);
   1.107 +    /* Interrupting the switch is equivalent to having the next thread
   1.108 +       inturrupted at the return instruction. And therefore at safe point. */
   1.109 +    if(prev != next) switch_threads(prev, next);
   1.110 +
   1.111      list_for_each(iterator, &exited_threads)
   1.112      {
   1.113          thread = list_entry(iterator, struct thread, thread_list);
   1.114 @@ -144,24 +136,6 @@ void schedule(void)
   1.115              xfree(thread);
   1.116          }
   1.117      }
   1.118 -    next = idle_thread;   
   1.119 -    /* Thread list needs to be protected */
   1.120 -    list_for_each(iterator, &idle_thread->thread_list)
   1.121 -    {
   1.122 -        thread = list_entry(iterator, struct thread, thread_list);
   1.123 -        if(is_runnable(thread)) 
   1.124 -        {
   1.125 -            next = thread;
   1.126 -            /* Put this thread on the end of the list */
   1.127 -            list_del(&thread->thread_list);
   1.128 -            list_add_tail(&thread->thread_list, &idle_thread->thread_list);
   1.129 -            break;
   1.130 -        }
   1.131 -    }
   1.132 -    local_irq_restore(flags);
   1.133 -    /* Interrupting the switch is equivalent to having the next thread
   1.134 -       inturrupted at the return instruction. And therefore at safe point. */
   1.135 -    if(prev != next) switch_threads(prev, next);
   1.136  }
   1.137  
   1.138  struct thread* create_thread(char *name, void (*function)(void *), void *data)
   1.139 @@ -267,32 +241,10 @@ void wake(struct thread *thread)
   1.140  
   1.141  void idle_thread_fn(void *unused)
   1.142  {
   1.143 -    s_time_t until;
   1.144      threads_started = 1;
   1.145 -    unsigned long flags;
   1.146 -    struct list_head *iterator;
   1.147 -    struct thread *next, *thread;
   1.148 -    for(;;)
   1.149 -    {
   1.150 +    while (1) {
   1.151 +        block(current);
   1.152          schedule();
   1.153 -        next = NULL;
   1.154 -        local_irq_save(flags);
   1.155 -        list_for_each(iterator, &idle_thread->thread_list)
   1.156 -        {
   1.157 -            thread = list_entry(iterator, struct thread, thread_list);
   1.158 -            if(is_runnable(thread)) 
   1.159 -            {
   1.160 -                next = thread;
   1.161 -                break;
   1.162 -            }
   1.163 -        }
   1.164 -        if (!next) {
   1.165 -            /* block until the next timeout expires, or for 10 secs, whichever comes first */
   1.166 -            until = blocking_time();
   1.167 -            block_domain(until);
   1.168 -        }
   1.169 -        local_irq_restore(flags);
   1.170 -        wake_expired();
   1.171      }
   1.172  }
   1.173