summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2010-06-17 20:15:58 +0000
committerMichael Sevakis <jethead71@rockbox.org>2010-06-17 20:15:58 +0000
commit2b640ba4b8a0007821677fc9f3cf9e856d53417e (patch)
treeb68204a1c5a33a93980a7903bc5cb4a906af5938
parent69028d5d31384a0a97bd42081cacb01eb5d52793 (diff)
downloadrockbox-2b640ba4b8a0007821677fc9f3cf9e856d53417e.zip
rockbox-2b640ba4b8a0007821677fc9f3cf9e856d53417e.tar.gz
rockbox-2b640ba4b8a0007821677fc9f3cf9e856d53417e.tar.bz2
rockbox-2b640ba4b8a0007821677fc9f3cf9e856d53417e.tar.xz
Switch iPod 3G to use EABI toolchain. Make necessary threading changes to avoid use of stack after switching to idle stack.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26898 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/main.c6
-rw-r--r--firmware/export/thread.h2
-rw-r--r--firmware/target/hosted/sdl/thread-sdl.c5
-rw-r--r--firmware/thread.c72
-rwxr-xr-xtools/configure2
5 files changed, 54 insertions, 33 deletions
diff --git a/apps/main.c b/apps/main.c
index 858ec03..2555deb 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 8912283..d907e5d 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 5ef9867..1a68391 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 5cad67b..48734f2 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(&current->queue);
+ corelock_unlock(&current->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(&current->queue);
- corelock_unlock(&current->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 3503f84..c805f22 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