ia64/xen-unstable
changeset 12473:0839db0aa611
[MINIOS] Add timer support.
Based on an original patch by Robert Kaiser.
Signed-off-by: Grzegorz Milos <gm281@cam.ac.uk>
Based on an original patch by Robert Kaiser.
Signed-off-by: Grzegorz Milos <gm281@cam.ac.uk>
author | kfraser@localhost.localdomain |
---|---|
date | Wed Nov 15 09:33:01 2006 +0000 (2006-11-15) |
parents | 85c57682d772 |
children | 6e22ba721720 |
files | extras/mini-os/README extras/mini-os/include/sched.h extras/mini-os/include/time.h extras/mini-os/kernel.c extras/mini-os/sched.c extras/mini-os/time.c |
line diff
1.1 --- a/extras/mini-os/README Wed Nov 15 09:30:44 2006 +0000 1.2 +++ b/extras/mini-os/README Wed Nov 15 09:33:01 2006 +0000 1.3 @@ -26,5 +26,5 @@ Stuff it doesn't show: 1.4 - to start it do the following in domain0 (assuming xend is running) 1.5 # xm create domain_config 1.6 1.7 -this starts the kernel and prints out a bunch of stuff and then every 1.8 -1000 timer interrupts the system time. 1.9 +this starts the kernel and prints out a bunch of stuff and then once 1.10 +every second the system time.
2.1 --- a/extras/mini-os/include/sched.h Wed Nov 15 09:30:44 2006 +0000 2.2 +++ b/extras/mini-os/include/sched.h Wed Nov 15 09:33:01 2006 +0000 2.3 @@ -2,6 +2,7 @@ 2.4 #define __SCHED_H__ 2.5 2.6 #include <list.h> 2.7 +#include <time.h> 2.8 2.9 struct thread 2.10 { 2.11 @@ -11,6 +12,7 @@ struct thread 2.12 unsigned long ip; /* Instruction pointer */ 2.13 struct list_head thread_list; 2.14 u32 flags; 2.15 + s_time_t wakeup_time; 2.16 }; 2.17 2.18 2.19 @@ -36,5 +38,6 @@ static inline struct thread* get_current 2.20 2.21 void wake(struct thread *thread); 2.22 void block(struct thread *thread); 2.23 +void sleep(u32 millisecs); 2.24 2.25 #endif /* __SCHED_H__ */
3.1 --- a/extras/mini-os/include/time.h Wed Nov 15 09:30:44 2006 +0000 3.2 +++ b/extras/mini-os/include/time.h Wed Nov 15 09:33:01 2006 +0000 3.3 @@ -7,8 +7,9 @@ 3.4 * File: time.h 3.5 * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk) 3.6 * Changes: Grzegorz Milos (gm281@cam.ac.uk) 3.7 + * Robert Kaiser (kaiser@informatik.fh-wiesbaden.de) 3.8 * 3.9 - * Date: Jul 2003, changesJun 2005 3.10 + * Date: Jul 2003, changes: Jun 2005, Sep 2006 3.11 * 3.12 * Environment: Xen Minimal OS 3.13 * Description: Time and timer functions 3.14 @@ -57,7 +58,8 @@ struct timespec { 3.15 void init_time(void); 3.16 s_time_t get_s_time(void); 3.17 s_time_t get_v_time(void); 3.18 +u64 monotonic_clock(void); 3.19 void gettimeofday(struct timeval *tv); 3.20 -void block_domain(u32 millisecs); 3.21 +void block_domain(s_time_t until); 3.22 3.23 #endif /* _TIME_H_ */
4.1 --- a/extras/mini-os/kernel.c Wed Nov 15 09:30:44 2006 +0000 4.2 +++ b/extras/mini-os/kernel.c Wed Nov 15 09:33:01 2006 +0000 4.3 @@ -6,6 +6,7 @@ 4.4 * 4.5 * Copyright (c) 2002-2003, K A Fraser & R Neugebauer 4.6 * Copyright (c) 2005, Grzegorz Milos, Intel Research Cambridge 4.7 + * Copyright (c) 2006, Robert Kaiser, FH Wiesbaden 4.8 * 4.9 * Permission is hereby granted, free of charge, to any person obtaining a copy 4.10 * of this software and associated documentation files (the "Software"), to 4.11 @@ -66,11 +67,24 @@ void xenbus_tester(void *p) 4.12 /* test_xenbus(); */ 4.13 } 4.14 4.15 +void periodic_thread(void *p) 4.16 +{ 4.17 + struct timeval tv; 4.18 + printk("Periodic thread started.\n"); 4.19 + for(;;) 4.20 + { 4.21 + gettimeofday(&tv); 4.22 + printk("T(s=%ld us=%ld)\n", tv.tv_sec, tv.tv_usec); 4.23 + sleep(1000); 4.24 + } 4.25 +} 4.26 + 4.27 /* This should be overridden by the application we are linked against. */ 4.28 __attribute__((weak)) int app_main(start_info_t *si) 4.29 { 4.30 printk("Dummy main: start_info=%p\n", si); 4.31 create_thread("xenbus_tester", xenbus_tester, si); 4.32 + create_thread("periodic_thread", periodic_thread, si); 4.33 return 0; 4.34 } 4.35
5.1 --- a/extras/mini-os/sched.c Wed Nov 15 09:30:44 2006 +0000 5.2 +++ b/extras/mini-os/sched.c Wed Nov 15 09:33:01 2006 +0000 5.3 @@ -5,7 +5,7 @@ 5.4 * 5.5 * File: sched.c 5.6 * Author: Grzegorz Milos 5.7 - * Changes: 5.8 + * Changes: Robert Kaiser 5.9 * 5.10 * Date: Aug 2005 5.11 * 5.12 @@ -142,6 +142,54 @@ void inline print_runqueue(void) 5.13 printk("\n"); 5.14 } 5.15 5.16 +/* Find the time when the next timeout expires. If this is more than 5.17 + 10 seconds from now, return 10 seconds from now. */ 5.18 +static s_time_t blocking_time(void) 5.19 +{ 5.20 + struct thread *thread; 5.21 + struct list_head *iterator; 5.22 + s_time_t min_wakeup_time; 5.23 + unsigned long flags; 5.24 + local_irq_save(flags); 5.25 + /* default-block the domain for 10 seconds: */ 5.26 + min_wakeup_time = NOW() + SECONDS(10); 5.27 + 5.28 + /* Thread list needs to be protected */ 5.29 + list_for_each(iterator, &idle_thread->thread_list) 5.30 + { 5.31 + thread = list_entry(iterator, struct thread, thread_list); 5.32 + if(!is_runnable(thread) && thread->wakeup_time != 0LL) 5.33 + { 5.34 + if(thread->wakeup_time < min_wakeup_time) 5.35 + { 5.36 + min_wakeup_time = thread->wakeup_time; 5.37 + } 5.38 + } 5.39 + } 5.40 + local_irq_restore(flags); 5.41 + return(min_wakeup_time); 5.42 +} 5.43 + 5.44 +/* Wake up all threads with expired timeouts. */ 5.45 +static void wake_expired(void) 5.46 +{ 5.47 + struct thread *thread; 5.48 + struct list_head *iterator; 5.49 + s_time_t now = NOW(); 5.50 + unsigned long flags; 5.51 + local_irq_save(flags); 5.52 + /* Thread list needs to be protected */ 5.53 + list_for_each(iterator, &idle_thread->thread_list) 5.54 + { 5.55 + thread = list_entry(iterator, struct thread, thread_list); 5.56 + if(!is_runnable(thread) && thread->wakeup_time != 0LL) 5.57 + { 5.58 + if(thread->wakeup_time <= now) 5.59 + wake(thread); 5.60 + } 5.61 + } 5.62 + local_irq_restore(flags); 5.63 +} 5.64 5.65 void schedule(void) 5.66 { 5.67 @@ -229,8 +277,9 @@ struct thread* create_thread(char *name, 5.68 stack_push(thread, (unsigned long) data); 5.69 thread->ip = (unsigned long) thread_starter; 5.70 5.71 - /* Not runable, not exited */ 5.72 + /* Not runable, not exited, not sleeping */ 5.73 thread->flags = 0; 5.74 + thread->wakeup_time = 0LL; 5.75 set_runnable(thread); 5.76 local_irq_save(flags); 5.77 if(idle_thread != NULL) { 5.78 @@ -247,20 +296,34 @@ struct thread* create_thread(char *name, 5.79 5.80 void block(struct thread *thread) 5.81 { 5.82 + thread->wakeup_time = 0LL; 5.83 clear_runnable(thread); 5.84 } 5.85 5.86 +void sleep(u32 millisecs) 5.87 +{ 5.88 + struct thread *thread = get_current(); 5.89 + thread->wakeup_time = NOW() + MILLISECS(millisecs); 5.90 + clear_runnable(thread); 5.91 + schedule(); 5.92 +} 5.93 + 5.94 void wake(struct thread *thread) 5.95 { 5.96 + thread->wakeup_time = 0LL; 5.97 set_runnable(thread); 5.98 } 5.99 5.100 void idle_thread_fn(void *unused) 5.101 { 5.102 + s_time_t until; 5.103 for(;;) 5.104 { 5.105 schedule(); 5.106 - block_domain(10000); 5.107 + /* block until the next timeout expires, or for 10 secs, whichever comes first */ 5.108 + until = blocking_time(); 5.109 + block_domain(until); 5.110 + wake_expired(); 5.111 } 5.112 } 5.113 5.114 @@ -278,7 +341,7 @@ void run_idle_thread(void) 5.115 "push %1\n\t" 5.116 "ret" 5.117 :"=m" (idle_thread->sp) 5.118 - :"m" (idle_thread->ip)); 5.119 + :"m" (idle_thread->ip)); 5.120 #endif 5.121 } 5.122
6.1 --- a/extras/mini-os/time.c Wed Nov 15 09:30:44 2006 +0000 6.2 +++ b/extras/mini-os/time.c Wed Nov 15 09:33:01 2006 +0000 6.3 @@ -3,6 +3,7 @@ 6.4 * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge 6.5 * (C) 2002-2003 - Keir Fraser - University of Cambridge 6.6 * (C) 2005 - Grzegorz Milos - Intel Research Cambridge 6.7 + * (C) 2006 - Robert Kaiser - FH Wiesbaden 6.8 **************************************************************************** 6.9 * 6.10 * File: time.c 6.11 @@ -194,21 +195,15 @@ void gettimeofday(struct timeval *tv) 6.12 } 6.13 6.14 6.15 -static void print_current_time(void) 6.16 -{ 6.17 - struct timeval tv; 6.18 - 6.19 - gettimeofday(&tv); 6.20 - printk("T(s=%ld us=%ld)\n", tv.tv_sec, tv.tv_usec); 6.21 -} 6.22 - 6.23 - 6.24 -void block_domain(u32 millisecs) 6.25 +void block_domain(s_time_t until) 6.26 { 6.27 struct timeval tv; 6.28 gettimeofday(&tv); 6.29 - HYPERVISOR_set_timer_op(monotonic_clock() + 1000000LL * (s64) millisecs); 6.30 - HYPERVISOR_sched_op(SCHEDOP_block, 0); 6.31 + if(monotonic_clock() < until) 6.32 + { 6.33 + HYPERVISOR_set_timer_op(until); 6.34 + HYPERVISOR_sched_op(SCHEDOP_block, 0); 6.35 + } 6.36 } 6.37 6.38 6.39 @@ -217,15 +212,8 @@ void block_domain(u32 millisecs) 6.40 */ 6.41 static void timer_handler(evtchn_port_t ev, struct pt_regs *regs, void *ign) 6.42 { 6.43 - static int i; 6.44 - 6.45 get_time_values_from_xen(); 6.46 update_wallclock(); 6.47 - i++; 6.48 - if (i >= 1000) { 6.49 - print_current_time(); 6.50 - i = 0; 6.51 - } 6.52 } 6.53 6.54