diff options
-rw-r--r-- | apps/main.c | 6 | ||||
-rw-r--r-- | firmware/export/thread.h | 2 | ||||
-rw-r--r-- | firmware/target/hosted/sdl/thread-sdl.c | 5 | ||||
-rw-r--r-- | firmware/thread.c | 72 | ||||
-rwxr-xr-x | tools/configure | 2 |
5 files changed, 54 insertions, 33 deletions
diff --git a/apps/main.c b/apps/main.c index 858ec03847..2555deb12f 100644 --- a/apps/main.c +++ b/apps/main.c @@ -694,7 +694,7 @@ static void init(void) } #ifdef CPU_PP -void cop_main(void) +void __attribute__((noreturn)) cop_main(void) { /* This is the entry point for the coprocessor Anyone not running an upgraded bootloader will never reach this point, @@ -705,7 +705,6 @@ void cop_main(void) destroyed for purposes of continuity. The cop sits idle until at least one thread exists on it. */ -/* 3G doesn't have Rolo or dual core support yet */ #if NUM_CORES > 1 system_init(); kernel_init(); @@ -717,5 +716,4 @@ void cop_main(void) } #endif /* CPU_PP */ -#endif - +#endif /* SIMULATOR */ diff --git a/firmware/export/thread.h b/firmware/export/thread.h index 8912283343..d907e5dc95 100644 --- a/firmware/export/thread.h +++ b/firmware/export/thread.h @@ -375,7 +375,7 @@ void thread_thaw(unsigned int thread_id); /* Wait for a thread to exit */ void thread_wait(unsigned int thread_id); /* Exit the current thread */ -void thread_exit(void); +void thread_exit(void) __attribute__((noreturn)); #if defined(DEBUG) || defined(ROCKBOX_HAS_LOGF) #define ALLOW_REMOVE_THREAD /* Remove a thread from the scheduler */ diff --git a/firmware/target/hosted/sdl/thread-sdl.c b/firmware/target/hosted/sdl/thread-sdl.c index 5ef9867b23..1a683911d7 100644 --- a/firmware/target/hosted/sdl/thread-sdl.c +++ b/firmware/target/hosted/sdl/thread-sdl.c @@ -630,6 +630,11 @@ void remove_thread(unsigned int thread_id) void thread_exit(void) { remove_thread(THREAD_ID_CURRENT); + /* This should never and must never be reached - if it is, the + * state is corrupted */ + THREAD_PANICF("thread_exit->K:*R", + thread_id_entry(THREAD_ID_CURRENT)); + while (1); } void thread_wait(unsigned int thread_id) diff --git a/firmware/thread.c b/firmware/thread.c index 5cad67b657..48734f2ffe 100644 --- a/firmware/thread.c +++ b/firmware/thread.c @@ -156,6 +156,14 @@ static inline void store_context(void* addr) static inline void load_context(const void* addr) __attribute__((always_inline)); +#if NUM_CORES > 1 +static void __attribute__((noinline, noreturn)) + thread_final_exit(struct thread_entry *current); +#else +static void __attribute__((always_inline, noreturn)) + thread_final_exit(struct thread_entry *current); +#endif + void switch_thread(void) __attribute__((noinline)); @@ -219,7 +227,7 @@ static void thread_stkov(struct thread_entry *thread) #define LOCK_THREAD(thread) \ ({ corelock_lock(&(thread)->slot_cl); }) #define TRY_LOCK_THREAD(thread) \ - ({ corelock_try_lock(&thread->slot_cl); }) + ({ corelock_try_lock(&(thread)->slot_cl); }) #define UNLOCK_THREAD(thread) \ ({ corelock_unlock(&(thread)->slot_cl); }) #define UNLOCK_THREAD_AT_TASK_SWITCH(thread) \ @@ -854,7 +862,8 @@ struct thread_entry * * catch something. *--------------------------------------------------------------------------- */ -static void check_for_obj_waiters(const char *function, struct thread_entry *thread) +static void __attribute__((noinline)) check_for_obj_waiters( + const char *function, struct thread_entry *thread) { /* Only one bit in the mask should be set with a frequency on 1 which * represents the thread's own base priority */ @@ -1663,10 +1672,39 @@ void thread_wait(unsigned int thread_id) * Exit the current thread. The Right Way to Do Things (TM). *--------------------------------------------------------------------------- */ +/* This is done to foil optimizations that may require the current stack, + * such as optimizing subexpressions that put variables on the stack that + * get used after switching stacks. */ +static void thread_final_exit(struct thread_entry *current) +{ +#if NUM_CORES > 1 + cpucache_flush(); + + /* Switch to the idle stack if not on the main core (where "main" + * runs) - we can hope gcc doesn't need the old stack beyond this + * point. */ + if (current->core != CPU) + { + switch_to_idle_stack(current->core); + } + + /* At this point, this thread isn't using resources allocated for + * execution except the slot itself. */ +#endif /* NUM_CORES */ + + /* Signal this thread */ + thread_queue_wake(¤t->queue); + corelock_unlock(¤t->waiter_cl); + switch_thread(); + /* This should never and must never be reached - if it is, the + * state is corrupted */ + THREAD_PANICF("thread_exit->K:*R", current); + while (1); +} + void thread_exit(void) { - const unsigned int core = CURRENT_CORE; - struct thread_entry *current = cores[core].running; + register struct thread_entry * current = cores[CURRENT_CORE].running; /* Cancel CPU boost if any */ cancel_cpu_boost(); @@ -1701,34 +1739,14 @@ void thread_exit(void) /* Switch tasks and never return */ block_thread_on_l(current, STATE_KILLED); -#if NUM_CORES > 1 - /* Switch to the idle stack if not on the main core (where "main" - * runs) - we can hope gcc doesn't need the old stack beyond this - * point. */ - if (core != CPU) - { - switch_to_idle_stack(core); - } - - cpucache_flush(); - - /* At this point, this thread isn't using resources allocated for - * execution except the slot itself. */ -#endif + /* Slot must be unusable until thread is really gone */ + UNLOCK_THREAD_AT_TASK_SWITCH(current); /* Update ID for this slot */ new_thread_id(current->id, current); current->name = NULL; - /* Signal this thread */ - thread_queue_wake(¤t->queue); - corelock_unlock(¤t->waiter_cl); - /* Slot must be unusable until thread is really gone */ - UNLOCK_THREAD_AT_TASK_SWITCH(current); - switch_thread(); - /* This should never and must never be reached - if it is, the - * state is corrupted */ - THREAD_PANICF("thread_exit->K:*R", current); + thread_final_exit(current); } #ifdef ALLOW_REMOVE_THREAD diff --git a/tools/configure b/tools/configure index 3503f8493c..c805f2250e 100755 --- a/tools/configure +++ b/tools/configure @@ -40,7 +40,7 @@ prefixtools () { } findarmgcc() { - models_not_checked_with_eabi="ipodnano1g ipod3g ipod4g ipodmini1g ipod1g2g vibe500 cowond2" + models_not_checked_with_eabi="ipodnano1g ipod4g ipodmini1g ipod1g2g vibe500 cowond2" if [ "$ARG_ARM_EABI" != 1 ]; then # eabi not explicitely enabled for model in $models_not_checked_with_eabi; do if [ "$modelname" = "$model" ]; then |