mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-13 18:17:39 -04:00
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
This commit is contained in:
parent
cad99bae1d
commit
2f99e609f9
18 changed files with 51 additions and 709 deletions
|
@ -26,7 +26,6 @@
|
||||||
#include "string-extra.h"
|
#include "string-extra.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "system.h"
|
|
||||||
#include "lcd.h"
|
#include "lcd.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "filefuncs.h"
|
#include "filefuncs.h"
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "system.h"
|
||||||
#include "screen_access.h"
|
#include "screen_access.h"
|
||||||
|
|
||||||
extern const unsigned char * const byte_units[];
|
extern const unsigned char * const byte_units[];
|
||||||
|
|
|
@ -23,13 +23,13 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "system.h"
|
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "radio.h"
|
#include "radio.h"
|
||||||
#include "buffering.h"
|
#include "buffering.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
#include "string-extra.h"
|
#include "string-extra.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "filefuncs.h"
|
#include "filefuncs.h"
|
||||||
|
|
||||||
#define MAX_RADIOART_IMAGES 10
|
#define MAX_RADIOART_IMAGES 10
|
||||||
|
|
|
@ -37,11 +37,7 @@ target/hosted/sdl/lcd-remote-bitmap.c
|
||||||
#endif
|
#endif
|
||||||
target/hosted/sdl/lcd-sdl.c
|
target/hosted/sdl/lcd-sdl.c
|
||||||
target/hosted/sdl/system-sdl.c
|
target/hosted/sdl/system-sdl.c
|
||||||
#ifdef HAVE_SDL_THREADS
|
|
||||||
target/hosted/sdl/thread-sdl.c
|
target/hosted/sdl/thread-sdl.c
|
||||||
#else
|
|
||||||
thread.c
|
|
||||||
#endif
|
|
||||||
target/hosted/sdl/timer-sdl.c
|
target/hosted/sdl/timer-sdl.c
|
||||||
#ifdef HAVE_TOUCHSCREEN
|
#ifdef HAVE_TOUCHSCREEN
|
||||||
target/hosted/sdl/key_to_touch-sdl.c
|
target/hosted/sdl/key_to_touch-sdl.c
|
||||||
|
|
|
@ -717,9 +717,7 @@ Lyre prototype 1 */
|
||||||
#define HAVE_WAKEUP_EXT_CB
|
#define HAVE_WAKEUP_EXT_CB
|
||||||
|
|
||||||
|
|
||||||
#if defined(ASSEMBLER_THREADS) \
|
#if (CONFIG_PLATFORM & PLATFORM_ANDROID)
|
||||||
|| defined(HAVE_WIN32_FIBER_THREADS) \
|
|
||||||
|| defined(HAVE_SIGALTSTACK_THREADS)
|
|
||||||
#define HAVE_PRIORITY_SCHEDULING
|
#define HAVE_PRIORITY_SCHEDULING
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -84,19 +84,15 @@
|
||||||
* We need more stack when we run under a host
|
* We need more stack when we run under a host
|
||||||
* maybe more expensive C lib functions?
|
* maybe more expensive C lib functions?
|
||||||
*
|
*
|
||||||
* simulator (possibly) doesn't simulate stack usage anyway but well ... */
|
* simulator doesn't simulate stack usage anyway but well ... */
|
||||||
#ifdef HAVE_SIGALTSTACK_THREADS
|
#if ((CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(SIMULATOR))
|
||||||
#include <signal.h>
|
|
||||||
/* 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 */
|
|
||||||
#define DEFAULT_STACK_SIZE 0x400 /* Bytes */
|
#define DEFAULT_STACK_SIZE 0x400 /* Bytes */
|
||||||
|
#else
|
||||||
|
#define DEFAULT_STACK_SIZE 0x1000 /* Bytes */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if defined(ASSEMBLER_THREADS)
|
#if (CONFIG_PLATFORM & (PLATFORM_NATIVE|PLATFORM_ANDROID))
|
||||||
/* Need to keep structures inside the header file because debug_menu
|
/* Need to keep structures inside the header file because debug_menu
|
||||||
* needs them. */
|
* needs them. */
|
||||||
#ifdef CPU_COLDFIRE
|
#ifdef CPU_COLDFIRE
|
||||||
|
@ -116,7 +112,7 @@ struct regs
|
||||||
uint32_t pr; /* 32 - Procedure register */
|
uint32_t pr; /* 32 - Procedure register */
|
||||||
uint32_t start; /* 36 - Thread start address, or NULL when started */
|
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
|
struct regs
|
||||||
{
|
{
|
||||||
uint32_t r[8]; /* 0-28 - Registers r4-r11 */
|
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 */
|
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 CPU_PP
|
||||||
#ifdef HAVE_CORELOCK_OBJECT
|
#ifdef HAVE_CORELOCK_OBJECT
|
||||||
/* No reliable atomic instruction available - use Peterson's algorithm */
|
/* 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);
|
void corelock_unlock(struct corelock *cl);
|
||||||
#endif /* HAVE_CORELOCK_OBJECT */
|
#endif /* HAVE_CORELOCK_OBJECT */
|
||||||
#endif /* CPU_PP */
|
#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
|
/* 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
|
threads being maintained that are normally dealt with in FIFO order
|
||||||
|
@ -267,7 +251,7 @@ struct thread_entry
|
||||||
object where thread is blocked - used
|
object where thread is blocked - used
|
||||||
for implicit unblock and explicit wake
|
for implicit unblock and explicit wake
|
||||||
states: STATE_BLOCKED/STATE_BLOCKED_W_TMO */
|
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 -
|
struct corelock *obj_cl; /* Object corelock where thead is blocked -
|
||||||
states: STATE_BLOCKED/STATE_BLOCKED_W_TMO */
|
states: STATE_BLOCKED/STATE_BLOCKED_W_TMO */
|
||||||
struct corelock waiter_cl; /* Corelock for thread_wait */
|
struct corelock waiter_cl; /* Corelock for thread_wait */
|
||||||
|
@ -324,7 +308,7 @@ struct thread_entry
|
||||||
/* Specify current thread in a function taking an ID. */
|
/* Specify current thread in a function taking an ID. */
|
||||||
#define THREAD_ID_CURRENT ((unsigned int)-1)
|
#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
|
/* Operations to be performed just before stopping a thread and starting
|
||||||
a new one if specified before calling switch_thread */
|
a new one if specified before calling switch_thread */
|
||||||
enum
|
enum
|
||||||
|
@ -357,7 +341,7 @@ struct core_entry
|
||||||
threads */
|
threads */
|
||||||
#endif
|
#endif
|
||||||
long next_tmo_check; /* soonest time to check tmo threads */
|
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
|
struct thread_blk_ops blk_ops; /* operations to perform when
|
||||||
blocking a thread */
|
blocking a thread */
|
||||||
struct corelock rtr_cl; /* Lock for rtr list */
|
struct corelock rtr_cl; /* Lock for rtr list */
|
||||||
|
|
|
@ -68,9 +68,7 @@ void (*tick_funcs[MAX_NUM_TICK_TASKS+1])(void);
|
||||||
static struct
|
static struct
|
||||||
{
|
{
|
||||||
struct event_queue *queues[MAX_NUM_QUEUES+1];
|
struct event_queue *queues[MAX_NUM_QUEUES+1];
|
||||||
#ifdef HAVE_CORELOCK_OBJECT
|
IF_COP( struct corelock cl; )
|
||||||
struct corelock cl;
|
|
||||||
#endif
|
|
||||||
} all_queues SHAREDBSS_ATTR;
|
} all_queues SHAREDBSS_ATTR;
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
#include "button.h"
|
#include "button.h"
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
#include "backlight.h"
|
#include "backlight.h"
|
||||||
#include "system.h"
|
#include "misc.h"
|
||||||
#include "button-sdl.h"
|
#include "button-sdl.h"
|
||||||
#include "backlight.h"
|
#include "backlight.h"
|
||||||
#include "sim_tasks.h"
|
#include "sim_tasks.h"
|
||||||
|
|
|
@ -34,14 +34,6 @@
|
||||||
static SDL_TimerID tick_timer_id;
|
static SDL_TimerID tick_timer_id;
|
||||||
long start_tick;
|
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 */
|
/* Condition to signal that "interrupts" may proceed */
|
||||||
static SDL_cond *sim_thread_cond;
|
static SDL_cond *sim_thread_cond;
|
||||||
/* Mutex to serialize changing levels and exclude other threads while
|
/* Mutex to serialize changing levels and exclude other threads while
|
||||||
|
@ -106,9 +98,6 @@ void sim_exit_irq_handler(void)
|
||||||
|
|
||||||
status_reg = 0;
|
status_reg = 0;
|
||||||
SDL_UnlockMutex(sim_irq_mtx);
|
SDL_UnlockMutex(sim_irq_mtx);
|
||||||
#ifndef HAVE_SDL_THREADS
|
|
||||||
SDL_CondSignal(wfi_cond);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool sim_kernel_init(void)
|
static bool sim_kernel_init(void)
|
||||||
|
@ -126,33 +115,15 @@ static bool sim_kernel_init(void)
|
||||||
panicf("Cannot create sim_thread_cond\n");
|
panicf("Cannot create sim_thread_cond\n");
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sim_kernel_shutdown(void)
|
void sim_kernel_shutdown(void)
|
||||||
{
|
{
|
||||||
SDL_RemoveTimer(tick_timer_id);
|
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_DestroyMutex(sim_irq_mtx);
|
||||||
SDL_DestroyCond(sim_thread_cond);
|
SDL_DestroyCond(sim_thread_cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
Uint32 tick_timer(Uint32 interval, void *param)
|
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);
|
new_tick = (SDL_GetTicks() - start_tick) / (1000/HZ);
|
||||||
|
|
||||||
while(new_tick != current_tick && !do_exit)
|
while(new_tick != current_tick)
|
||||||
{
|
{
|
||||||
sim_enter_irq_handler();
|
sim_enter_irq_handler();
|
||||||
|
|
||||||
|
@ -175,7 +146,7 @@ Uint32 tick_timer(Uint32 interval, void *param)
|
||||||
sim_exit_irq_handler();
|
sim_exit_irq_handler();
|
||||||
}
|
}
|
||||||
|
|
||||||
return do_exit ? 0 : interval;
|
return interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tick_start(unsigned int interval_in_ms)
|
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);
|
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
|
|
||||||
|
|
|
@ -184,9 +184,7 @@ static int sdl_event_thread(void * param)
|
||||||
|
|
||||||
/* Order here is relevent to prevent deadlocks and use of destroyed
|
/* Order here is relevent to prevent deadlocks and use of destroyed
|
||||||
sync primitives by kernel threads */
|
sync primitives by kernel threads */
|
||||||
#ifdef HAVE_SDL_THREADS
|
sim_thread_shutdown();
|
||||||
sim_thread_shutdown(); /* not needed for native threads */
|
|
||||||
#endif
|
|
||||||
sim_kernel_shutdown();
|
sim_kernel_shutdown();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -201,13 +199,9 @@ void sim_do_exit(void)
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t *stackbegin;
|
|
||||||
uintptr_t *stackend;
|
|
||||||
void system_init(void)
|
void system_init(void)
|
||||||
{
|
{
|
||||||
SDL_sem *s;
|
SDL_sem *s;
|
||||||
/* fake stack, OS manages size (and growth) */
|
|
||||||
stackbegin = stackend = (uintptr_t*)&s;
|
|
||||||
|
|
||||||
#if (CONFIG_PLATFORM & PLATFORM_MAEMO)
|
#if (CONFIG_PLATFORM & PLATFORM_MAEMO)
|
||||||
/* Make glib thread safe */
|
/* 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
|
/* wait for sdl_event_thread to run so that it can initialize the surfaces
|
||||||
* and video subsystem needed for SDL events */
|
* and video subsystem needed for SDL events */
|
||||||
SDL_SemWait(s);
|
SDL_SemWait(s);
|
||||||
|
|
||||||
/* cleanup */
|
/* cleanup */
|
||||||
SDL_DestroySemaphore(s);
|
SDL_DestroySemaphore(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void system_exception_wait(void)
|
||||||
|
{
|
||||||
|
sim_thread_exception_wait();
|
||||||
|
}
|
||||||
|
|
||||||
void system_reboot(void)
|
void system_reboot(void)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_SDL_THREADS
|
|
||||||
sim_thread_exception_wait();
|
sim_thread_exception_wait();
|
||||||
#else
|
|
||||||
sim_do_exit();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void system_exception_wait(void)
|
|
||||||
{
|
|
||||||
system_reboot();
|
|
||||||
}
|
|
||||||
|
|
||||||
void sys_handle_argv(int argc, char *argv[])
|
void sys_handle_argv(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
|
|
@ -46,9 +46,6 @@ void sys_poweroff(void);
|
||||||
void sys_handle_argv(int argc, char *argv[]);
|
void sys_handle_argv(int argc, char *argv[]);
|
||||||
void gui_message_loop(void);
|
void gui_message_loop(void);
|
||||||
void sim_do_exit(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 background; /* True if the background image is enabled */
|
||||||
extern bool showremote;
|
extern bool showremote;
|
||||||
|
|
|
@ -22,13 +22,11 @@
|
||||||
#ifndef __THREADSDL_H__
|
#ifndef __THREADSDL_H__
|
||||||
#define __THREADSDL_H__
|
#define __THREADSDL_H__
|
||||||
|
|
||||||
#ifdef HAVE_SDL_THREADS
|
|
||||||
/* extra thread functions that only apply when running on hosting platforms */
|
/* extra thread functions that only apply when running on hosting platforms */
|
||||||
void sim_thread_lock(void *me);
|
void sim_thread_lock(void *me);
|
||||||
void * sim_thread_unlock(void);
|
void * sim_thread_unlock(void);
|
||||||
void sim_thread_exception_wait(void);
|
void sim_thread_exception_wait(void);
|
||||||
void sim_thread_shutdown(void); /* Shut down all kernel threads gracefully */
|
void sim_thread_shutdown(void); /* Shut down all kernel threads gracefully */
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* #ifndef __THREADSDL_H__ */
|
#endif /* #ifndef __THREADSDL_H__ */
|
||||||
|
|
||||||
|
|
|
@ -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 <system.h>
|
|
||||||
/*---------------------------------------------------------------------------
|
|
||||||
* 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-<platform>.c
|
|
||||||
**/
|
|
||||||
|
|
||||||
static inline void core_sleep(void)
|
|
||||||
{
|
|
||||||
enable_irq();
|
|
||||||
wait_for_interrupt();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,294 +0,0 @@
|
||||||
#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();
|
|
||||||
}
|
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
|
@ -174,13 +174,10 @@ void switch_thread(void)
|
||||||
__attribute__((noinline));
|
__attribute__((noinline));
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Processor/OS-specific section - include necessary core support
|
* Processor-specific section - include necessary core support
|
||||||
*/
|
*/
|
||||||
|
#if defined(ANDROID)
|
||||||
#if defined(HAVE_WIN32_FIBER_THREADS)
|
#include "thread-android-arm.c"
|
||||||
#include "thread-win32.c"
|
|
||||||
#elif defined(HAVE_SIGALTSTACK_THREADS)
|
|
||||||
#include "thread-unix.c"
|
|
||||||
#elif defined(CPU_ARM)
|
#elif defined(CPU_ARM)
|
||||||
#include "thread-arm.c"
|
#include "thread-arm.c"
|
||||||
#if defined (CPU_PP)
|
#if defined (CPU_PP)
|
||||||
|
@ -967,7 +964,7 @@ void check_tmo_threads(void)
|
||||||
* life again. */
|
* life again. */
|
||||||
if (state == STATE_BLOCKED_W_TMO)
|
if (state == STATE_BLOCKED_W_TMO)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_CORELOCK_OBJECT
|
#if NUM_CORES > 1
|
||||||
/* Lock the waiting thread's kernel object */
|
/* Lock the waiting thread's kernel object */
|
||||||
struct corelock *ocl = curr->obj_cl;
|
struct corelock *ocl = curr->obj_cl;
|
||||||
|
|
||||||
|
@ -1782,7 +1779,7 @@ void thread_exit(void)
|
||||||
*/
|
*/
|
||||||
void remove_thread(unsigned int thread_id)
|
void remove_thread(unsigned int thread_id)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_CORELOCK_OBJECT
|
#if NUM_CORES > 1
|
||||||
/* core is not constant here because of core switching */
|
/* core is not constant here because of core switching */
|
||||||
unsigned int core = CURRENT_CORE;
|
unsigned int core = CURRENT_CORE;
|
||||||
unsigned int old_core = NUM_CORES;
|
unsigned int old_core = NUM_CORES;
|
||||||
|
@ -2311,9 +2308,6 @@ void init_threads(void)
|
||||||
thread_exit();
|
thread_exit();
|
||||||
#endif /* NUM_CORES */
|
#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 */
|
/* 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";
|
const char *fmt = "%s";
|
||||||
if (name == NULL IF_COP(|| name == THREAD_DESTRUCT) || *name == '\0')
|
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";
|
fmt = "%04lX";
|
||||||
}
|
}
|
||||||
snprintf(buffer, size, fmt, name);
|
snprintf(buffer, size, fmt, name);
|
||||||
|
|
82
tools/configure
vendored
82
tools/configure
vendored
|
@ -25,7 +25,6 @@ bindir=
|
||||||
libdir=
|
libdir=
|
||||||
sharedir=
|
sharedir=
|
||||||
|
|
||||||
thread_support="ASSEMBLER_THREADS"
|
|
||||||
app_modelname=
|
app_modelname=
|
||||||
app_lcd_width=
|
app_lcd_width=
|
||||||
app_lcd_height=
|
app_lcd_height=
|
||||||
|
@ -164,41 +163,6 @@ findsdl(){
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
# check for availability of sigaltstack to support our thread engine
|
|
||||||
check_sigaltstack() {
|
|
||||||
cat >$tmpdir/check_threads.c <<EOF
|
|
||||||
#include <signal.h>
|
|
||||||
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 <<EOF
|
|
||||||
#include <windows.h>
|
|
||||||
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 () {
|
simcc () {
|
||||||
|
|
||||||
# default tool setup for native building
|
# default tool setup for native building
|
||||||
|
@ -211,8 +175,6 @@ simcc () {
|
||||||
GCCOPTS="$GCCOPTS -fno-builtin -g"
|
GCCOPTS="$GCCOPTS -fno-builtin -g"
|
||||||
GCCOPTIMIZE=''
|
GCCOPTIMIZE=''
|
||||||
LDOPTS='-lm' # button-sdl.c uses sqrt()
|
LDOPTS='-lm' # button-sdl.c uses sqrt()
|
||||||
sigaltstack=""
|
|
||||||
fibers=""
|
|
||||||
|
|
||||||
# default output binary name, don't override app_get_platform()
|
# default output binary name, don't override app_get_platform()
|
||||||
if [ "$app_type" != "sdl-app" ]; then
|
if [ "$app_type" != "sdl-app" ]; then
|
||||||
|
@ -231,7 +193,6 @@ simcc () {
|
||||||
CYGWIN*)
|
CYGWIN*)
|
||||||
echo "Cygwin host detected"
|
echo "Cygwin host detected"
|
||||||
|
|
||||||
fibers=`check_fiber`
|
|
||||||
LDOPTS="$LDOPTS -mconsole"
|
LDOPTS="$LDOPTS -mconsole"
|
||||||
output="$output.exe"
|
output="$output.exe"
|
||||||
winbuild="yes"
|
winbuild="yes"
|
||||||
|
@ -240,33 +201,29 @@ simcc () {
|
||||||
MINGW*)
|
MINGW*)
|
||||||
echo "MinGW host detected"
|
echo "MinGW host detected"
|
||||||
|
|
||||||
fibers=`check_fiber`
|
|
||||||
LDOPTS="$LDOPTS -mconsole"
|
LDOPTS="$LDOPTS -mconsole"
|
||||||
output="$output.exe"
|
output="$output.exe"
|
||||||
winbuild="yes"
|
winbuild="yes"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
Linux)
|
Linux)
|
||||||
sigaltstack=`check_sigaltstack`
|
|
||||||
echo "Linux host detected"
|
echo "Linux host detected"
|
||||||
LDOPTS="$LDOPTS -ldl"
|
LDOPTS="$LDOPTS -ldl"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
FreeBSD)
|
FreeBSD)
|
||||||
sigaltstack=`check_sigaltstack`
|
|
||||||
echo "FreeBSD host detected"
|
echo "FreeBSD host detected"
|
||||||
LDOPTS="$LDOPTS -ldl"
|
LDOPTS="$LDOPTS -ldl"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
Darwin)
|
Darwin)
|
||||||
sigaltstack=`check_sigaltstack`
|
|
||||||
echo "Darwin host detected"
|
echo "Darwin host detected"
|
||||||
LDOPTS="$LDOPTS -ldl"
|
LDOPTS="$LDOPTS -ldl"
|
||||||
|
|
||||||
SHARED_FLAG="-dynamiclib -Wl\,-single_module"
|
SHARED_FLAG="-dynamiclib -Wl\,-single_module"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
SunOS)
|
SunOS)
|
||||||
sigaltstack=`check_sigaltstack`
|
|
||||||
echo "*Solaris host detected"
|
echo "*Solaris host detected"
|
||||||
|
|
||||||
GCCOPTS="$GCCOPTS -fPIC"
|
GCCOPTS="$GCCOPTS -fPIC"
|
||||||
|
@ -362,34 +319,11 @@ EOF
|
||||||
# add cross-compiler option(s)
|
# add cross-compiler option(s)
|
||||||
prefixtools i586-mingw32msvc-
|
prefixtools i586-mingw32msvc-
|
||||||
LDOPTS="$LDOPTS -mconsole"
|
LDOPTS="$LDOPTS -mconsole"
|
||||||
fibers=`check_fiber`
|
|
||||||
output="rockboxui.exe"
|
output="rockboxui.exe"
|
||||||
endian="little" # windows is little endian
|
endian="little" # windows is little endian
|
||||||
echo "Enabling MMX support"
|
echo "Enabling MMX support"
|
||||||
GCCOPTS="$GCCOPTS -mmmx"
|
GCCOPTS="$GCCOPTS -mmmx"
|
||||||
fi
|
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"
|
GLOBAL_LDOPTS="$GLOBAL_LDOPTS -Wl,-z,defs"
|
||||||
SHARED_FLAG="-shared"
|
SHARED_FLAG="-shared"
|
||||||
endian="little"
|
endian="little"
|
||||||
thread_support="HAVE_SIGALTSTACK_THREADS"
|
|
||||||
|
|
||||||
is_n900=0
|
is_n900=0
|
||||||
# Determine maemo version
|
# Determine maemo version
|
||||||
|
@ -1061,11 +994,6 @@ help() {
|
||||||
--thumb Build with -mthumb (for ARM builds)
|
--thumb Build with -mthumb (for ARM builds)
|
||||||
--no-thumb The opposite of --thumb (don't use thumb even for targets
|
--no-thumb The opposite of --thumb (don't use thumb even for targets
|
||||||
where this is the default
|
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
|
--prefix Target installation directory
|
||||||
--help Shows this message (must not be used with other options)
|
--help Shows this message (must not be used with other options)
|
||||||
|
|
||||||
|
@ -1087,7 +1015,6 @@ ARG_VOICE=
|
||||||
ARG_ARM_EABI=
|
ARG_ARM_EABI=
|
||||||
ARG_ARM_THUMB=
|
ARG_ARM_THUMB=
|
||||||
ARG_PREFIX="$PREFIX"
|
ARG_PREFIX="$PREFIX"
|
||||||
ARG_THREAD_SUPPORT=
|
|
||||||
err=
|
err=
|
||||||
for arg in "$@"; do
|
for arg in "$@"; do
|
||||||
case "$arg" in
|
case "$arg" in
|
||||||
|
@ -1108,9 +1035,6 @@ for arg in "$@"; do
|
||||||
--no-eabi) ARG_ARM_EABI=0;;
|
--no-eabi) ARG_ARM_EABI=0;;
|
||||||
--thumb) ARG_ARM_THUMB=1;;
|
--thumb) ARG_ARM_THUMB=1;;
|
||||||
--no-thumb) ARG_ARM_THUMB=0;;
|
--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`;;
|
--prefix=*) ARG_PREFIX=`echo "$arg" | cut -d = -f 2`;;
|
||||||
--help) help;;
|
--help) help;;
|
||||||
*) err=1; echo "[ERROR] Option '$arg' unsupported";;
|
*) err=1; echo "[ERROR] Option '$arg' unsupported";;
|
||||||
|
@ -3402,7 +3326,6 @@ sed > autoconf.h \
|
||||||
-e "s<^#undef DO_BOOTCHART<$use_bootchart<g" \
|
-e "s<^#undef DO_BOOTCHART<$use_bootchart<g" \
|
||||||
-e "s<@config_rtc@<$config_rtc<g" \
|
-e "s<@config_rtc@<$config_rtc<g" \
|
||||||
-e "s<@have_rtc_alarm@<$have_rtc_alarm<g" \
|
-e "s<@have_rtc_alarm@<$have_rtc_alarm<g" \
|
||||||
-e "s<@thread_support@<$thread_support<g" \
|
|
||||||
-e "s<@RBDIR@<${rbdir}<g" \
|
-e "s<@RBDIR@<${rbdir}<g" \
|
||||||
-e "s<@sharepath@<${sharedir}<g" \
|
-e "s<@sharepath@<${sharedir}<g" \
|
||||||
-e "s<@binpath@<${bindir}<g" \
|
-e "s<@binpath@<${bindir}<g" \
|
||||||
|
@ -3439,9 +3362,6 @@ sed > autoconf.h \
|
||||||
@config_rtc@
|
@config_rtc@
|
||||||
@have_rtc_alarm@
|
@have_rtc_alarm@
|
||||||
|
|
||||||
/* the threading backend we use */
|
|
||||||
#define @thread_support@
|
|
||||||
|
|
||||||
/* lcd dimensions for application builds from configure */
|
/* lcd dimensions for application builds from configure */
|
||||||
@lcd_width@
|
@lcd_width@
|
||||||
@lcd_height@
|
@lcd_height@
|
||||||
|
|
|
@ -46,12 +46,9 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#ifdef HAVE_SDL_THREADS
|
#include <SDL.h>
|
||||||
|
#include <SDL_thread.h>
|
||||||
#include "thread-sdl.h"
|
#include "thread-sdl.h"
|
||||||
#else
|
|
||||||
#define sim_thread_unlock() NULL
|
|
||||||
#define sim_thread_lock(a)
|
|
||||||
#endif
|
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue