summaryrefslogtreecommitdiffstats
path: root/firmware/target
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2012-01-04 18:07:21 +0100
committerThomas Martitz <kugel@rockbox.org>2012-01-22 18:46:44 +0100
commit991ae1e39553172a7dd6cd8c634aebfce892e261 (patch)
tree672a4583af663def399c4fefdbad060605397fbc /firmware/target
parenteaa83bd64775b87e943d345e2810deed44408776 (diff)
downloadrockbox-991ae1e39553172a7dd6cd8c634aebfce892e261.tar.gz
rockbox-991ae1e39553172a7dd6cd8c634aebfce892e261.tar.bz2
rockbox-991ae1e39553172a7dd6cd8c634aebfce892e261.zip
Create fimrware/asm directory for assembly optimized stuff.
This dir is suitable for stuff that doesn't fit the target tree, e.g. because it also builds on hosted or otherwise. It also has a generic subfolder for fallback C implementations so that not all archs need to provide asm files. SOURCES should only contain "foo.c" where foo.c includes the specific <arch>/foo.c files from the subdirs using the preprocessor. This way automatic selection of asm versions or generic C verion is possible. For the start, the thread support files are moved, since ASM threads can be used on hosted platforms as well. Since core_sleep() remains platform specific it's moved to the corresponding system.h headers. Change-Id: Iebff272f3407a6eaafeb7656ceb0ae9eca3f7cb9
Diffstat (limited to 'firmware/target')
-rw-r--r--firmware/target/arm/system-arm.h27
-rw-r--r--firmware/target/arm/thread-arm.c121
-rw-r--r--firmware/target/coldfire/system-target.h10
-rw-r--r--firmware/target/coldfire/thread-coldfire.c111
-rw-r--r--firmware/target/hosted/android/system-target.h5
-rw-r--r--firmware/target/hosted/sdl/system-sdl.h9
-rw-r--r--firmware/target/hosted/system-hosted.h37
-rw-r--r--firmware/target/hosted/thread-arm.c99
-rw-r--r--firmware/target/hosted/thread-unix.c316
-rw-r--r--firmware/target/hosted/thread-win32.c85
-rw-r--r--firmware/target/hosted/ypr0/system-target.h5
-rw-r--r--firmware/target/mips/ingenic_jz47xx/system-target.h24
-rw-r--r--firmware/target/mips/thread-mips32.c133
-rw-r--r--firmware/target/sh/system-target.h14
-rw-r--r--firmware/target/sh/thread-sh.c109
15 files changed, 116 insertions, 989 deletions
diff --git a/firmware/target/arm/system-arm.h b/firmware/target/arm/system-arm.h
index ffce77a176..719ec82f1b 100644
--- a/firmware/target/arm/system-arm.h
+++ b/firmware/target/arm/system-arm.h
@@ -347,4 +347,31 @@ static inline uint32_t swaw32_hw(uint32_t value)
}
+#if defined(CPU_TCC780X) || defined(CPU_TCC77X) /* Single core only for now */ \
+|| CONFIG_CPU == IMX31L || CONFIG_CPU == DM320 || CONFIG_CPU == AS3525 \
+|| CONFIG_CPU == S3C2440 || CONFIG_CPU == S5L8701 || CONFIG_CPU == AS3525v2 \
+|| CONFIG_CPU == S5L8702
+/* Use the generic ARMv4/v5/v6 wait for IRQ */
+static inline void core_sleep(void)
+{
+ asm volatile (
+ "mcr p15, 0, %0, c7, c0, 4 \n" /* Wait for interrupt */
+#if CONFIG_CPU == IMX31L
+ "nop\n nop\n nop\n nop\n nop\n" /* Clean out the pipes */
+#endif
+ : : "r"(0)
+ );
+ enable_irq();
+}
+#else
+/* Skip this if special code is required and implemented */
+#if !(defined(CPU_PP)) && CONFIG_CPU != RK27XX && CONFIG_CPU != IMX233
+static inline void core_sleep(void)
+{
+ /* TODO: core_sleep not implemented, battery life will be decreased */
+ enable_irq();
+}
+#endif /* CPU_PP */
+#endif
+
#endif /* SYSTEM_ARM_H */
diff --git a/firmware/target/arm/thread-arm.c b/firmware/target/arm/thread-arm.c
deleted file mode 100644
index 88dac2542a..0000000000
--- a/firmware/target/arm/thread-arm.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2005 by Thom Johansen
- *
- * Generic ARM threading support
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-/*---------------------------------------------------------------------------
- * Start the thread running and terminate it if it returns
- *---------------------------------------------------------------------------
- */
-static void __attribute__((naked)) USED_ATTR start_thread(void)
-{
- /* r0 = context */
- asm volatile (
- "ldr sp, [r0, #32] \n" /* Load initial sp */
- "ldr r4, [r0, #40] \n" /* start in r4 since it's non-volatile */
- "mov r1, #0 \n" /* Mark thread as running */
- "str r1, [r0, #40] \n"
-#if NUM_CORES > 1
- "ldr r0, =commit_discard_idcache \n" /* Invalidate this core's cache. */
- "mov lr, pc \n" /* This could be the first entry into */
- "bx r0 \n" /* plugin or codec code for this core. */
-#endif
- "mov lr, pc \n" /* Call thread function */
- "bx r4 \n"
- ); /* No clobber list - new thread doesn't care */
- thread_exit();
-#if 0
- asm volatile (".ltorg"); /* Dump constant pool */
-#endif
-}
-
-/* For startup, place context pointer in r4 slot, start_thread pointer in r5
- * slot, and thread function pointer in context.start. See load_context for
- * what happens when thread is initially going to run. */
-#define THREAD_STARTUP_INIT(core, thread, function) \
- ({ (thread)->context.r[0] = (uint32_t)&(thread)->context, \
- (thread)->context.r[1] = (uint32_t)start_thread, \
- (thread)->context.start = (uint32_t)function; })
-
-
-/*---------------------------------------------------------------------------
- * Store non-volatile context.
- *---------------------------------------------------------------------------
- */
-static inline void store_context(void* addr)
-{
- asm volatile(
- "stmia %0, { r4-r11, sp, lr } \n"
- : : "r" (addr)
- );
-}
-
-/*---------------------------------------------------------------------------
- * Load non-volatile context.
- *---------------------------------------------------------------------------
- */
-static inline void load_context(const void* addr)
-{
- asm volatile(
- "ldr r0, [%0, #40] \n" /* Load start pointer */
- "cmp r0, #0 \n" /* Check for NULL */
-
- /* If not already running, jump to start */
-#if ARM_ARCH == 4 && defined(USE_THUMB)
- "ldmneia %0, { r0, r12 } \n"
- "bxne r12 \n"
-#else
- "ldmneia %0, { r0, pc } \n"
-#endif
-
- "ldmia %0, { r4-r11, sp, lr } \n" /* Load regs r4 to r14 from context */
- : : "r" (addr) : "r0" /* only! */
- );
-}
-
-#if defined(CPU_TCC780X) || defined(CPU_TCC77X) /* Single core only for now */ \
-|| CONFIG_CPU == IMX31L || CONFIG_CPU == DM320 || CONFIG_CPU == AS3525 \
-|| CONFIG_CPU == S3C2440 || CONFIG_CPU == S5L8701 || CONFIG_CPU == AS3525v2 \
-|| CONFIG_CPU == S5L8702
-/* Use the generic ARMv4/v5/v6 wait for IRQ */
-static inline void core_sleep(void)
-{
- asm volatile (
- "mcr p15, 0, %0, c7, c0, 4 \n" /* Wait for interrupt */
-#if CONFIG_CPU == IMX31L
- "nop\n nop\n nop\n nop\n nop\n" /* Clean out the pipes */
-#endif
- : : "r"(0)
- );
- enable_irq();
-}
-#else
-/* Skip this if special code is required and implemented */
-#if !(defined(CPU_PP)) && CONFIG_CPU != RK27XX && CONFIG_CPU != IMX233
-static inline void core_sleep(void)
-{
- /* TODO: core_sleep not implemented, battery life will be decreased */
- enable_irq();
-}
-#endif /* CPU_PP */
-#endif
-
-
diff --git a/firmware/target/coldfire/system-target.h b/firmware/target/coldfire/system-target.h
index 74767c4583..5c810eb9b1 100644
--- a/firmware/target/coldfire/system-target.h
+++ b/firmware/target/coldfire/system-target.h
@@ -223,4 +223,14 @@ void commit_discard_idcache(void);
static inline void commit_discard_dcache(void) {}
static inline void commit_dcache(void) {}
+/*---------------------------------------------------------------------------
+ * Put core in a power-saving state if waking list wasn't repopulated.
+ *---------------------------------------------------------------------------
+ */
+static inline void core_sleep(void)
+{
+ /* Supervisor mode, interrupts enabled upon wakeup */
+ asm volatile ("stop #0x2000");
+};
+
#endif /* SYSTEM_TARGET_H */
diff --git a/firmware/target/coldfire/thread-coldfire.c b/firmware/target/coldfire/thread-coldfire.c
deleted file mode 100644
index e59a9390ba..0000000000
--- a/firmware/target/coldfire/thread-coldfire.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2004 by Linus Nielsen Feltzing
- *
- * Coldfire processor threading support
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-/*---------------------------------------------------------------------------
- * Start the thread running and terminate it if it returns
- *---------------------------------------------------------------------------
- */
-void start_thread(void); /* Provide C access to ASM label */
-static void USED_ATTR __start_thread(void)
-{
- /* a0=macsr, a1=context */
- asm volatile (
- "start_thread: \n" /* Start here - no naked attribute */
- "move.l %a0, %macsr \n" /* Set initial mac status reg */
- "lea.l 48(%a1), %a1 \n"
- "move.l (%a1)+, %sp \n" /* Set initial stack */
- "move.l (%a1), %a2 \n" /* Fetch thread function pointer */
- "clr.l (%a1) \n" /* Mark thread running */
- "jsr (%a2) \n" /* Call thread function */
- );
- thread_exit();
-}
-
-/* Set EMAC unit to fractional mode with saturation for each new thread,
- * since that's what'll be the most useful for most things which the dsp
- * will do. Codecs should still initialize their preferred modes
- * explicitly. Context pointer is placed in d2 slot and start_thread
- * pointer in d3 slot. thread function pointer is placed in context.start.
- * See load_context for what happens when thread is initially going to
- * run.
- */
-#define THREAD_STARTUP_INIT(core, thread, function) \
- ({ (thread)->context.macsr = EMAC_FRACTIONAL | EMAC_SATURATE, \
- (thread)->context.d[0] = (uint32_t)&(thread)->context, \
- (thread)->context.d[1] = (uint32_t)start_thread, \
- (thread)->context.start = (uint32_t)(function); })
-
-/*---------------------------------------------------------------------------
- * Store non-volatile context.
- *---------------------------------------------------------------------------
- */
-static inline void store_context(void* addr)
-{
- asm volatile (
- "move.l %%macsr,%%d0 \n"
- "movem.l %%d0/%%d2-%%d7/%%a2-%%a7,(%0) \n"
- : : "a" (addr) : "d0" /* only! */
- );
-}
-
-/*---------------------------------------------------------------------------
- * Load non-volatile context.
- *---------------------------------------------------------------------------
- */
-static inline void load_context(const void* addr)
-{
- asm volatile (
- "move.l 52(%0), %%d0 \n" /* Get start address */
- "beq.b 1f \n" /* NULL -> already running */
- "movem.l (%0), %%a0-%%a2 \n" /* a0=macsr, a1=context, a2=start_thread */
- "jmp (%%a2) \n" /* Start the thread */
- "1: \n"
- "movem.l (%0), %%d0/%%d2-%%d7/%%a2-%%a7 \n" /* Load context */
- "move.l %%d0, %%macsr \n"
- : : "a" (addr) : "d0" /* only! */
- );
-}
-
-/*---------------------------------------------------------------------------
- * Put core in a power-saving state if waking list wasn't repopulated.
- *---------------------------------------------------------------------------
- */
-static inline void core_sleep(void)
-{
- /* Supervisor mode, interrupts enabled upon wakeup */
- asm volatile ("stop #0x2000");
-};
-
-/*---------------------------------------------------------------------------
- * Call this from asm to make sure the sp is pointing to the
- * correct place before the context is saved.
- *---------------------------------------------------------------------------
- */
-static inline void _profile_thread_stopped(int current_thread)
-{
- asm volatile ("move.l %[id], -(%%sp)\n\t"
- "jsr profile_thread_stopped\n\t"
- "addq.l #4, %%sp\n\t"
- :: [id] "r" (current_thread)
- : "cc", "memory");
-}
diff --git a/firmware/target/hosted/android/system-target.h b/firmware/target/hosted/android/system-target.h
index aba7e6d6c0..fd81b6661e 100644
--- a/firmware/target/hosted/android/system-target.h
+++ b/firmware/target/hosted/android/system-target.h
@@ -23,10 +23,7 @@
#define __SYSTEM_TARGET_H__
#include "kernel-unix.h"
-
-static inline void commit_dcache(void) {}
-static inline void commit_discard_dcache(void) {}
-static inline void commit_discard_idcache(void) {}
+#include "system-hosted.h"
/* don't pull in jni.h for every user of this file, it should be only needed
* within the target tree (if at all)
diff --git a/firmware/target/hosted/sdl/system-sdl.h b/firmware/target/hosted/sdl/system-sdl.h
index d607e5e0a6..a20cbe5fac 100644
--- a/firmware/target/hosted/sdl/system-sdl.h
+++ b/firmware/target/hosted/sdl/system-sdl.h
@@ -41,6 +41,8 @@ int set_irq_level(int level);
#define restore_irq(level) \
((void)set_irq_level(level))
+#include "system-hosted.h"
+
void sim_enter_irq_handler(void);
void sim_exit_irq_handler(void);
void sim_kernel_shutdown(void);
@@ -48,17 +50,10 @@ void sys_poweroff(void);
void sys_handle_argv(int argc, char *argv[]);
void gui_message_loop(void);
void sim_do_exit(void) NORETURN_ATTR;
-#ifndef HAVE_SDL_THREADS
-void wait_for_interrupt(void);
-#endif
extern bool background; /* True if the background image is enabled */
extern bool showremote;
extern int display_zoom;
extern long start_tick;
-static inline void commit_dcache(void) {}
-static inline void commit_discard_dcache(void) {}
-static inline void commit_discard_idcache(void) {}
-
#endif /* _SYSTEM_SDL_H_ */
diff --git a/firmware/target/hosted/system-hosted.h b/firmware/target/hosted/system-hosted.h
new file mode 100644
index 0000000000..e60803fde0
--- /dev/null
+++ b/firmware/target/hosted/system-hosted.h
@@ -0,0 +1,37 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2010 by Thomas Martitz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef __SYSTEM_HOSTED_H__
+#define __SYSTEM_HOSTED_H__
+
+#include "system.h"
+
+static inline void commit_dcache(void) {}
+static inline void commit_discard_dcache(void) {}
+static inline void commit_discard_idcache(void) {}
+
+static inline void core_sleep(void)
+{
+ enable_irq();
+ wait_for_interrupt();
+}
+
+#endif
diff --git a/firmware/target/hosted/thread-arm.c b/firmware/target/hosted/thread-arm.c
deleted file mode 100644
index 8815f063d7..0000000000
--- a/firmware/target/hosted/thread-arm.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2005 by Thom Johansen
- * Copyright (C) 2010 by Thomas Martitz (Android-suitable core_sleep())
- *
- * Generic ARM threading support
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-#include <system.h>
-
-/*---------------------------------------------------------------------------
- * Start the thread running and terminate it if it returns
- *---------------------------------------------------------------------------
- */
-static void __attribute__((naked)) USED_ATTR start_thread(void)
-{
- /* r0 = context */
- asm volatile (
- "ldr sp, [r0, #32] \n" /* Load initial sp */
- "ldr r4, [r0, #40] \n" /* start in r4 since it's non-volatile */
- "mov r1, #0 \n" /* Mark thread as running */
- "str r1, [r0, #40] \n"
- "mov lr, pc \n" /* Call thread function */
- "bx r4 \n"
- ); /* No clobber list - new thread doesn't care */
- thread_exit();
-}
-
-/* For startup, place context pointer in r4 slot, start_thread pointer in r5
- * slot, and thread function pointer in context.start. See load_context for
- * what happens when thread is initially going to run. */
-#define THREAD_STARTUP_INIT(core, thread, function) \
- ({ (thread)->context.r[0] = (uint32_t)&(thread)->context, \
- (thread)->context.r[1] = (uint32_t)start_thread, \
- (thread)->context.start = (uint32_t)function; })
-
-
-/*---------------------------------------------------------------------------
- * Store non-volatile context.
- *---------------------------------------------------------------------------
- */
-static inline void store_context(void* addr)
-{
- asm volatile(
- "stmia %0, { r4-r11, sp, lr } \n"
- : : "r" (addr)
- );
-}
-
-/*---------------------------------------------------------------------------
- * Load non-volatile context.
- *---------------------------------------------------------------------------
- */
-static inline void load_context(const void* addr)
-{
- asm volatile(
- "ldr r0, [%0, #40] \n" /* Load start pointer */
- "cmp r0, #0 \n" /* Check for NULL */
-
- /* If not already running, jump to start */
- "ldmneia %0, { r0, pc } \n"
- "ldmia %0, { r4-r11, sp, lr } \n" /* Load regs r4 to r14 from context */
- : : "r" (addr) : "r0" /* only! */
- );
-}
-
-/*
- * this core sleep suspends the OS thread rockbox runs under, which greatly
- * reduces cpu usage (~100% to <10%)
- *
- * it returns when when the tick timer is called, other interrupt-like
- * events occur
- *
- * wait_for_interrupt is implemented in kernel-<platform>.c
- **/
-
-static inline void core_sleep(void)
-{
- enable_irq();
- wait_for_interrupt();
-}
-
-
diff --git a/firmware/target/hosted/thread-unix.c b/firmware/target/hosted/thread-unix.c
deleted file mode 100644
index 79310e0600..0000000000
--- a/firmware/target/hosted/thread-unix.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2011 by Thomas Martitz
- *
- * Generic unix threading support
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-#include <stdlib.h>
-#include <stdbool.h>
-#include <signal.h>
-#include <stdio.h>
-#include <setjmp.h>
-#include <unistd.h>
-#include <pthread.h>
-#include <errno.h>
-#include "debug.h"
-
-static volatile bool sig_handler_called;
-static volatile jmp_buf tramp_buf;
-static volatile jmp_buf bootstrap_buf;
-static void (*thread_func)(void);
-static const int trampoline_sig = SIGUSR1;
-static pthread_t main_thread;
-
-static struct ctx {
- jmp_buf thread_buf;
-} thread_bufs[MAXTHREADS];
-static struct ctx* thread_context, *target_context;
-static int curr_uc;
-
-static void trampoline(int sig);
-static void bootstrap_context(void) __attribute__((noinline));
-
-/* The *_context functions are heavily based on Gnu pth
- * http://www.gnu.org/software/pth/
- *
- * adjusted to work in a multi-thread environment to
- * offer a ucontext-like API
- */
-
-/*
- * VARIANT 2: THE SIGNAL STACK TRICK
- *
- * This uses sigstack/sigaltstack() and friends and is really the
- * most tricky part of Pth. When you understand the following
- * stuff you're a good Unix hacker and then you've already
- * understood the gory ingredients of Pth. So, either welcome to
- * the club of hackers, or do yourself a favor and skip this ;)
- *
- * The ingenious fact is that this variant runs really on _all_ POSIX
- * compliant systems without special platform kludges. But be _VERY_
- * carefully when you change something in the following code. The slightest
- * change or reordering can lead to horribly broken code. Really every
- * function call in the following case is intended to be how it is, doubt
- * me...
- *
- * For more details we strongly recommend you to read the companion
- * paper ``Portable Multithreading -- The Signal Stack Trick for
- * User-Space Thread Creation'' from Ralf S. Engelschall. A copy of the
- * draft of this paper you can find in the file rse-pmt.ps inside the
- * GNU Pth distribution.
- */
-
-static int make_context(struct ctx *ctx, void (*f)(void), char *sp, size_t stack_size)
-{
- struct sigaction sa;
- struct sigaction osa;
- stack_t ss;
- stack_t oss;
- sigset_t osigs;
- sigset_t sigs;
-
- disable_irq();
- /*
- * Preserve the trampoline_sig signal state, block trampoline_sig,
- * and establish our signal handler. The signal will
- * later transfer control onto the signal stack.
- */
- sigemptyset(&sigs);
- sigaddset(&sigs, trampoline_sig);
- sigprocmask(SIG_BLOCK, &sigs, &osigs);
- sa.sa_handler = trampoline;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_ONSTACK;
- if (sigaction(trampoline_sig, &sa, &osa) != 0)
- {
- DEBUGF("%s(): %s\n", __func__, strerror(errno));
- return false;
- }
- /*
- * Set the new stack.
- *
- * For sigaltstack we're lucky [from sigaltstack(2) on
- * FreeBSD 3.1]: ``Signal stacks are automatically adjusted
- * for the direction of stack growth and alignment
- * requirements''
- *
- * For sigstack we have to decide ourself [from sigstack(2)
- * on Solaris 2.6]: ``The direction of stack growth is not
- * indicated in the historical definition of struct sigstack.
- * The only way to portably establish a stack pointer is for
- * the application to determine stack growth direction.''
- */
- ss.ss_sp = sp;
- ss.ss_size = stack_size;
- ss.ss_flags = 0;
- if (sigaltstack(&ss, &oss) < 0)
- {
- DEBUGF("%s(): %s\n", __func__, strerror(errno));
- return false;
- }
-
- /*
- * Now transfer control onto the signal stack and set it up.
- * It will return immediately via "return" after the setjmp()
- * was performed. Be careful here with race conditions. The
- * signal can be delivered the first time sigsuspend() is
- * called.
- */
- sig_handler_called = false;
- main_thread = pthread_self();
- sigfillset(&sigs);
- sigdelset(&sigs, trampoline_sig);
- pthread_kill(main_thread, trampoline_sig);
- while(!sig_handler_called)
- sigsuspend(&sigs);
-
- /*
- * Inform the system that we are back off the signal stack by
- * removing the alternative signal stack. Be careful here: It
- * first has to be disabled, before it can be removed.
- */
- sigaltstack(NULL, &ss);
- ss.ss_flags = SS_DISABLE;
- if (sigaltstack(&ss, NULL) < 0)
- {
- DEBUGF("%s(): %s\n", __func__, strerror(errno));
- return false;
- }
- sigaltstack(NULL, &ss);
- if (!(ss.ss_flags & SS_DISABLE))
- {
- DEBUGF("%s(): %s\n", __func__, strerror(errno));
- return false;
- }
- if (!(oss.ss_flags & SS_DISABLE))
- sigaltstack(&oss, NULL);
-
- /*
- * Restore the old trampoline_sig signal handler and mask
- */
- sigaction(trampoline_sig, &osa, NULL);
- sigprocmask(SIG_SETMASK, &osigs, NULL);
-
- /*
- * Tell the trampoline and bootstrap function where to dump
- * the new machine context, and what to do afterwards...
- */
- thread_func = f;
- thread_context = ctx;
-
- /*
- * Now enter the trampoline again, but this time not as a signal
- * handler. Instead we jump into it directly. The functionally
- * redundant ping-pong pointer arithmentic is neccessary to avoid
- * type-conversion warnings related to the `volatile' qualifier and
- * the fact that `jmp_buf' usually is an array type.
- */
- if (setjmp(*((jmp_buf *)&bootstrap_buf)) == 0)
- longjmp(*((jmp_buf *)&tramp_buf), 1);
-
- /*
- * Ok, we returned again, so now we're finished
- */
- enable_irq();
- return true;
-}
-
-static void trampoline(int sig)
-{
- (void)sig;
- /* sanity check, no other thread should be here */
- if (pthread_self() != main_thread)
- return;
-
- if (setjmp(*((jmp_buf *)&tramp_buf)) == 0)
- {
- sig_handler_called = true;
- return;
- }
- /* longjump'd back in */
- bootstrap_context();
-}
-
-void bootstrap_context(void)
-{
- /* copy to local storage so we can spawn further threads
- * in the meantime */
- void (*thread_entry)(void) = thread_func;
- struct ctx *t = thread_context;
-
- /*
- * Save current machine state (on new stack) and
- * go back to caller until we're scheduled for real...
- */
- if (setjmp(t->thread_buf) == 0)
- longjmp(*((jmp_buf *)&bootstrap_buf), 1);
-
- /*
- * The new thread is now running: GREAT!
- * Now we just invoke its init function....
- */
- thread_entry();
- DEBUGF("thread left\n");
- thread_exit();
-}
-
-static inline void set_context(struct ctx *c)
-{
- longjmp(c->thread_buf, 1);
-}
-
-static inline void swap_context(struct ctx *old, struct ctx *new)
-{
- if (setjmp(old->thread_buf) == 0)
- longjmp(new->thread_buf, 1);
-}
-
-static inline void get_context(struct ctx *c)
-{
- setjmp(c->thread_buf);
-}
-
-
-static void setup_thread(struct regs *context);
-
-#define INIT_MAIN_THREAD
-static void init_main_thread(void *addr)
-{
- /* get a context for the main thread so that we can jump to it from
- * other threads */
- struct regs *context = (struct regs*)addr;
- context->uc = &thread_bufs[curr_uc++];
- get_context(context->uc);
-}
-
-#define THREAD_STARTUP_INIT(core, thread, function) \
- ({ (thread)->context.stack_size = (thread)->stack_size, \
- (thread)->context.stack = (uintptr_t)(thread)->stack; \
- (thread)->context.start = function; })
-
-
-
-/*
- * Prepare context to make the thread runnable by calling swapcontext on it
- */
-static void setup_thread(struct regs *context)
-{
- void (*fn)(void) = context->start;
- context->uc = &thread_bufs[curr_uc++];
- while (!make_context(context->uc, fn, (char*)context->stack, context->stack_size))
- DEBUGF("Thread creation failed. Retrying");
-}
-
-
-/*
- * Save the ucontext_t pointer for later use in swapcontext()
- *
- * Cannot do getcontext() here, because jumping back to the context
- * resumes after the getcontext call (i.e. store_context), but we need
- * to resume from load_context()
- */
-static inline void store_context(void* addr)
-{
- struct regs *r = (struct regs*)addr;
- target_context = r->uc;
-}
-
-/*
- * Perform context switch
- */
-static inline void load_context(const void* addr)
-{
- struct regs *r = (struct regs*)addr;
- if (UNLIKELY(r->start))
- {
- setup_thread(r);
- r->start = NULL;
- }
- swap_context(target_context, r->uc);
-}
-
-/*
- * play nice with the host and sleep while waiting for the tick */
-extern void wait_for_interrupt(void);
-static inline void core_sleep(void)
-{
- enable_irq();
- wait_for_interrupt();
-}
diff --git a/firmware/target/hosted/thread-win32.c b/firmware/target/hosted/thread-win32.c
deleted file mode 100644
index a60198494a..0000000000
--- a/firmware/target/hosted/thread-win32.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2010 by Thomas Martitz
- *
- * Generic ARM threading support
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-
-#include <windows.h>
-#include "system.h"
-
-#define INIT_MAIN_THREAD
-
-#define THREAD_STARTUP_INIT(core, thread, function) \
- ({ (thread)->context.stack_size = (thread)->stack_size, \
- (thread)->context.stack = (uintptr_t)(thread)->stack; \
- (thread)->context.start = function; })
-
-static void init_main_thread(void *addr)
-{
- struct regs *context = (struct regs*)addr;
- /* we must convert the current main thread to a fiber to be able to
- * schedule other fibers */
- context->uc = ConvertThreadToFiber(NULL);
- context->stack_size = 0;
-}
-
-static inline void store_context(void* addr)
-{
- (void)addr;
- /* nothing to do here, Fibers continue after the SwitchToFiber call */
-}
-
-static void start_thread(void)
-{
- void (*func)(void) = GetFiberData();
- func();
- /* go out if thread function returns */
- thread_exit();
-}
-
-/*
- * Load context and run it
- *
- * Resume execution from the last load_context call for the thread
- */
-
-static inline void load_context(const void* addr)
-{
- struct regs *context = (struct regs*)addr;
- if (UNLIKELY(context->start))
- { /* need setup before switching to it */
- context->uc = CreateFiber(context->stack_size,
- (LPFIBER_START_ROUTINE)start_thread, context->start);
- /* can't assign stack pointer, only stack size */
- context->stack_size = 0;
- context->start = NULL;
- }
- SwitchToFiber(context->uc);
-}
-
-/*
- * play nice with the host and sleep while waiting for the tick */
-static inline void core_sleep(void)
-{
- enable_irq();
- wait_for_interrupt();
-}
-
diff --git a/firmware/target/hosted/ypr0/system-target.h b/firmware/target/hosted/ypr0/system-target.h
index efd235282e..1ef8b9aeda 100644
--- a/firmware/target/hosted/ypr0/system-target.h
+++ b/firmware/target/hosted/ypr0/system-target.h
@@ -22,10 +22,7 @@
#define __SYSTEM_TARGET_H__
#include "kernel-unix.h"
-
-static inline void commit_dcache(void) {}
-static inline void commit_discard_dcache(void) {}
-static inline void commit_discard_idcache(void) {}
+#include "system-hosted.h"
#define NEED_GENERIC_BYTESWAPS
#endif /* __SYSTEM_TARGET_H__ */
diff --git a/firmware/target/mips/ingenic_jz47xx/system-target.h b/firmware/target/mips/ingenic_jz47xx/system-target.h
index caf1733158..1c2e7d7173 100644
--- a/firmware/target/mips/ingenic_jz47xx/system-target.h
+++ b/firmware/target/mips/ingenic_jz47xx/system-target.h
@@ -97,4 +97,28 @@ void dma_disable(void);
#define DMA_IRQ(n) (IRQ_DMA_0 + (n))
#define GPIO_IRQ(n) (IRQ_GPIO_0 + (n))
+/*---------------------------------------------------------------------------
+ * Put core in a power-saving state.
+ *---------------------------------------------------------------------------
+ */
+static inline void core_sleep(void)
+{
+#if CONFIG_CPU == JZ4732
+ __cpm_idle_mode();
+#endif
+ asm volatile(".set mips32r2 \n"
+ "mfc0 $8, $12 \n" /* mfc t0, $12 */
+ "move $9, $8 \n" /* move t1, t0 */
+ "la $10, 0x8000000 \n" /* la t2, 0x8000000 */
+ "or $8, $8, $10 \n" /* Enable reduced power mode */
+ "mtc0 $8, $12 \n" /* mtc t0, $12 */
+ "wait \n"
+ "mtc0 $9, $12 \n" /* mtc t1, $12 */
+ ".set mips0 \n"
+ ::: "t0", "t1", "t2"
+ );
+ enable_irq();
+}
+
+
#endif /* __SYSTEM_TARGET_H_ */
diff --git a/firmware/target/mips/thread-mips32.c b/firmware/target/mips/thread-mips32.c
deleted file mode 100644
index ba90c8965b..0000000000
--- a/firmware/target/mips/thread-mips32.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2008 by Maurus Cuelenaere
- *
- * 32-bit MIPS threading support
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-/*---------------------------------------------------------------------------
- * Start the thread running and terminate it if it returns
- *---------------------------------------------------------------------------
- */
-
-void start_thread(void); /* Provide C access to ASM label */
-static void USED_ATTR _start_thread(void)
-{
- /* t1 = context */
- asm volatile (
- "start_thread: \n"
- ".set noreorder \n"
- ".set noat \n"
- "lw $8, 4($9) \n" /* Fetch thread function pointer ($8 = t0, $9 = t1) */
- "lw $29, 36($9) \n" /* Set initial sp(=$29) */
- "jalr $8 \n" /* Start the thread */
- "sw $0, 44($9) \n" /* Clear start address */
- ".set at \n"
- ".set reorder \n"
- );
- thread_exit();
-}
-
-/* Place context pointer in s0 slot, function pointer in s1 slot, and
- * start_thread pointer in context_start */
-#define THREAD_STARTUP_INIT(core, thread, function) \
- ({ (thread)->context.r[0] = (uint32_t)&(thread)->context, \
- (thread)->context.r[1] = (uint32_t)(function), \
- (thread)->context.start = (uint32_t)start_thread; })
-
-/*---------------------------------------------------------------------------
- * Store non-volatile context.
- *---------------------------------------------------------------------------
- */
-static inline void store_context(void* addr)
-{
- asm volatile (
- ".set noreorder \n"
- ".set noat \n"
- "sw $16, 0(%0) \n" /* s0 */
- "sw $17, 4(%0) \n" /* s1 */
- "sw $18, 8(%0) \n" /* s2 */
- "sw $19, 12(%0) \n" /* s3 */
- "sw $20, 16(%0) \n" /* s4 */
- "sw $21, 20(%0) \n" /* s5 */
- "sw $22, 24(%0) \n" /* s6 */
- "sw $23, 28(%0) \n" /* s7 */
- "sw $30, 32(%0) \n" /* fp */
- "sw $29, 36(%0) \n" /* sp */
- "sw $31, 40(%0) \n" /* ra */
- ".set at \n"
- ".set reorder \n"
- : : "r" (addr)
- );
-}
-
-/*---------------------------------------------------------------------------
- * Load non-volatile context.
- *---------------------------------------------------------------------------
- */
-static inline void load_context(const void* addr)
-{
- asm volatile (
- ".set noat \n"
- ".set noreorder \n"
- "lw $8, 44(%0) \n" /* Get start address ($8 = t0) */
- "beqz $8, running \n" /* NULL -> already running */
- "nop \n"
- "jr $8 \n"
- "move $9, %0 \n" /* t1 = context */
- "running: \n"
- "lw $16, 0(%0) \n" /* s0 */
- "lw $17, 4(%0) \n" /* s1 */
- "lw $18, 8(%0) \n" /* s2 */
- "lw $19, 12(%0) \n" /* s3 */
- "lw $20, 16(%0) \n" /* s4 */
- "lw $21, 20(%0) \n" /* s5 */
- "lw $22, 24(%0) \n" /* s6 */
- "lw $23, 28(%0) \n" /* s7 */
- "lw $30, 32(%0) \n" /* fp */
- "lw $29, 36(%0) \n" /* sp */
- "lw $31, 40(%0) \n" /* ra */
- ".set at \n"
- ".set reorder \n"
- : : "r" (addr) : "t0", "t1"
- );
-}
-
-/*---------------------------------------------------------------------------
- * Put core in a power-saving state.
- *---------------------------------------------------------------------------
- */
-static inline void core_sleep(void)
-{
-#if CONFIG_CPU == JZ4732
- __cpm_idle_mode();
-#endif
- asm volatile(".set mips32r2 \n"
- "mfc0 $8, $12 \n" /* mfc t0, $12 */
- "move $9, $8 \n" /* move t1, t0 */
- "la $10, 0x8000000 \n" /* la t2, 0x8000000 */
- "or $8, $8, $10 \n" /* Enable reduced power mode */
- "mtc0 $8, $12 \n" /* mtc t0, $12 */
- "wait \n"
- "mtc0 $9, $12 \n" /* mtc t1, $12 */
- ".set mips0 \n"
- ::: "t0", "t1", "t2"
- );
- enable_irq();
-}
diff --git a/firmware/target/sh/system-target.h b/firmware/target/sh/system-target.h
index 5db9cc071f..a62a024823 100644
--- a/firmware/target/sh/system-target.h
+++ b/firmware/target/sh/system-target.h
@@ -137,4 +137,18 @@ static inline void commit_dcache(void) {}
static inline void commit_discard_dcache(void) {}
static inline void commit_discard_idcache(void) {}
+/*---------------------------------------------------------------------------
+ * Put core in a power-saving state.
+ *---------------------------------------------------------------------------
+ */
+static inline void core_sleep(void)
+{
+ asm volatile (
+ "and.b #0x7f, @(r0, gbr) \n" /* Clear SBY (bit 7) in SBYCR */
+ "mov #0, r1 \n" /* Enable interrupts */
+ "ldc r1, sr \n" /* Following instruction cannot be interrupted */
+ "sleep \n" /* Execute standby */
+ : : "z"(&SBYCR-GBR) : "r1");
+}
+
#endif /* SYSTEM_TARGET_H */
diff --git a/firmware/target/sh/thread-sh.c b/firmware/target/sh/thread-sh.c
deleted file mode 100644
index 0f844f204b..0000000000
--- a/firmware/target/sh/thread-sh.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2002 by Ulf Ralberg
- *
- * SH processor threading support
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-/*---------------------------------------------------------------------------
- * Start the thread running and terminate it if it returns
- *---------------------------------------------------------------------------
- */
-void start_thread(void); /* Provide C access to ASM label */
-static void USED_ATTR __start_thread(void)
-{
- /* r8 = context */
- asm volatile (
- "_start_thread: \n" /* Start here - no naked attribute */
- "mov.l @(4, r8), r0 \n" /* Fetch thread function pointer */
- "mov.l @(28, r8), r15 \n" /* Set initial sp */
- "mov #0, r1 \n" /* Start the thread */
- "jsr @r0 \n"
- "mov.l r1, @(36, r8) \n" /* Clear start address */
- );
- thread_exit();
-}
-
-/* Place context pointer in r8 slot, function pointer in r9 slot, and
- * start_thread pointer in context_start */
-#define THREAD_STARTUP_INIT(core, thread, function) \
- ({ (thread)->context.r[0] = (uint32_t)&(thread)->context, \
- (thread)->context.r[1] = (uint32_t)(function), \
- (thread)->context.start = (uint32_t)start_thread; })
-
-/*---------------------------------------------------------------------------
- * Store non-volatile context.
- *---------------------------------------------------------------------------
- */
-static inline void store_context(void* addr)
-{
- asm volatile (
- "add #36, %0 \n" /* Start at last reg. By the time routine */
- "sts.l pr, @-%0 \n" /* is done, %0 will have the original value */
- "mov.l r15,@-%0 \n"
- "mov.l r14,@-%0 \n"
- "mov.l r13,@-%0 \n"
- "mov.l r12,@-%0 \n"
- "mov.l r11,@-%0 \n"
- "mov.l r10,@-%0 \n"
- "mov.l r9, @-%0 \n"
- "mov.l r8, @-%0 \n"
- : : "r" (addr)
- );
-}
-
-/*---------------------------------------------------------------------------
- * Load non-volatile context.
- *---------------------------------------------------------------------------
- */
-static inline void load_context(const void* addr)
-{
- asm volatile (
- "mov.l @(36, %0), r0 \n" /* Get start address */
- "tst r0, r0 \n"
- "bt .running \n" /* NULL -> already running */
- "jmp @r0 \n" /* r8 = context */
- ".running: \n"
- "mov.l @%0+, r8 \n" /* Executes in delay slot and outside it */
- "mov.l @%0+, r9 \n"
- "mov.l @%0+, r10 \n"
- "mov.l @%0+, r11 \n"
- "mov.l @%0+, r12 \n"
- "mov.l @%0+, r13 \n"
- "mov.l @%0+, r14 \n"
- "mov.l @%0+, r15 \n"
- "lds.l @%0+, pr \n"
- : : "r" (addr) : "r0" /* only! */
- );
-}
-
-/*---------------------------------------------------------------------------
- * Put core in a power-saving state.
- *---------------------------------------------------------------------------
- */
-static inline void core_sleep(void)
-{
- asm volatile (
- "and.b #0x7f, @(r0, gbr) \n" /* Clear SBY (bit 7) in SBYCR */
- "mov #0, r1 \n" /* Enable interrupts */
- "ldc r1, sr \n" /* Following instruction cannot be interrupted */
- "sleep \n" /* Execute standby */
- : : "z"(&SBYCR-GBR) : "r1");
-}
-