diff -r 9977b8785570 extras/mini-os/README --- a/extras/mini-os/README Fri Sep 29 19:12:15 2006 +0100 +++ b/extras/mini-os/README Sun Oct 01 00:56:02 2006 +0200 @@ -26,5 +26,5 @@ Stuff it doesn't show: - to start it do the following in domain0 (assuming xend is running) # xm create domain_config -this starts the kernel and prints out a bunch of stuff and then every -1000 timer interrupts the system time. +this starts the kernel and prints out a bunch of stuff and then once +every second the system time. diff -r 9977b8785570 extras/mini-os/include/sched.h --- a/extras/mini-os/include/sched.h Fri Sep 29 19:12:15 2006 +0100 +++ b/extras/mini-os/include/sched.h Sun Oct 01 00:34:44 2006 +0200 @@ -2,6 +2,7 @@ #define __SCHED_H__ #include +#include struct thread { @@ -11,6 +12,7 @@ struct thread unsigned long ip; /* Instruction pointer */ struct list_head thread_list; u32 flags; + s_time_t wakeup_time; }; @@ -36,5 +38,6 @@ static inline struct thread* get_current void wake(struct thread *thread); void block(struct thread *thread); +void sleep(u32 millisecs); #endif /* __SCHED_H__ */ diff -r 9977b8785570 extras/mini-os/include/time.h --- a/extras/mini-os/include/time.h Fri Sep 29 19:12:15 2006 +0100 +++ b/extras/mini-os/include/time.h Sun Oct 01 00:35:36 2006 +0200 @@ -7,8 +7,9 @@ * File: time.h * Author: Rolf Neugebauer (neugebar@xxxxxxxxxxxxx) * Changes: Grzegorz Milos (gm281@xxxxxxxxx) + * Robert Kaiser (kaiser@xxxxxxxxxxxxxxxxxxxxxxxxxx) * - * Date: Jul 2003, changesJun 2005 + * Date: Jul 2003, changes: Jun 2005, Sep 2006 * * Environment: Xen Minimal OS * Description: Time and timer functions @@ -57,7 +58,8 @@ void init_time(void); void init_time(void); s_time_t get_s_time(void); s_time_t get_v_time(void); +u64 monotonic_clock(void); void gettimeofday(struct timeval *tv); -void block_domain(u32 millisecs); +void block_domain(s_time_t until); #endif /* _TIME_H_ */ diff -r 9977b8785570 extras/mini-os/kernel.c --- a/extras/mini-os/kernel.c Fri Sep 29 19:12:15 2006 +0100 +++ b/extras/mini-os/kernel.c Sun Oct 01 00:37:22 2006 +0200 @@ -6,6 +6,7 @@ * * Copyright (c) 2002-2003, K A Fraser & R Neugebauer * Copyright (c) 2005, Grzegorz Milos, Intel Research Cambridge + * Copyright (c) 2006, Robert Kaiser, FH Wiesbaden * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -66,11 +67,24 @@ void xenbus_tester(void *p) /* test_xenbus(); */ } +void periodic_thread(void *p) +{ + struct timeval tv; + printk("Periodic thread started.\n"); + for(;;) + { + gettimeofday(&tv); + printk("T(s=%ld us=%ld)\n", tv.tv_sec, tv.tv_usec); + sleep(1000); + } +} + /* This should be overridden by the application we are linked against. */ __attribute__((weak)) int app_main(start_info_t *si) { printk("Dummy main: start_info=%p\n", si); create_thread("xenbus_tester", xenbus_tester, si); + create_thread("periodic_thread", periodic_thread, si); return 0; } diff -r 9977b8785570 extras/mini-os/sched.c --- a/extras/mini-os/sched.c Fri Sep 29 19:12:15 2006 +0100 +++ b/extras/mini-os/sched.c Sun Oct 01 00:50:49 2006 +0200 @@ -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, 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 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 } diff -r 9977b8785570 extras/mini-os/time.c --- a/extras/mini-os/time.c Fri Sep 29 19:12:15 2006 +0100 +++ b/extras/mini-os/time.c Sun Oct 01 00:31:41 2006 +0200 @@ -3,6 +3,7 @@ * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge * (C) 2002-2003 - Keir Fraser - University of Cambridge * (C) 2005 - Grzegorz Milos - Intel Research Cambridge + * (C) 2006 - Robert Kaiser - FH Wiesbaden **************************************************************************** * * File: time.c @@ -194,21 +195,15 @@ void gettimeofday(struct timeval *tv) } -static void print_current_time(void) -{ - struct timeval tv; - - gettimeofday(&tv); - printk("T(s=%ld us=%ld)\n", tv.tv_sec, tv.tv_usec); -} - - -void block_domain(u32 millisecs) +void block_domain(s_time_t until) { struct timeval tv; gettimeofday(&tv); - HYPERVISOR_set_timer_op(monotonic_clock() + 1000000LL * (s64) millisecs); - HYPERVISOR_sched_op(SCHEDOP_block, 0); + if(monotonic_clock() < until) + { + HYPERVISOR_set_timer_op(until); + HYPERVISOR_sched_op(SCHEDOP_block, 0); + } } @@ -217,15 +212,8 @@ void block_domain(u32 millisecs) */ static void timer_handler(evtchn_port_t ev, struct pt_regs *regs, void *ign) { - static int i; - get_time_values_from_xen(); update_wallclock(); - i++; - if (i >= 1000) { - print_current_time(); - i = 0; - } }