diff options
author | kfraser@localhost.localdomain <kfraser@localhost.localdomain> | 2006-11-15 09:33:01 +0000 |
---|---|---|
committer | kfraser@localhost.localdomain <kfraser@localhost.localdomain> | 2006-11-15 09:33:01 +0000 |
commit | 4aad88265bede002cb3e8a01bc6a8581c3424f6e (patch) | |
tree | 509157021cc7617217339f9d2a293dec3796d4cc /extras/mini-os/sched.c | |
parent | a4be7b6267be611349c5282363e00ae2847fc0ab (diff) | |
download | xen-4aad88265bede002cb3e8a01bc6a8581c3424f6e.tar.gz xen-4aad88265bede002cb3e8a01bc6a8581c3424f6e.tar.bz2 xen-4aad88265bede002cb3e8a01bc6a8581c3424f6e.zip |
[MINIOS] Add timer support.
Based on an original patch by Robert Kaiser.
Signed-off-by: Grzegorz Milos <gm281@cam.ac.uk>
Diffstat (limited to 'extras/mini-os/sched.c')
-rw-r--r-- | extras/mini-os/sched.c | 71 |
1 files changed, 67 insertions, 4 deletions
diff --git a/extras/mini-os/sched.c b/extras/mini-os/sched.c index ee1adb6549..e6c9cc3771 100644 --- a/extras/mini-os/sched.c +++ b/extras/mini-os/sched.c @@ -5,7 +5,7 @@ * * File: sched.c * Author: Grzegorz Milos - * Changes: + * Changes: Robert Kaiser * * Date: Aug 2005 * @@ -142,6 +142,54 @@ void inline print_runqueue(void) printk("\n"); } +/* Find the time when the next timeout expires. If this is more than + 10 seconds from now, return 10 seconds from now. */ +static s_time_t blocking_time(void) +{ + struct thread *thread; + struct list_head *iterator; + s_time_t min_wakeup_time; + unsigned long flags; + local_irq_save(flags); + /* default-block the domain for 10 seconds: */ + min_wakeup_time = NOW() + SECONDS(10); + + /* Thread list needs to be protected */ + list_for_each(iterator, &idle_thread->thread_list) + { + thread = list_entry(iterator, struct thread, thread_list); + if(!is_runnable(thread) && thread->wakeup_time != 0LL) + { + if(thread->wakeup_time < min_wakeup_time) + { + min_wakeup_time = thread->wakeup_time; + } + } + } + local_irq_restore(flags); + return(min_wakeup_time); +} + +/* Wake up all threads with expired timeouts. */ +static void wake_expired(void) +{ + struct thread *thread; + struct list_head *iterator; + s_time_t now = NOW(); + unsigned long flags; + local_irq_save(flags); + /* Thread list needs to be protected */ + list_for_each(iterator, &idle_thread->thread_list) + { + thread = list_entry(iterator, struct thread, thread_list); + if(!is_runnable(thread) && thread->wakeup_time != 0LL) + { + if(thread->wakeup_time <= now) + wake(thread); + } + } + local_irq_restore(flags); +} void schedule(void) { @@ -229,8 +277,9 @@ struct thread* create_thread(char *name, void (*function)(void *), void *data) stack_push(thread, (unsigned long) data); thread->ip = (unsigned long) thread_starter; - /* Not runable, not exited */ + /* Not runable, not exited, not sleeping */ thread->flags = 0; + thread->wakeup_time = 0LL; set_runnable(thread); local_irq_save(flags); if(idle_thread != NULL) { @@ -247,20 +296,34 @@ struct thread* create_thread(char *name, void (*function)(void *), void *data) void block(struct thread *thread) { + thread->wakeup_time = 0LL; clear_runnable(thread); } +void sleep(u32 millisecs) +{ + struct thread *thread = get_current(); + thread->wakeup_time = NOW() + MILLISECS(millisecs); + clear_runnable(thread); + schedule(); +} + void wake(struct thread *thread) { + thread->wakeup_time = 0LL; set_runnable(thread); } void idle_thread_fn(void *unused) { + s_time_t until; for(;;) { schedule(); - block_domain(10000); + /* block until the next timeout expires, or for 10 secs, whichever comes first */ + until = blocking_time(); + block_domain(until); + wake_expired(); } } @@ -278,7 +341,7 @@ void run_idle_thread(void) "push %1\n\t" "ret" :"=m" (idle_thread->sp) - :"m" (idle_thread->ip)); + :"m" (idle_thread->ip)); #endif } |