From a690ebb1d1925e4f443c8ea7047c9b183e931d2a Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Mon, 30 Jul 2007 16:44:36 +0000 Subject: Trim a little bulk off the scheduler for dual core. Shouldn't change bin size on single except for a small function call avoidance. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14075 a1c6a512-1295-4272-9138-f99709370657 --- firmware/thread.c | 94 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 50 insertions(+), 44 deletions(-) diff --git a/firmware/thread.c b/firmware/thread.c index b8bfeb4ef3..eba27b74d5 100644 --- a/firmware/thread.c +++ b/firmware/thread.c @@ -388,12 +388,11 @@ static void remove_from_list(struct thread_entry **list, static void check_sleepers(void) __attribute__ ((noinline)); static void check_sleepers(void) { + const unsigned int core = CURRENT_CORE; struct thread_entry *current, *next; /* Check sleeping threads. */ - current = cores[CURRENT_CORE].sleeping; - if (current == NULL) - return ; + current = cores[core].sleeping; for (;;) { @@ -403,12 +402,12 @@ static void check_sleepers(void) { /* Sleep timeout has been reached so bring the thread * back to life again. */ - remove_from_list(&cores[CURRENT_CORE].sleeping, current); - add_to_list(&cores[CURRENT_CORE].running, current); + remove_from_list(&cores[core].sleeping, current); + add_to_list(&cores[core].running, current); current->statearg = 0; /* If there is no more processes in the list, break the loop. */ - if (cores[CURRENT_CORE].sleeping == NULL) + if (cores[core].sleeping == NULL) break; current = next; @@ -419,7 +418,7 @@ static void check_sleepers(void) /* Break the loop once we have walked through the list of all * sleeping processes. */ - if (current == cores[CURRENT_CORE].sleeping) + if (current == cores[core].sleeping) break; } } @@ -429,14 +428,15 @@ static void check_sleepers(void) static void wake_list_awaken(void) __attribute__ ((noinline)); static void wake_list_awaken(void) { + const unsigned int core = CURRENT_CORE; int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); /* No need for another check in the IRQ lock since IRQs are allowed only to add threads to the waking list. They won't be adding more until we're done here though. */ - struct thread_entry *waking = cores[CURRENT_CORE].waking; - struct thread_entry *running = cores[CURRENT_CORE].running; + struct thread_entry *waking = cores[core].waking; + struct thread_entry *running = cores[core].running; if (running != NULL) { @@ -452,33 +452,36 @@ static void wake_list_awaken(void) { /* Just transfer the list as-is - just came out of a core * sleep. */ - cores[CURRENT_CORE].running = waking; + cores[core].running = waking; } /* Done with waking list */ - cores[CURRENT_CORE].waking = NULL; + cores[core].waking = NULL; set_irq_level(oldlevel); } static inline void sleep_core(void) { + const unsigned int core = CURRENT_CORE; + for (;;) { /* We want to do these ASAP as it may change the decision to sleep the core or the core has woken because an interrupt occurred and posted a message to a queue. */ - if (cores[CURRENT_CORE].waking != NULL) + if (cores[core].waking != NULL) wake_list_awaken(); - if (cores[CURRENT_CORE].last_tick != current_tick) + if (cores[core].last_tick != current_tick) { - check_sleepers(); - cores[CURRENT_CORE].last_tick = current_tick; + if (cores[core].sleeping != NULL) + check_sleepers(); + cores[core].last_tick = current_tick; } /* We must sleep until there is at least one process in the list * of running processes. */ - if (cores[CURRENT_CORE].running != NULL) + if (cores[core].running != NULL) break; /* Enter sleep mode to reduce power usage, woken up on interrupt */ @@ -508,34 +511,35 @@ void profile_thread(void) { static void change_thread_state(struct thread_entry **blocked_list) __attribute__ ((noinline)); static void change_thread_state(struct thread_entry **blocked_list) { + const unsigned int core = CURRENT_CORE; struct thread_entry *old; unsigned long new_state; /* Remove the thread from the list of running threads. */ - old = cores[CURRENT_CORE].running; + old = cores[core].running; new_state = GET_STATE(old->statearg); /* Check if a thread state change has been requested. */ if (new_state) { /* Change running thread state and switch to next thread. */ - remove_from_list(&cores[CURRENT_CORE].running, old); + remove_from_list(&cores[core].running, old); /* And put the thread into a new list of inactive threads. */ if (new_state == STATE_BLOCKED) add_to_list(blocked_list, old); else - add_to_list(&cores[CURRENT_CORE].sleeping, old); + add_to_list(&cores[core].sleeping, old); #ifdef HAVE_PRIORITY_SCHEDULING /* Reset priorities */ - if (old->priority == cores[CURRENT_CORE].highest_priority) - cores[CURRENT_CORE].highest_priority = 100; + if (old->priority == cores[core].highest_priority) + cores[core].highest_priority = 100; #endif } else /* Switch to the next running thread. */ - cores[CURRENT_CORE].running = old->next; + cores[core].running = old->next; } /*--------------------------------------------------------------------------- @@ -544,8 +548,10 @@ static void change_thread_state(struct thread_entry **blocked_list) */ void switch_thread(bool save_context, struct thread_entry **blocked_list) { + const unsigned int core = CURRENT_CORE; + #ifdef RB_PROFILE - profile_thread_stopped(get_threadnum(cores[CURRENT_CORE].running)); + profile_thread_stopped(get_threadnum(cores[core].running)); #endif unsigned int *stackptr; @@ -560,13 +566,13 @@ void switch_thread(bool save_context, struct thread_entry **blocked_list) * to this call. */ if (save_context) { - store_context(&cores[CURRENT_CORE].running->context); + store_context(&cores[core].running->context); /* Check if the current thread stack is overflown */ - stackptr = cores[CURRENT_CORE].running->stack; + stackptr = cores[core].running->stack; if(stackptr[0] != DEADBEEF) #ifdef THREAD_EXTRA_CHECKS - thread_panicf("Stkov", cores[CURRENT_CORE].running, NULL); + thread_panicf("Stkov", cores[core].running, NULL); #else thread_stkov(); #endif @@ -577,10 +583,10 @@ void switch_thread(bool save_context, struct thread_entry **blocked_list) /* This has to be done after the scheduler is finished with the blocked_list pointer so that an IRQ can't kill us by attempting a wake but before attempting any core sleep. */ - if (cores[CURRENT_CORE].switch_to_irq_level != STAY_IRQ_LEVEL) + if (cores[core].switch_to_irq_level != STAY_IRQ_LEVEL) { - int level = cores[CURRENT_CORE].switch_to_irq_level; - cores[CURRENT_CORE].switch_to_irq_level = STAY_IRQ_LEVEL; + int level = cores[core].switch_to_irq_level; + cores[core].switch_to_irq_level = STAY_IRQ_LEVEL; set_irq_level(level); } } @@ -595,34 +601,34 @@ void switch_thread(bool save_context, struct thread_entry **blocked_list) * got CPU time. */ for (;;) { - int priority = cores[CURRENT_CORE].running->priority; + int priority = cores[core].running->priority; - if (priority < cores[CURRENT_CORE].highest_priority) - cores[CURRENT_CORE].highest_priority = priority; + if (priority < cores[core].highest_priority) + cores[core].highest_priority = priority; - if (priority == cores[CURRENT_CORE].highest_priority || - (current_tick - cores[CURRENT_CORE].running->last_run > + if (priority == cores[core].highest_priority || + (current_tick - cores[core].running->last_run > priority * 8) || - cores[CURRENT_CORE].running->priority_x != 0) + cores[core].running->priority_x != 0) { break; } - cores[CURRENT_CORE].running = cores[CURRENT_CORE].running->next; + cores[core].running = cores[core].running->next; } /* Reset the value of thread's last running time to the current time. */ - cores[CURRENT_CORE].running->last_run = current_tick; + cores[core].running->last_run = current_tick; #endif #endif unlock_cores(); /* And finally give control to the next thread. */ - load_context(&cores[CURRENT_CORE].running->context); + load_context(&cores[core].running->context); #ifdef RB_PROFILE - profile_thread_started(get_threadnum(cores[CURRENT_CORE].running)); + profile_thread_started(get_threadnum(cores[core].running)); #endif } @@ -819,7 +825,7 @@ void wakeup_thread_irq_safe(struct thread_entry **list) struct thread_entry* create_thread(void (*function)(void), void* stack, int stack_size, const char *name IF_PRIO(, int priority) - IF_COP(, unsigned int core, bool fallback)) + IF_COP(, unsigned int core, bool fallback)) { unsigned int i; unsigned int stacklen; @@ -845,8 +851,8 @@ struct thread_entry* { if (fallback) return create_thread(function, stack, stack_size, name - IF_PRIO(, priority) IF_COP(, CPU, false)); - else + IF_PRIO(, priority) IF_COP(, CPU, false)); + else return NULL; } #endif @@ -929,7 +935,7 @@ void trigger_cpu_boost(void) void remove_thread(struct thread_entry *thread) { lock_cores(); - + if (thread == NULL) thread = cores[CURRENT_CORE].running; @@ -995,7 +1001,7 @@ struct thread_entry * thread_get_current(void) void init_threads(void) { - unsigned int core = CURRENT_CORE; + const unsigned int core = CURRENT_CORE; int slot; /* Let main CPU initialize first. */ -- cgit v1.2.3