From 2f99e609f9ae5981b3f18de64c75191a5c5645de Mon Sep 17 00:00:00 2001 From: Alex Parker Date: Sun, 20 Feb 2011 20:26:42 +0000 Subject: [PATCH] Revert r29327 - "Implement cooperative threads on hosted platforms using C code" on the release branch. Thanks to kugel for the patch. git-svn-id: svn://svn.rockbox.org/rockbox/branches/v3_8@29364 a1c6a512-1295-4272-9138-f99709370657 --- apps/misc.c | 1 - apps/misc.h | 1 + apps/radio/radioart.c | 2 +- firmware/SOURCES | 4 - firmware/export/config.h | 4 +- firmware/export/thread.h | 70 +++--- firmware/kernel.c | 4 +- firmware/target/hosted/sdl/button-sdl.c | 2 +- firmware/target/hosted/sdl/kernel-sdl.c | 62 +---- firmware/target/hosted/sdl/system-sdl.c | 21 +- firmware/target/hosted/sdl/system-sdl.h | 3 - firmware/target/hosted/sdl/thread-sdl.h | 2 - firmware/target/hosted/thread-arm.c | 98 -------- firmware/target/hosted/thread-unix.c | 294 ------------------------ firmware/target/hosted/thread-win32.c | 85 ------- firmware/thread.c | 18 +- tools/configure | 82 +------ uisimulator/common/io.c | 7 +- 18 files changed, 51 insertions(+), 709 deletions(-) delete mode 100644 firmware/target/hosted/thread-arm.c delete mode 100644 firmware/target/hosted/thread-unix.c delete mode 100644 firmware/target/hosted/thread-win32.c diff --git a/apps/misc.c b/apps/misc.c index fa34c21f4e..17490ecea8 100644 --- a/apps/misc.c +++ b/apps/misc.c @@ -26,7 +26,6 @@ #include "string-extra.h" #include "config.h" #include "misc.h" -#include "system.h" #include "lcd.h" #include "file.h" #include "filefuncs.h" diff --git a/apps/misc.h b/apps/misc.h index 1022af4e93..fa66956800 100644 --- a/apps/misc.h +++ b/apps/misc.h @@ -24,6 +24,7 @@ #include #include #include "config.h" +#include "system.h" #include "screen_access.h" extern const unsigned char * const byte_units[]; diff --git a/apps/radio/radioart.c b/apps/radio/radioart.c index 23fb7a33d5..85397c16b6 100644 --- a/apps/radio/radioart.c +++ b/apps/radio/radioart.c @@ -23,13 +23,13 @@ #include #include #include -#include "system.h" #include "settings.h" #include "radio.h" #include "buffering.h" #include "file.h" #include "kernel.h" #include "string-extra.h" +#include "misc.h" #include "filefuncs.h" #define MAX_RADIOART_IMAGES 10 diff --git a/firmware/SOURCES b/firmware/SOURCES index b2b353bda2..9c9ebf53fc 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -37,11 +37,7 @@ target/hosted/sdl/lcd-remote-bitmap.c #endif target/hosted/sdl/lcd-sdl.c target/hosted/sdl/system-sdl.c -#ifdef HAVE_SDL_THREADS target/hosted/sdl/thread-sdl.c -#else -thread.c -#endif target/hosted/sdl/timer-sdl.c #ifdef HAVE_TOUCHSCREEN target/hosted/sdl/key_to_touch-sdl.c diff --git a/firmware/export/config.h b/firmware/export/config.h index a870e5d815..3063e1f06d 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h @@ -717,9 +717,7 @@ Lyre prototype 1 */ #define HAVE_WAKEUP_EXT_CB -#if defined(ASSEMBLER_THREADS) \ - || defined(HAVE_WIN32_FIBER_THREADS) \ - || defined(HAVE_SIGALTSTACK_THREADS) +#if (CONFIG_PLATFORM & PLATFORM_ANDROID) #define HAVE_PRIORITY_SCHEDULING #endif diff --git a/firmware/export/thread.h b/firmware/export/thread.h index 179979a98a..3cce78444c 100644 --- a/firmware/export/thread.h +++ b/firmware/export/thread.h @@ -84,19 +84,15 @@ * We need more stack when we run under a host * maybe more expensive C lib functions? * - * simulator (possibly) doesn't simulate stack usage anyway but well ... */ -#ifdef HAVE_SIGALTSTACK_THREADS -#include -/* MINSIGSTKSZ for the OS to deliver the signal + 0x3000 for us */ -#define DEFAULT_STACK_SIZE (MINSIGSTKSZ+0x3000) /* Bytes */ -#elif (CONFIG_PLATFORM & PLATFORM_ANDROID) || defined(HAVE_WIN32_FIBER_THREADS) -#define DEFAULT_STACK_SIZE 0x1000 /* Bytes */ -#else /* native threads, sdl threads */ + * simulator doesn't simulate stack usage anyway but well ... */ +#if ((CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(SIMULATOR)) #define DEFAULT_STACK_SIZE 0x400 /* Bytes */ +#else +#define DEFAULT_STACK_SIZE 0x1000 /* Bytes */ #endif -#if defined(ASSEMBLER_THREADS) +#if (CONFIG_PLATFORM & (PLATFORM_NATIVE|PLATFORM_ANDROID)) /* Need to keep structures inside the header file because debug_menu * needs them. */ #ifdef CPU_COLDFIRE @@ -116,7 +112,7 @@ struct regs uint32_t pr; /* 32 - Procedure register */ uint32_t start; /* 36 - Thread start address, or NULL when started */ }; -#elif defined(CPU_ARM) +#elif defined(CPU_ARM) || (CONFIG_PLATFORM & PLATFORM_ANDROID) struct regs { uint32_t r[8]; /* 0-28 - Registers r4-r11 */ @@ -125,36 +121,6 @@ struct regs uint32_t start; /* 40 - Thread start address, or NULL when started */ }; -#elif defined(CPU_MIPS) -struct regs -{ - uint32_t r[9]; /* 0-32 - Registers s0-s7, fp */ - uint32_t sp; /* 36 - Stack pointer */ - uint32_t ra; /* 40 - Return address */ - uint32_t start; /* 44 - Thread start address, or NULL when started */ -}; -#endif /* CONFIG_CPU */ -#elif (CONFIG_PLATFORM & PLATFORM_HOSTED) || defined(__PCTOOL__) -#ifndef HAVE_SDL_THREADS -struct regs -{ - void (*start)(void); /* thread's entry point, or NULL when started */ - void* uc; /* host thread handle */ - uintptr_t sp; /* Stack pointer, unused */ - size_t stack_size; /* stack size, not always used */ - uintptr_t stack; /* pointer to start of the stack buffer */ -}; -#else /* SDL threads */ -struct regs -{ - void *t; /* OS thread */ - void *told; /* Last thread in slot (explained in thead-sdl.c) */ - void *s; /* Semaphore for blocking and wakeup */ - void (*start)(void); /* Start function */ -}; -#endif -#endif /* PLATFORM_NATIVE */ - #ifdef CPU_PP #ifdef HAVE_CORELOCK_OBJECT /* No reliable atomic instruction available - use Peterson's algorithm */ @@ -171,6 +137,24 @@ int corelock_try_lock(struct corelock *cl); void corelock_unlock(struct corelock *cl); #endif /* HAVE_CORELOCK_OBJECT */ #endif /* CPU_PP */ +#elif defined(CPU_MIPS) +struct regs +{ + uint32_t r[9]; /* 0-32 - Registers s0-s7, fp */ + uint32_t sp; /* 36 - Stack pointer */ + uint32_t ra; /* 40 - Return address */ + uint32_t start; /* 44 - Thread start address, or NULL when started */ +}; +#endif /* CONFIG_CPU */ +#elif (CONFIG_PLATFORM & PLATFORM_HOSTED) +struct regs +{ + void *t; /* OS thread */ + void *told; /* Last thread in slot (explained in thead-sdl.c) */ + void *s; /* Semaphore for blocking and wakeup */ + void (*start)(void); /* Start function */ +}; +#endif /* PLATFORM_NATIVE */ /* NOTE: The use of the word "queue" may also refer to a linked list of threads being maintained that are normally dealt with in FIFO order @@ -267,7 +251,7 @@ struct thread_entry object where thread is blocked - used for implicit unblock and explicit wake states: STATE_BLOCKED/STATE_BLOCKED_W_TMO */ -#ifdef HAVE_CORELOCK_OBJECT +#if NUM_CORES > 1 struct corelock *obj_cl; /* Object corelock where thead is blocked - states: STATE_BLOCKED/STATE_BLOCKED_W_TMO */ struct corelock waiter_cl; /* Corelock for thread_wait */ @@ -324,7 +308,7 @@ struct thread_entry /* Specify current thread in a function taking an ID. */ #define THREAD_ID_CURRENT ((unsigned int)-1) -#ifdef HAVE_CORELOCK_OBJECT +#if NUM_CORES > 1 /* Operations to be performed just before stopping a thread and starting a new one if specified before calling switch_thread */ enum @@ -357,7 +341,7 @@ struct core_entry threads */ #endif long next_tmo_check; /* soonest time to check tmo threads */ -#ifdef HAVE_CORELOCK_OBJECT +#if NUM_CORES > 1 struct thread_blk_ops blk_ops; /* operations to perform when blocking a thread */ struct corelock rtr_cl; /* Lock for rtr list */ diff --git a/firmware/kernel.c b/firmware/kernel.c index 588bbd2a75..ee42574055 100644 --- a/firmware/kernel.c +++ b/firmware/kernel.c @@ -68,9 +68,7 @@ void (*tick_funcs[MAX_NUM_TICK_TASKS+1])(void); static struct { struct event_queue *queues[MAX_NUM_QUEUES+1]; -#ifdef HAVE_CORELOCK_OBJECT - struct corelock cl; -#endif + IF_COP( struct corelock cl; ) } all_queues SHAREDBSS_ATTR; /**************************************************************************** diff --git a/firmware/target/hosted/sdl/button-sdl.c b/firmware/target/hosted/sdl/button-sdl.c index 9f1c1f7519..7abe2ae1a1 100644 --- a/firmware/target/hosted/sdl/button-sdl.c +++ b/firmware/target/hosted/sdl/button-sdl.c @@ -28,7 +28,7 @@ #include "button.h" #include "kernel.h" #include "backlight.h" -#include "system.h" +#include "misc.h" #include "button-sdl.h" #include "backlight.h" #include "sim_tasks.h" diff --git a/firmware/target/hosted/sdl/kernel-sdl.c b/firmware/target/hosted/sdl/kernel-sdl.c index 4fb1aede0a..d933b9097e 100644 --- a/firmware/target/hosted/sdl/kernel-sdl.c +++ b/firmware/target/hosted/sdl/kernel-sdl.c @@ -34,14 +34,6 @@ static SDL_TimerID tick_timer_id; long start_tick; -#ifndef HAVE_SDL_THREADS -/* for the wait_for_interrupt function */ -static bool do_exit; -static SDL_cond *wfi_cond; -static SDL_mutex *wfi_mutex; -#else -#define do_exit false -#endif /* Condition to signal that "interrupts" may proceed */ static SDL_cond *sim_thread_cond; /* Mutex to serialize changing levels and exclude other threads while @@ -106,9 +98,6 @@ void sim_exit_irq_handler(void) status_reg = 0; SDL_UnlockMutex(sim_irq_mtx); -#ifndef HAVE_SDL_THREADS - SDL_CondSignal(wfi_cond); -#endif } static bool sim_kernel_init(void) @@ -126,33 +115,15 @@ static bool sim_kernel_init(void) panicf("Cannot create sim_thread_cond\n"); return false; } -#ifndef HAVE_SDL_THREADS - wfi_cond = SDL_CreateCond(); - if (wfi_cond == NULL) - { - panicf("Cannot create wfi\n"); - return false; - } - wfi_mutex = SDL_CreateMutex(); - if (wfi_mutex == NULL) - { - panicf("Cannot create wfi mutex\n"); - return false; - } -#endif + return true; } void sim_kernel_shutdown(void) { SDL_RemoveTimer(tick_timer_id); -#ifndef HAVE_SDL_THREADS - do_exit = true; - SDL_CondSignal(wfi_cond); -#endif - disable_irq(); SDL_DestroyMutex(sim_irq_mtx); - SDL_DestroyCond(sim_thread_cond); + SDL_DestroyCond(sim_thread_cond); } Uint32 tick_timer(Uint32 interval, void *param) @@ -164,7 +135,7 @@ Uint32 tick_timer(Uint32 interval, void *param) new_tick = (SDL_GetTicks() - start_tick) / (1000/HZ); - while(new_tick != current_tick && !do_exit) + while(new_tick != current_tick) { sim_enter_irq_handler(); @@ -175,7 +146,7 @@ Uint32 tick_timer(Uint32 interval, void *param) sim_exit_irq_handler(); } - return do_exit ? 0 : interval; + return interval; } void tick_start(unsigned int interval_in_ms) @@ -197,29 +168,4 @@ void tick_start(unsigned int interval_in_ms) } tick_timer_id = SDL_AddTimer(interval_in_ms, tick_timer, NULL); -#ifndef HAVE_SDL_THREADS - SDL_LockMutex(wfi_mutex); -#endif } - -#ifndef HAVE_SDL_THREADS -static void check_exit(void) -{ - if (UNLIKELY(do_exit)) - { - SDL_DestroyCond(wfi_cond); - SDL_UnlockMutex(wfi_mutex); - SDL_DestroyMutex(wfi_mutex); - sim_do_exit(); - } -} - -void wait_for_interrupt(void) -{ - /* the exit may come at any time, during the CondWait or before, - * so check it twice */ - check_exit(); - SDL_CondWait(wfi_cond, wfi_mutex); - check_exit(); -} -#endif diff --git a/firmware/target/hosted/sdl/system-sdl.c b/firmware/target/hosted/sdl/system-sdl.c index 1cc9b2c919..9ea25c1014 100644 --- a/firmware/target/hosted/sdl/system-sdl.c +++ b/firmware/target/hosted/sdl/system-sdl.c @@ -184,9 +184,7 @@ static int sdl_event_thread(void * param) /* Order here is relevent to prevent deadlocks and use of destroyed sync primitives by kernel threads */ -#ifdef HAVE_SDL_THREADS - sim_thread_shutdown(); /* not needed for native threads */ -#endif + sim_thread_shutdown(); sim_kernel_shutdown(); return 0; @@ -201,13 +199,9 @@ void sim_do_exit(void) exit(EXIT_SUCCESS); } -uintptr_t *stackbegin; -uintptr_t *stackend; void system_init(void) { SDL_sem *s; - /* fake stack, OS manages size (and growth) */ - stackbegin = stackend = (uintptr_t*)&s; #if (CONFIG_PLATFORM & PLATFORM_MAEMO) /* Make glib thread safe */ @@ -225,24 +219,21 @@ void system_init(void) /* wait for sdl_event_thread to run so that it can initialize the surfaces * and video subsystem needed for SDL events */ SDL_SemWait(s); + /* cleanup */ SDL_DestroySemaphore(s); } +void system_exception_wait(void) +{ + sim_thread_exception_wait(); +} void system_reboot(void) { -#ifdef HAVE_SDL_THREADS sim_thread_exception_wait(); -#else - sim_do_exit(); -#endif } -void system_exception_wait(void) -{ - system_reboot(); -} void sys_handle_argv(int argc, char *argv[]) { diff --git a/firmware/target/hosted/sdl/system-sdl.h b/firmware/target/hosted/sdl/system-sdl.h index bec01ec81d..01952e50a0 100644 --- a/firmware/target/hosted/sdl/system-sdl.h +++ b/firmware/target/hosted/sdl/system-sdl.h @@ -46,9 +46,6 @@ void sys_poweroff(void); void sys_handle_argv(int argc, char *argv[]); void gui_message_loop(void); void sim_do_exit(void); -#ifndef HAVE_SDL_THREADS -void wait_for_interrupt(void); -#endif extern bool background; /* True if the background image is enabled */ extern bool showremote; diff --git a/firmware/target/hosted/sdl/thread-sdl.h b/firmware/target/hosted/sdl/thread-sdl.h index 9edb3ee74e..9384e6060d 100644 --- a/firmware/target/hosted/sdl/thread-sdl.h +++ b/firmware/target/hosted/sdl/thread-sdl.h @@ -22,13 +22,11 @@ #ifndef __THREADSDL_H__ #define __THREADSDL_H__ -#ifdef HAVE_SDL_THREADS /* extra thread functions that only apply when running on hosting platforms */ void sim_thread_lock(void *me); void * sim_thread_unlock(void); void sim_thread_exception_wait(void); void sim_thread_shutdown(void); /* Shut down all kernel threads gracefully */ -#endif #endif /* #ifndef __THREADSDL_H__ */ diff --git a/firmware/target/hosted/thread-arm.c b/firmware/target/hosted/thread-arm.c deleted file mode 100644 index d2fa7d1e5d..0000000000 --- a/firmware/target/hosted/thread-arm.c +++ /dev/null @@ -1,98 +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 -/*--------------------------------------------------------------------------- - * Start the thread running and terminate it if it returns - *--------------------------------------------------------------------------- - */ -static void __attribute__((naked,used)) 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-.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 a84ac70d56..0000000000 --- a/firmware/target/hosted/thread-unix.c +++ /dev/null @@ -1,294 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#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 -#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/thread.c b/firmware/thread.c index ea73150853..b71bc1749c 100644 --- a/firmware/thread.c +++ b/firmware/thread.c @@ -174,13 +174,10 @@ void switch_thread(void) __attribute__((noinline)); /**************************************************************************** - * Processor/OS-specific section - include necessary core support + * Processor-specific section - include necessary core support */ - -#if defined(HAVE_WIN32_FIBER_THREADS) -#include "thread-win32.c" -#elif defined(HAVE_SIGALTSTACK_THREADS) -#include "thread-unix.c" +#if defined(ANDROID) +#include "thread-android-arm.c" #elif defined(CPU_ARM) #include "thread-arm.c" #if defined (CPU_PP) @@ -967,7 +964,7 @@ void check_tmo_threads(void) * life again. */ if (state == STATE_BLOCKED_W_TMO) { -#ifdef HAVE_CORELOCK_OBJECT +#if NUM_CORES > 1 /* Lock the waiting thread's kernel object */ struct corelock *ocl = curr->obj_cl; @@ -1782,7 +1779,7 @@ void thread_exit(void) */ void remove_thread(unsigned int thread_id) { -#ifdef HAVE_CORELOCK_OBJECT +#if NUM_CORES > 1 /* core is not constant here because of core switching */ unsigned int core = CURRENT_CORE; unsigned int old_core = NUM_CORES; @@ -2311,9 +2308,6 @@ void init_threads(void) thread_exit(); #endif /* NUM_CORES */ } -#ifdef INIT_MAIN_THREAD - init_main_thread(&thread->context); -#endif } /* Shared stack scan helper for thread_stack_usage and idle_stack_usage */ @@ -2385,7 +2379,7 @@ void thread_get_name(char *buffer, int size, const char *fmt = "%s"; if (name == NULL IF_COP(|| name == THREAD_DESTRUCT) || *name == '\0') { - name = (const char *)(uintptr_t)thread->id; + name = (const char *)(unsigned int)thread->id; fmt = "%04lX"; } snprintf(buffer, size, fmt, name); diff --git a/tools/configure b/tools/configure index 6a060de2fc..bcb7d0a864 100755 --- a/tools/configure +++ b/tools/configure @@ -25,7 +25,6 @@ bindir= libdir= sharedir= -thread_support="ASSEMBLER_THREADS" app_modelname= app_lcd_width= app_lcd_height= @@ -164,41 +163,6 @@ findsdl(){ done } -# check for availability of sigaltstack to support our thread engine -check_sigaltstack() { - cat >$tmpdir/check_threads.c < -int main(int argc, char **argv) -{ -#ifndef NULL - #define NULL (void*)0 -#endif - sigaltstack(NULL, NULL); - return 0; -} -EOF - $CC -o $tmpdir/check_threads $tmpdir/check_threads.c 1> /dev/null - result=$? - rm -rf $tmpdir/check_threads* - echo $result -} - -# check for availability of Fiber on Win32 to support our thread engine -check_fiber() { - cat >$tmpdir/check_threads.c < -int main(int argc, char **argv) -{ - ConvertThreadToFiber(NULL); - return 0; -} -EOF - $CC -o $tmpdir/check_threads $tmpdir/check_threads.c 2>/dev/null - result=$? - rm -rf $tmpdir/check_threads* - echo $result -} - simcc () { # default tool setup for native building @@ -211,8 +175,6 @@ simcc () { GCCOPTS="$GCCOPTS -fno-builtin -g" GCCOPTIMIZE='' LDOPTS='-lm' # button-sdl.c uses sqrt() - sigaltstack="" - fibers="" # default output binary name, don't override app_get_platform() if [ "$app_type" != "sdl-app" ]; then @@ -231,7 +193,6 @@ simcc () { CYGWIN*) echo "Cygwin host detected" - fibers=`check_fiber` LDOPTS="$LDOPTS -mconsole" output="$output.exe" winbuild="yes" @@ -240,33 +201,29 @@ simcc () { MINGW*) echo "MinGW host detected" - fibers=`check_fiber` LDOPTS="$LDOPTS -mconsole" output="$output.exe" winbuild="yes" ;; Linux) - sigaltstack=`check_sigaltstack` echo "Linux host detected" LDOPTS="$LDOPTS -ldl" ;; FreeBSD) - sigaltstack=`check_sigaltstack` echo "FreeBSD host detected" LDOPTS="$LDOPTS -ldl" ;; Darwin) - sigaltstack=`check_sigaltstack` echo "Darwin host detected" LDOPTS="$LDOPTS -ldl" + SHARED_FLAG="-dynamiclib -Wl\,-single_module" ;; SunOS) - sigaltstack=`check_sigaltstack` echo "*Solaris host detected" GCCOPTS="$GCCOPTS -fPIC" @@ -362,34 +319,11 @@ EOF # add cross-compiler option(s) prefixtools i586-mingw32msvc- LDOPTS="$LDOPTS -mconsole" - fibers=`check_fiber` output="rockboxui.exe" endian="little" # windows is little endian echo "Enabling MMX support" GCCOPTS="$GCCOPTS -mmmx" fi - - thread_support= - if [ -z "$ARG_THREAD_SUPPORT" ] || [ "$ARG_THREAD_SUPPORT" = "0" ]; then - if [ "$sigaltstack" = "0" ]; then - thread_support="HAVE_SIGALTSTACK_THREADS" - LDOPTS="$LDOPTS -lpthread" # pthread needed - echo "Selected sigaltstack threads" - elif [ "$fibers" = "0" ]; then - thread_support="HAVE_WIN32_FIBER_THREADS" - echo "Selected Win32 Fiber threads" - fi - fi - - if [ -n `echo $app_type | grep "sdl"` ] && [ -z "$thread_support" ] \ - && [ "$ARG_THREAD_SUPPORT" != "0" ]; then - thread_support="HAVE_SDL_THREADS" - if [ "$ARG_THREAD_SUPPORT" = "1" ]; then - echo "Selected SDL threads" - else - echo "WARNING: Falling back to SDL threads" - fi - fi } # @@ -522,7 +456,6 @@ maemocc () { GLOBAL_LDOPTS="$GLOBAL_LDOPTS -Wl,-z,defs" SHARED_FLAG="-shared" endian="little" - thread_support="HAVE_SIGALTSTACK_THREADS" is_n900=0 # Determine maemo version @@ -1061,11 +994,6 @@ help() { --thumb Build with -mthumb (for ARM builds) --no-thumb The opposite of --thumb (don't use thumb even for targets where this is the default - --sdl-threads Force use of SDL threads. They have inferior performance, - but are better debuggable with GDB - --no-sdl-threads Disallow use of SDL threads. This prevents the default - behavior of falling back to them if no native thread - support was found. --prefix Target installation directory --help Shows this message (must not be used with other options) @@ -1087,7 +1015,6 @@ ARG_VOICE= ARG_ARM_EABI= ARG_ARM_THUMB= ARG_PREFIX="$PREFIX" -ARG_THREAD_SUPPORT= err= for arg in "$@"; do case "$arg" in @@ -1108,9 +1035,6 @@ for arg in "$@"; do --no-eabi) ARG_ARM_EABI=0;; --thumb) ARG_ARM_THUMB=1;; --no-thumb) ARG_ARM_THUMB=0;; - --sdl-threads)ARG_THREAD_SUPPORT=1;; - --no-sdl-threads) - ARG_THREAD_SUPPORT=0;; --prefix=*) ARG_PREFIX=`echo "$arg" | cut -d = -f 2`;; --help) help;; *) err=1; echo "[ERROR] Option '$arg' unsupported";; @@ -3402,7 +3326,6 @@ sed > autoconf.h \ -e "s<^#undef DO_BOOTCHART<$use_bootchart autoconf.h \ @config_rtc@ @have_rtc_alarm@ -/* the threading backend we use */ -#define @thread_support@ - /* lcd dimensions for application builds from configure */ @lcd_width@ @lcd_height@ diff --git a/uisimulator/common/io.c b/uisimulator/common/io.c index 0d680e0e8a..f77180dc21 100644 --- a/uisimulator/common/io.c +++ b/uisimulator/common/io.c @@ -46,12 +46,9 @@ #endif #include -#ifdef HAVE_SDL_THREADS +#include +#include #include "thread-sdl.h" -#else -#define sim_thread_unlock() NULL -#define sim_thread_lock(a) -#endif #include "thread.h" #include "kernel.h" #include "debug.h"