aboutsummaryrefslogtreecommitdiffstats
path: root/extras/mini-os/sched.c
diff options
context:
space:
mode:
Diffstat (limited to 'extras/mini-os/sched.c')
-rw-r--r--extras/mini-os/sched.c198
1 files changed, 62 insertions, 136 deletions
diff --git a/extras/mini-os/sched.c b/extras/mini-os/sched.c
index ee1adb6549..9b111c28e5 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
*
@@ -54,82 +54,9 @@
#define DEBUG(_f, _a...) ((void)0)
#endif
-
-#define RUNNABLE_FLAG 0x00000001
-
-#define is_runnable(_thread) (_thread->flags & RUNNABLE_FLAG)
-#define set_runnable(_thread) (_thread->flags |= RUNNABLE_FLAG)
-#define clear_runnable(_thread) (_thread->flags &= ~RUNNABLE_FLAG)
-
-
struct thread *idle_thread = NULL;
LIST_HEAD(exited_threads);
-void idle_thread_fn(void *unused);
-
-void dump_stack(struct thread *thread)
-{
- unsigned long *bottom = (unsigned long *)(thread->stack + 2*4*1024);
- unsigned long *pointer = (unsigned long *)thread->sp;
- int count;
- if(thread == current)
- {
-#ifdef __i386__
- asm("movl %%esp,%0"
- : "=r"(pointer));
-#else
- asm("movq %%rsp,%0"
- : "=r"(pointer));
-#endif
- }
- printk("The stack for \"%s\"\n", thread->name);
- for(count = 0; count < 25 && pointer < bottom; count ++)
- {
- printk("[0x%lx] 0x%lx\n", pointer, *pointer);
- pointer++;
- }
-
- if(pointer < bottom) printk(" ... continues.\n");
-}
-
-#ifdef __i386__
-#define switch_threads(prev, next) do { \
- unsigned long esi,edi; \
- __asm__ __volatile__("pushfl\n\t" \
- "pushl %%ebp\n\t" \
- "movl %%esp,%0\n\t" /* save ESP */ \
- "movl %4,%%esp\n\t" /* restore ESP */ \
- "movl $1f,%1\n\t" /* save EIP */ \
- "pushl %5\n\t" /* restore EIP */ \
- "ret\n\t" \
- "1:\t" \
- "popl %%ebp\n\t" \
- "popfl" \
- :"=m" (prev->sp),"=m" (prev->ip), \
- "=S" (esi),"=D" (edi) \
- :"m" (next->sp),"m" (next->ip), \
- "2" (prev), "d" (next)); \
-} while (0)
-#elif __x86_64__
-#define switch_threads(prev, next) do { \
- unsigned long rsi,rdi; \
- __asm__ __volatile__("pushfq\n\t" \
- "pushq %%rbp\n\t" \
- "movq %%rsp,%0\n\t" /* save RSP */ \
- "movq %4,%%rsp\n\t" /* restore RSP */ \
- "movq $1f,%1\n\t" /* save RIP */ \
- "pushq %5\n\t" /* restore RIP */ \
- "ret\n\t" \
- "1:\t" \
- "popq %%rbp\n\t" \
- "popfq" \
- :"=m" (prev->sp),"=m" (prev->ip), \
- "=S" (rsi),"=D" (rdi) \
- :"m" (next->sp),"m" (next->ip), \
- "2" (prev), "d" (next)); \
-} while (0)
-#endif
-
void inline print_runqueue(void)
{
struct list_head *it;
@@ -142,6 +69,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)
{
@@ -202,88 +177,39 @@ void exit_thread(void)
schedule();
}
-/* Pushes the specified value onto the stack of the specified thread */
-static void stack_push(struct thread *thread, unsigned long value)
-{
- thread->sp -= sizeof(unsigned long);
- *((unsigned long *)thread->sp) = value;
-}
-
-struct thread* create_thread(char *name, void (*function)(void *), void *data)
+void block(struct thread *thread)
{
- struct thread *thread;
- unsigned long flags;
-
- thread = xmalloc(struct thread);
- /* Allocate 2 pages for stack, stack will be 2pages aligned */
- thread->stack = (char *)alloc_pages(1);
- thread->name = name;
- printk("Thread \"%s\": pointer: 0x%lx, stack: 0x%lx\n", name, thread,
- thread->stack);
-
- thread->sp = (unsigned long)thread->stack + 4096 * 2;
- /* Save pointer to the thread on the stack, used by current macro */
- *((unsigned long *)thread->stack) = (unsigned long)thread;
-
- stack_push(thread, (unsigned long) function);
- stack_push(thread, (unsigned long) data);
- thread->ip = (unsigned long) thread_starter;
-
- /* Not runable, not exited */
- thread->flags = 0;
- set_runnable(thread);
- local_irq_save(flags);
- if(idle_thread != NULL) {
- list_add_tail(&thread->thread_list, &idle_thread->thread_list);
- } else if(function != idle_thread_fn)
- {
- printk("BUG: Not allowed to create thread before initialising scheduler.\n");
- BUG();
- }
- local_irq_restore(flags);
- return thread;
+ thread->wakeup_time = 0LL;
+ clear_runnable(thread);
}
-
-void block(struct thread *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();
}
}
-void run_idle_thread(void)
-{
- /* Switch stacks and run the thread */
-#if defined(__i386__)
- __asm__ __volatile__("mov %0,%%esp\n\t"
- "push %1\n\t"
- "ret"
- :"=m" (idle_thread->sp)
- :"m" (idle_thread->ip));
-#elif defined(__x86_64__)
- __asm__ __volatile__("mov %0,%%rsp\n\t"
- "push %1\n\t"
- "ret"
- :"=m" (idle_thread->sp)
- :"m" (idle_thread->ip));
-#endif
-}
-
-
-
DECLARE_MUTEX(mutex);
void th_f1(void *data)