diff options
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/arm/thread-pp.c | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/firmware/target/arm/thread-pp.c b/firmware/target/arm/thread-pp.c index 335f1f3e0a..0c077779e5 100644 --- a/firmware/target/arm/thread-pp.c +++ b/firmware/target/arm/thread-pp.c | |||
@@ -199,7 +199,9 @@ static void INIT_ATTR core_thread_init(unsigned int core) | |||
199 | } | 199 | } |
200 | 200 | ||
201 | /*--------------------------------------------------------------------------- | 201 | /*--------------------------------------------------------------------------- |
202 | * Switches to a stack that always resides in the Rockbox core. | 202 | * Switches to a stack that always resides in the Rockbox core then calls |
203 | * the final exit routine to actually finish removing the thread from the | ||
204 | * scheduler. | ||
203 | * | 205 | * |
204 | * Needed when a thread suicides on a core other than the main CPU since the | 206 | * Needed when a thread suicides on a core other than the main CPU since the |
205 | * stack used when idling is the stack of the last thread to run. This stack | 207 | * stack used when idling is the stack of the last thread to run. This stack |
@@ -207,13 +209,24 @@ static void INIT_ATTR core_thread_init(unsigned int core) | |||
207 | * to use a stack from an unloaded module until another thread runs on it. | 209 | * to use a stack from an unloaded module until another thread runs on it. |
208 | *--------------------------------------------------------------------------- | 210 | *--------------------------------------------------------------------------- |
209 | */ | 211 | */ |
210 | static inline void switch_to_idle_stack(const unsigned int core) | 212 | static inline void __attribute__((noreturn,always_inline)) |
213 | thread_final_exit(struct thread_entry *current) | ||
211 | { | 214 | { |
212 | asm volatile ( | 215 | asm volatile ( |
213 | "str sp, [%0] \n" /* save original stack pointer on idle stack */ | 216 | "cmp %1, #0 \n" /* CPU? */ |
214 | "mov sp, %0 \n" /* switch stacks */ | 217 | "ldrne r0, =cpucache_flush \n" /* No? write back data */ |
215 | : : "r"(&idle_stacks[core][IDLE_STACK_WORDS-1])); | 218 | "movne lr, pc \n" |
216 | (void)core; | 219 | "bxne r0 \n" |
220 | "mov r0, %0 \n" /* copy thread parameter */ | ||
221 | "mov sp, %2 \n" /* switch to idle stack */ | ||
222 | "bl thread_final_exit_do \n" /* finish removal */ | ||
223 | : : "r"(current), | ||
224 | "r"(current->core), | ||
225 | "r"(&idle_stacks[current->core][IDLE_STACK_WORDS]) | ||
226 | : "r0", "r1", "r2", "r3", "ip", "lr"); /* Because of flush call, | ||
227 | force inputs out | ||
228 | of scratch regs */ | ||
229 | while (1); | ||
217 | } | 230 | } |
218 | 231 | ||
219 | /*--------------------------------------------------------------------------- | 232 | /*--------------------------------------------------------------------------- |