Use cookies for thread identification instead of pointers directly which gives a buffer against wrongly identifying a thread when the slot is recycled (which has been nagging me for awhile). A slot gets 255 uses before it repeats. Everything gets incompatible so a full update is required.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19377 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Michael Sevakis 2008-12-10 08:57:10 +00:00
parent 40ff47c7ee
commit 8cfbd3604f
32 changed files with 329 additions and 234 deletions

View file

@ -184,7 +184,7 @@ enum {
static void buffering_thread(void); static void buffering_thread(void);
static long buffering_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]; static long buffering_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)];
static const char buffering_thread_name[] = "buffering"; static const char buffering_thread_name[] = "buffering";
static struct thread_entry *buffering_thread_p; static unsigned int buffering_thread_id = 0;
static struct event_queue buffering_queue; static struct event_queue buffering_queue;
static struct queue_sender_list buffering_queue_sender_list; static struct queue_sender_list buffering_queue_sender_list;
@ -1468,13 +1468,13 @@ void buffering_init(void)
conf_watermark = BUFFERING_DEFAULT_WATERMARK; conf_watermark = BUFFERING_DEFAULT_WATERMARK;
queue_init(&buffering_queue, true); queue_init(&buffering_queue, true);
buffering_thread_p = create_thread( buffering_thread, buffering_stack, buffering_thread_id = create_thread( buffering_thread, buffering_stack,
sizeof(buffering_stack), CREATE_THREAD_FROZEN, sizeof(buffering_stack), CREATE_THREAD_FROZEN,
buffering_thread_name IF_PRIO(, PRIORITY_BUFFERING) buffering_thread_name IF_PRIO(, PRIORITY_BUFFERING)
IF_COP(, CPU)); IF_COP(, CPU));
queue_enable_queue_send(&buffering_queue, &buffering_queue_sender_list, queue_enable_queue_send(&buffering_queue, &buffering_queue_sender_list,
buffering_thread_p); buffering_thread_id);
} }
/* Initialise the buffering subsystem */ /* Initialise the buffering subsystem */
@ -1501,7 +1501,7 @@ bool buffering_reset(char *buf, size_t buflen)
high_watermark = 3*buflen / 4; high_watermark = 3*buflen / 4;
#endif #endif
thread_thaw(buffering_thread_p); thread_thaw(buffering_thread_id);
return true; return true;
} }

View file

@ -82,12 +82,12 @@
#define CODEC_ENC_MAGIC 0x52454E43 /* RENC */ #define CODEC_ENC_MAGIC 0x52454E43 /* RENC */
/* increase this every time the api struct changes */ /* increase this every time the api struct changes */
#define CODEC_API_VERSION 27 #define CODEC_API_VERSION 28
/* update this to latest version if a change to the api struct breaks /* update this to latest version if a change to the api struct breaks
backwards compatibility (and please take the opportunity to sort in any backwards compatibility (and please take the opportunity to sort in any
new function which are "waiting" at the end of the function table) */ new function which are "waiting" at the end of the function table) */
#define CODEC_MIN_API_VERSION 27 #define CODEC_MIN_API_VERSION 28
/* codec return codes */ /* codec return codes */
enum codec_status { enum codec_status {
@ -164,14 +164,14 @@ struct codec_api {
void (*yield)(void); void (*yield)(void);
#if NUM_CORES > 1 #if NUM_CORES > 1
struct thread_entry * unsigned int
(*create_thread)(void (*function)(void), void* stack, (*create_thread)(void (*function)(void), void* stack,
size_t stack_size, unsigned flags, const char *name size_t stack_size, unsigned flags, const char *name
IF_PRIO(, int priority) IF_PRIO(, int priority)
IF_COP(, unsigned int core)); IF_COP(, unsigned int core));
void (*thread_thaw)(struct thread_entry *thread); void (*thread_thaw)(unsigned int thread_id);
void (*thread_wait)(struct thread_entry *thread); void (*thread_wait)(unsigned int thread_id);
void (*semaphore_init)(struct semaphore *s, int max, int start); void (*semaphore_init)(struct semaphore *s, int max, int start);
void (*semaphore_wait)(struct semaphore *s); void (*semaphore_wait)(struct semaphore *s);
void (*semaphore_release)(struct semaphore *s); void (*semaphore_release)(struct semaphore *s);

View file

@ -200,7 +200,7 @@ static void set_elapsed(struct mp3entry* id3)
static int mad_synth_thread_stack[DEFAULT_STACK_SIZE/sizeof(int)/2] IBSS_ATTR; static int mad_synth_thread_stack[DEFAULT_STACK_SIZE/sizeof(int)/2] IBSS_ATTR;
static const unsigned char * const mad_synth_thread_name = "mp3dec"; static const unsigned char * const mad_synth_thread_name = "mp3dec";
static struct thread_entry *mad_synth_thread_p; static unsigned int mad_synth_thread_id = 0;
static void mad_synth_thread(void) static void mad_synth_thread(void)
@ -249,14 +249,14 @@ static bool mad_synth_thread_create(void)
ci->semaphore_init(&synth_done_sem, 1, 0); ci->semaphore_init(&synth_done_sem, 1, 0);
ci->semaphore_init(&synth_pending_sem, 1, 0); ci->semaphore_init(&synth_pending_sem, 1, 0);
mad_synth_thread_p = ci->create_thread(mad_synth_thread, mad_synth_thread_id = ci->create_thread(mad_synth_thread,
mad_synth_thread_stack, mad_synth_thread_stack,
sizeof(mad_synth_thread_stack), 0, sizeof(mad_synth_thread_stack), 0,
mad_synth_thread_name mad_synth_thread_name
IF_PRIO(, PRIORITY_PLAYBACK) IF_PRIO(, PRIORITY_PLAYBACK)
IF_COP(, COP)); IF_COP(, COP));
if (mad_synth_thread_p == NULL) if (mad_synth_thread_id == 0)
return false; return false;
return true; return true;
@ -267,7 +267,7 @@ static void mad_synth_thread_quit(void)
/*mop up COP thread*/ /*mop up COP thread*/
die=1; die=1;
ci->semaphore_release(&synth_pending_sem); ci->semaphore_release(&synth_pending_sem);
ci->thread_wait(mad_synth_thread_p); ci->thread_wait(mad_synth_thread_id);
invalidate_icache(); invalidate_icache();
} }
#else #else

View file

@ -197,7 +197,7 @@ static int spc_emu_thread_stack[DEFAULT_STACK_SIZE/sizeof(int)]
CACHEALIGN_ATTR; CACHEALIGN_ATTR;
static const unsigned char * const spc_emu_thread_name = "spc emu"; static const unsigned char * const spc_emu_thread_name = "spc emu";
static struct thread_entry *emu_thread_p; static unsigned int emu_thread_id = 0;
enum enum
{ {
@ -352,11 +352,11 @@ static void spc_emu_thread(void)
static bool spc_emu_start(void) static bool spc_emu_start(void)
{ {
emu_thread_p = ci->create_thread(spc_emu_thread, spc_emu_thread_stack, emu_thread_id = ci->create_thread(spc_emu_thread, spc_emu_thread_stack,
sizeof(spc_emu_thread_stack), CREATE_THREAD_FROZEN, sizeof(spc_emu_thread_stack), CREATE_THREAD_FROZEN,
spc_emu_thread_name IF_PRIO(, PRIORITY_PLAYBACK), COP); spc_emu_thread_name IF_PRIO(, PRIORITY_PLAYBACK), COP);
if (emu_thread_p == NULL) if (emu_thread_id == 0)
return false; return false;
/* Initialize audio queue as full to prevent emu thread from trying to run the /* Initialize audio queue as full to prevent emu thread from trying to run the
@ -368,7 +368,7 @@ static bool spc_emu_start(void)
sample_queue.tail = 2; sample_queue.tail = 2;
/* Start it running */ /* Start it running */
ci->thread_thaw(emu_thread_p); ci->thread_thaw(emu_thread_id);
return true; return true;
} }
@ -382,10 +382,10 @@ static inline int load_spc_buffer(uint8_t *buf, size_t size)
static inline void spc_emu_quit(void) static inline void spc_emu_quit(void)
{ {
if (emu_thread_p != NULL) { if (emu_thread_id != 0) {
emu_thread_send_msg(SPC_EMU_QUIT, 0); emu_thread_send_msg(SPC_EMU_QUIT, 0);
/* Wait for emu thread to be killed */ /* Wait for emu thread to be killed */
ci->thread_wait(emu_thread_p); ci->thread_wait(emu_thread_id);
invalidate_icache(); invalidate_icache();
} }
} }

View file

@ -115,7 +115,7 @@ static bool pcmbuf_flush;
static int codec_thread_priority = PRIORITY_PLAYBACK; static int codec_thread_priority = PRIORITY_PLAYBACK;
#endif #endif
extern struct thread_entry *codec_thread_p; extern uintptr_t codec_thread_id;
/* Helpful macros for use in conditionals this assumes some of the above /* Helpful macros for use in conditionals this assumes some of the above
* static variable names */ * static variable names */
@ -258,13 +258,13 @@ static void boost_codec_thread(bool boost)
if (priority != codec_thread_priority) if (priority != codec_thread_priority)
{ {
codec_thread_priority = priority; codec_thread_priority = priority;
thread_set_priority(codec_thread_p, priority); thread_set_priority(codec_thread_id, priority);
voice_thread_set_priority(priority); voice_thread_set_priority(priority);
} }
} }
else if (codec_thread_priority != PRIORITY_PLAYBACK) else if (codec_thread_priority != PRIORITY_PLAYBACK)
{ {
thread_set_priority(codec_thread_p, PRIORITY_PLAYBACK); thread_set_priority(codec_thread_id, PRIORITY_PLAYBACK);
voice_thread_set_priority(PRIORITY_PLAYBACK); voice_thread_set_priority(PRIORITY_PLAYBACK);
codec_thread_priority = PRIORITY_PLAYBACK; codec_thread_priority = PRIORITY_PLAYBACK;
} }
@ -276,7 +276,7 @@ static void pcmbuf_under_watermark(void)
/* Only codec thread initiates boost - voice boosts the cpu when playing /* Only codec thread initiates boost - voice boosts the cpu when playing
a clip */ a clip */
#ifndef SIMULATOR #ifndef SIMULATOR
if (thread_get_current() == codec_thread_p) if (thread_get_current() == codec_thread_id)
#endif /* SIMULATOR */ #endif /* SIMULATOR */
{ {
#ifdef HAVE_PRIORITY_SCHEDULING #ifdef HAVE_PRIORITY_SCHEDULING

View file

@ -299,7 +299,7 @@ static struct queue_sender_list codec_queue_sender_list;
static long codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)] static long codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
IBSS_ATTR; IBSS_ATTR;
static const char codec_thread_name[] = "codec"; static const char codec_thread_name[] = "codec";
struct thread_entry *codec_thread_p; /* For modifying thread priority later. */ unsigned int codec_thread_id; /* For modifying thread priority later. */
/* PCM buffer messaging */ /* PCM buffer messaging */
static struct event_queue pcmbuf_queue SHAREDBSS_ATTR; static struct event_queue pcmbuf_queue SHAREDBSS_ATTR;
@ -2499,7 +2499,7 @@ static void audio_thread(void)
*/ */
void audio_init(void) void audio_init(void)
{ {
struct thread_entry *audio_thread_p; unsigned int audio_thread_id;
/* Can never do this twice */ /* Can never do this twice */
if (audio_is_initialized) if (audio_is_initialized)
@ -2543,22 +2543,22 @@ void audio_init(void)
talk first */ talk first */
talk_init(); talk_init();
codec_thread_p = create_thread( codec_thread_id = create_thread(
codec_thread, codec_stack, sizeof(codec_stack), codec_thread, codec_stack, sizeof(codec_stack),
CREATE_THREAD_FROZEN, CREATE_THREAD_FROZEN,
codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK) codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK)
IF_COP(, CPU)); IF_COP(, CPU));
queue_enable_queue_send(&codec_queue, &codec_queue_sender_list, queue_enable_queue_send(&codec_queue, &codec_queue_sender_list,
codec_thread_p); codec_thread_id);
audio_thread_p = create_thread(audio_thread, audio_stack, audio_thread_id = create_thread(audio_thread, audio_stack,
sizeof(audio_stack), CREATE_THREAD_FROZEN, sizeof(audio_stack), CREATE_THREAD_FROZEN,
audio_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) audio_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE)
IF_COP(, CPU)); IF_COP(, CPU));
queue_enable_queue_send(&audio_queue, &audio_queue_sender_list, queue_enable_queue_send(&audio_queue, &audio_queue_sender_list,
audio_thread_p); audio_thread_id);
#ifdef PLAYBACK_VOICE #ifdef PLAYBACK_VOICE
voice_thread_init(); voice_thread_init();
@ -2599,8 +2599,8 @@ void audio_init(void)
#ifdef PLAYBACK_VOICE #ifdef PLAYBACK_VOICE
voice_thread_resume(); voice_thread_resume();
#endif #endif
thread_thaw(codec_thread_p); thread_thaw(codec_thread_id);
thread_thaw(audio_thread_p); thread_thaw(audio_thread_id);
} /* audio_init */ } /* audio_init */

View file

@ -146,7 +146,8 @@ static const struct plugin_api rockbox_api = {
font_get_width, font_get_width,
screen_clear_area, screen_clear_area,
gui_scrollbar_draw, gui_scrollbar_draw,
#endif #endif /* HAVE_LCD_BITMAP */
get_codepage_name,
backlight_on, backlight_on,
backlight_off, backlight_off,
@ -482,6 +483,7 @@ static const struct plugin_api rockbox_api = {
&statusbars, &statusbars,
gui_syncstatusbar_draw, gui_syncstatusbar_draw,
/* options */ /* options */
get_settings_list,
find_setting, find_setting,
option_screen, option_screen,
set_option, set_option,
@ -619,8 +621,6 @@ static const struct plugin_api rockbox_api = {
appsversion, appsversion,
/* new stuff at the end, sort into place next time /* new stuff at the end, sort into place next time
the API gets incompatible */ the API gets incompatible */
get_settings_list,
get_codepage_name,
}; };
int plugin_load(const char* plugin, const void* parameter) int plugin_load(const char* plugin, const void* parameter)

View file

@ -7,7 +7,7 @@
* \/ \/ \/ \/ \/ * \/ \/ \/ \/ \/
* $Id$ * $Id$
* *
* Copyright (C) 2002 Björn Stenberg * Copyright (C) 2002 Björn Stenberg
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -131,12 +131,12 @@ void* plugin_get_buffer(size_t *buffer_size);
#define PLUGIN_MAGIC 0x526F634B /* RocK */ #define PLUGIN_MAGIC 0x526F634B /* RocK */
/* increase this every time the api struct changes */ /* increase this every time the api struct changes */
#define PLUGIN_API_VERSION 128 #define PLUGIN_API_VERSION 129
/* update this to latest version if a change to the api struct breaks /* update this to latest version if a change to the api struct breaks
backwards compatibility (and please take the opportunity to sort in any backwards compatibility (and please take the opportunity to sort in any
new function which are "waiting" at the end of the function table) */ new function which are "waiting" at the end of the function table) */
#define PLUGIN_MIN_API_VERSION 127 #define PLUGIN_MIN_API_VERSION 129
/* plugin return codes */ /* plugin return codes */
enum plugin_status { enum plugin_status {
@ -244,6 +244,7 @@ struct plugin_api {
int min_shown, int max_shown, int min_shown, int max_shown,
unsigned flags); unsigned flags);
#endif /* HAVE_LCD_BITMAP */ #endif /* HAVE_LCD_BITMAP */
const char* (*get_codepage_name)(int cp);
/* backlight */ /* backlight */
/* The backlight_* functions must be present in the API regardless whether /* The backlight_* functions must be present in the API regardless whether
@ -408,13 +409,13 @@ struct plugin_api {
long (*default_event_handler)(long event); long (*default_event_handler)(long event);
long (*default_event_handler_ex)(long event, void (*callback)(void *), void *parameter); long (*default_event_handler_ex)(long event, void (*callback)(void *), void *parameter);
struct thread_entry* threads; struct thread_entry* threads;
struct thread_entry* (*create_thread)(void (*function)(void), void* stack, unsigned int (*create_thread)(void (*function)(void), void* stack,
size_t stack_size, unsigned flags, size_t stack_size, unsigned flags,
const char *name const char *name
IF_PRIO(, int priority) IF_PRIO(, int priority)
IF_COP(, unsigned int core)); IF_COP(, unsigned int core));
void (*thread_exit)(void); void (*thread_exit)(void);
void (*thread_wait)(struct thread_entry *thread); void (*thread_wait)(unsigned int thread_id);
#if CONFIG_CODEC == SWCODEC #if CONFIG_CODEC == SWCODEC
void (*mutex_init)(struct mutex *m); void (*mutex_init)(struct mutex *m);
void (*mutex_lock)(struct mutex *m); void (*mutex_lock)(struct mutex *m);
@ -456,7 +457,7 @@ struct plugin_api {
#if CONFIG_CODEC == SWCODEC #if CONFIG_CODEC == SWCODEC
void (*queue_enable_queue_send)(struct event_queue *q, void (*queue_enable_queue_send)(struct event_queue *q,
struct queue_sender_list *send, struct queue_sender_list *send,
struct thread_entry *owner); unsigned int thread_id);
bool (*queue_empty)(const struct event_queue *q); bool (*queue_empty)(const struct event_queue *q);
void (*queue_wait)(struct event_queue *q, struct queue_event *ev); void (*queue_wait)(struct event_queue *q, struct queue_event *ev);
intptr_t (*queue_send)(struct event_queue *q, long id, intptr_t (*queue_send)(struct event_queue *q, long id,
@ -616,6 +617,7 @@ struct plugin_api {
void (*gui_syncstatusbar_draw)(struct gui_syncstatusbar * bars, bool force_redraw); void (*gui_syncstatusbar_draw)(struct gui_syncstatusbar * bars, bool force_redraw);
/* options */ /* options */
const struct settings_list* (*get_settings_list)(int*count);
const struct settings_list* (*find_setting)(const void* variable, int *id); const struct settings_list* (*find_setting)(const void* variable, int *id);
bool (*option_screen)(const struct settings_list *setting, bool (*option_screen)(const struct settings_list *setting,
struct viewport parent[NB_SCREENS], struct viewport parent[NB_SCREENS],
@ -771,7 +773,7 @@ struct plugin_api {
char *buf, int buflen); char *buf, int buflen);
#endif #endif
void (*thread_thaw)(struct thread_entry *thread); void (*thread_thaw)(unsigned int thread_id);
#ifdef HAVE_SEMAPHORE_OBJECTS #ifdef HAVE_SEMAPHORE_OBJECTS
void (*semaphore_init)(struct semaphore *s, int max, int start); void (*semaphore_init)(struct semaphore *s, int max, int start);
@ -782,8 +784,6 @@ struct plugin_api {
const char *appsversion; const char *appsversion;
/* new stuff at the end, sort into place next time /* new stuff at the end, sort into place next time
the API gets incompatible */ the API gets incompatible */
const struct settings_list* (*get_settings_list)(int*count);
const char* (*get_codepage_name)(int cp);
}; };
/* plugin header */ /* plugin header */

View file

@ -206,7 +206,7 @@ struct
{ {
bool foreground; /* set as long as we're owning the UI */ bool foreground; /* set as long as we're owning the UI */
bool exiting; /* signal to the thread that we want to exit */ bool exiting; /* signal to the thread that we want to exit */
struct thread_entry *thread; /* worker thread id */ unsigned int thread; /* worker thread id */
} gTread; } gTread;
static const struct plugin_api* rb; /* here is the global API struct pointer */ static const struct plugin_api* rb; /* here is the global API struct pointer */

View file

@ -216,7 +216,7 @@ struct batt_info
#define BUF_ELEMENTS (sizeof(bat)/sizeof(struct batt_info)) #define BUF_ELEMENTS (sizeof(bat)/sizeof(struct batt_info))
static struct thread_entry *thread_id; static unsigned int thread_id;
static struct event_queue thread_q; static struct event_queue thread_q;
static bool in_usb_mode; static bool in_usb_mode;
static unsigned int buf_idx; static unsigned int buf_idx;
@ -537,7 +537,7 @@ int main(void)
if ((thread_id = rb->create_thread(thread, thread_stack, if ((thread_id = rb->create_thread(thread, thread_stack,
sizeof(thread_stack), 0, "Battery Benchmark" sizeof(thread_stack), 0, "Battery Benchmark"
IF_PRIO(, PRIORITY_BACKGROUND) IF_PRIO(, PRIORITY_BACKGROUND)
IF_COP(, CPU))) == NULL) IF_COP(, CPU))) == 0)
{ {
rb->splash(HZ, "Cannot create thread!"); rb->splash(HZ, "Cannot create thread!");
return PLUGIN_ERROR; return PLUGIN_ERROR;

View file

@ -732,7 +732,7 @@ bool audio_thread_init(void)
rb->queue_enable_queue_send(audio_str.hdr.q, &audio_str_queue_send, rb->queue_enable_queue_send(audio_str.hdr.q, &audio_str_queue_send,
audio_str.thread); audio_str.thread);
if (audio_str.thread == NULL) if (audio_str.thread == 0)
return false; return false;
/* Wait for thread to initialize */ /* Wait for thread to initialize */
@ -744,11 +744,11 @@ bool audio_thread_init(void)
/* Stops the audio thread */ /* Stops the audio thread */
void audio_thread_exit(void) void audio_thread_exit(void)
{ {
if (audio_str.thread != NULL) if (audio_str.thread != 0)
{ {
str_post_msg(&audio_str, STREAM_QUIT, 0); str_post_msg(&audio_str, STREAM_QUIT, 0);
rb->thread_wait(audio_str.thread); rb->thread_wait(audio_str.thread);
audio_str.thread = NULL; audio_str.thread = 0;
} }
#ifndef SIMULATOR #ifndef SIMULATOR

View file

@ -835,7 +835,7 @@ void disk_buf_reply_msg(intptr_t retval)
bool disk_buf_init(void) bool disk_buf_init(void)
{ {
disk_buf.thread = NULL; disk_buf.thread = 0;
list_initialize(&nf_list); list_initialize(&nf_list);
rb->mutex_init(&disk_buf_mtx); rb->mutex_init(&disk_buf_mtx);
@ -893,7 +893,7 @@ bool disk_buf_init(void)
rb->queue_enable_queue_send(disk_buf.q, &disk_buf_queue_send, rb->queue_enable_queue_send(disk_buf.q, &disk_buf_queue_send,
disk_buf.thread); disk_buf.thread);
if (disk_buf.thread == NULL) if (disk_buf.thread == 0)
return false; return false;
/* Wait for thread to initialize */ /* Wait for thread to initialize */
@ -904,10 +904,10 @@ bool disk_buf_init(void)
void disk_buf_exit(void) void disk_buf_exit(void)
{ {
if (disk_buf.thread != NULL) if (disk_buf.thread != 0)
{ {
rb->queue_post(disk_buf.q, STREAM_QUIT, 0); rb->queue_post(disk_buf.q, STREAM_QUIT, 0);
rb->thread_wait(disk_buf.thread); rb->thread_wait(disk_buf.thread);
disk_buf.thread = NULL; disk_buf.thread = 0;
} }
} }

View file

@ -62,7 +62,7 @@ struct dbuf_range
* playback events as well as buffering */ * playback events as well as buffering */
struct disk_buf struct disk_buf
{ {
struct thread_entry *thread; unsigned int thread;
struct event_queue *q; struct event_queue *q;
uint8_t *start; /* Start pointer */ uint8_t *start; /* Start pointer */
uint8_t *end; /* End of buffer pointer less MPEG_GUARDBUF_SIZE. The uint8_t *end; /* End of buffer pointer less MPEG_GUARDBUF_SIZE. The

View file

@ -1027,7 +1027,7 @@ intptr_t parser_send_video_msg(long id, intptr_t data)
{ {
intptr_t retval = 0; intptr_t retval = 0;
if (video_str.thread != NULL && disk_buf.in_file >= 0) if (video_str.thread != 0 && disk_buf.in_file >= 0)
{ {
/* Hook certain messages since they involve multiple operations /* Hook certain messages since they involve multiple operations
* behind the scenes */ * behind the scenes */

View file

@ -908,7 +908,7 @@ static void stream_mgr_thread(void)
/* Opens a new file */ /* Opens a new file */
int stream_open(const char *filename) int stream_open(const char *filename)
{ {
if (stream_mgr.thread != NULL) if (stream_mgr.thread != 0)
return stream_mgr_send_msg(STREAM_OPEN, (intptr_t)filename); return stream_mgr_send_msg(STREAM_OPEN, (intptr_t)filename);
return STREAM_ERROR; return STREAM_ERROR;
} }
@ -916,7 +916,7 @@ int stream_open(const char *filename)
/* Plays the current file starting at time 'start' */ /* Plays the current file starting at time 'start' */
int stream_play(void) int stream_play(void)
{ {
if (stream_mgr.thread != NULL) if (stream_mgr.thread != 0)
return stream_mgr_send_msg(STREAM_PLAY, 0); return stream_mgr_send_msg(STREAM_PLAY, 0);
return STREAM_ERROR; return STREAM_ERROR;
} }
@ -924,7 +924,7 @@ int stream_play(void)
/* Pauses playback if playing */ /* Pauses playback if playing */
int stream_pause(void) int stream_pause(void)
{ {
if (stream_mgr.thread != NULL) if (stream_mgr.thread != 0)
return stream_mgr_send_msg(STREAM_PAUSE, false); return stream_mgr_send_msg(STREAM_PAUSE, false);
return STREAM_ERROR; return STREAM_ERROR;
} }
@ -932,7 +932,7 @@ int stream_pause(void)
/* Resumes playback if paused */ /* Resumes playback if paused */
int stream_resume(void) int stream_resume(void)
{ {
if (stream_mgr.thread != NULL) if (stream_mgr.thread != 0)
return stream_mgr_send_msg(STREAM_PAUSE, true); return stream_mgr_send_msg(STREAM_PAUSE, true);
return STREAM_ERROR; return STREAM_ERROR;
} }
@ -940,7 +940,7 @@ int stream_resume(void)
/* Stops playback if not stopped */ /* Stops playback if not stopped */
int stream_stop(void) int stream_stop(void)
{ {
if (stream_mgr.thread != NULL) if (stream_mgr.thread != 0)
return stream_mgr_send_msg(STREAM_STOP, 0); return stream_mgr_send_msg(STREAM_STOP, 0);
return STREAM_ERROR; return STREAM_ERROR;
} }
@ -950,7 +950,7 @@ int stream_seek(uint32_t time, int whence)
{ {
int ret; int ret;
if (stream_mgr.thread == NULL) if (stream_mgr.thread == 0)
return STREAM_ERROR; return STREAM_ERROR;
stream_mgr_lock(); stream_mgr_lock();
@ -968,7 +968,7 @@ int stream_seek(uint32_t time, int whence)
/* Closes the current file */ /* Closes the current file */
int stream_close(void) int stream_close(void)
{ {
if (stream_mgr.thread != NULL) if (stream_mgr.thread != 0)
return stream_mgr_send_msg(STREAM_CLOSE, 0); return stream_mgr_send_msg(STREAM_CLOSE, 0);
return STREAM_ERROR; return STREAM_ERROR;
} }
@ -1018,7 +1018,7 @@ int stream_init(void)
rb->queue_enable_queue_send(stream_mgr.q, &stream_mgr_queue_send, rb->queue_enable_queue_send(stream_mgr.q, &stream_mgr_queue_send,
stream_mgr.thread); stream_mgr.thread);
if (stream_mgr.thread == NULL) if (stream_mgr.thread == 0)
{ {
rb->splash(HZ, "Could not create stream manager thread!"); rb->splash(HZ, "Could not create stream manager thread!");
return STREAM_ERROR; return STREAM_ERROR;
@ -1073,11 +1073,11 @@ void stream_exit(void)
disk_buf_exit(); disk_buf_exit();
pcm_output_exit(); pcm_output_exit();
if (stream_mgr.thread != NULL) if (stream_mgr.thread != 0)
{ {
stream_mgr_post_msg(STREAM_QUIT, 0); stream_mgr_post_msg(STREAM_QUIT, 0);
rb->thread_wait(stream_mgr.thread); rb->thread_wait(stream_mgr.thread);
stream_mgr.thread = NULL; stream_mgr.thread = 0;
} }
#ifndef HAVE_LCD_COLOR #ifndef HAVE_LCD_COLOR

View file

@ -27,7 +27,7 @@
* coordination with assistance from the parser */ * coordination with assistance from the parser */
struct stream_mgr struct stream_mgr
{ {
struct thread_entry *thread; /* Playback control thread */ unsigned int thread; /* Playback control thread */
struct event_queue *q; /* event queue for control thread */ struct event_queue *q; /* event queue for control thread */
const char *filename; /* Current filename */ const char *filename; /* Current filename */
uint32_t resume_time; /* The stream tick where playback was uint32_t resume_time; /* The stream tick where playback was

View file

@ -45,7 +45,7 @@ struct stream_hdr
struct stream struct stream
{ {
struct stream_hdr hdr; /* Base stream data */ struct stream_hdr hdr; /* Base stream data */
struct thread_entry *thread; /* Stream's thread */ unsigned int thread; /* Stream's thread */
uint8_t* curr_packet; /* Current stream packet beginning */ uint8_t* curr_packet; /* Current stream packet beginning */
uint8_t* curr_packet_end; /* Current stream packet end */ uint8_t* curr_packet_end; /* Current stream packet end */
struct list_item l; /* List of streams - either reserve pool struct list_item l; /* List of streams - either reserve pool

View file

@ -1009,7 +1009,7 @@ bool video_thread_init(void)
rb->queue_enable_queue_send(video_str.hdr.q, &video_str_queue_send, rb->queue_enable_queue_send(video_str.hdr.q, &video_str_queue_send,
video_str.thread); video_str.thread);
if (video_str.thread == NULL) if (video_str.thread == 0)
return false; return false;
/* Wait for thread to initialize */ /* Wait for thread to initialize */
@ -1022,11 +1022,11 @@ bool video_thread_init(void)
/* Terminates the video thread */ /* Terminates the video thread */
void video_thread_exit(void) void video_thread_exit(void)
{ {
if (video_str.thread != NULL) if (video_str.thread != 0)
{ {
str_post_msg(&video_str, STREAM_QUIT, 0); str_post_msg(&video_str, STREAM_QUIT, 0);
rb->thread_wait(video_str.thread); rb->thread_wait(video_str.thread);
IF_COP(invalidate_icache()); IF_COP(invalidate_icache());
video_str.thread = NULL; video_str.thread = 0;
} }
} }

View file

@ -218,7 +218,7 @@ struct mutex slide_cache_stack_lock;
static int empty_slide_hid; static int empty_slide_hid;
struct thread_entry *thread_id; unsigned int thread_id;
struct event_queue thread_q; struct event_queue thread_q;
static char tmp_path_name[MAX_PATH]; static char tmp_path_name[MAX_PATH];
@ -831,7 +831,7 @@ bool create_pf_thread(void)
IF_PRIO(, PRIORITY_BACKGROUND) IF_PRIO(, PRIORITY_BACKGROUND)
IF_COP(, CPU) IF_COP(, CPU)
) )
) == NULL) { ) == 0) {
return false; return false;
} }
thread_is_running = true; thread_is_running = true;

View file

@ -525,7 +525,7 @@ static enum plugin_status test_track(const char* filename)
long ticks; long ticks;
unsigned long speed; unsigned long speed;
unsigned long duration; unsigned long duration;
struct thread_entry* codecthread_id; unsigned int codecthread_id;
const char* ch; const char* ch;
/* Display filename (excluding any path)*/ /* Display filename (excluding any path)*/
@ -590,7 +590,7 @@ static enum plugin_status test_track(const char* filename)
if ((codecthread_id = rb->create_thread(codec_thread, if ((codecthread_id = rb->create_thread(codec_thread,
codec_stack, codec_stack_size, 0, "testcodec" codec_stack, codec_stack_size, 0, "testcodec"
IF_PRIO(,PRIORITY_PLAYBACK) IF_COP(, CPU))) == NULL) IF_PRIO(,PRIORITY_PLAYBACK) IF_COP(, CPU))) == 0)
{ {
log_text("Cannot create codec thread!",true); log_text("Cannot create codec thread!",true);
goto exit; goto exit;

View file

@ -39,7 +39,7 @@ static unsigned long hw_sampr IDATA_ATTR = HW_SAMPR_DEFAULT;
static int gen_thread_stack[DEFAULT_STACK_SIZE/sizeof(int)] IBSS_ATTR; static int gen_thread_stack[DEFAULT_STACK_SIZE/sizeof(int)] IBSS_ATTR;
static bool gen_quit IBSS_ATTR; static bool gen_quit IBSS_ATTR;
static struct thread_entry *gen_thread_p; static unsigned int gen_thread_id;
#define OUTPUT_CHUNK_COUNT (1 << 1) #define OUTPUT_CHUNK_COUNT (1 << 1)
#define OUTPUT_CHUNK_MASK (OUTPUT_CHUNK_COUNT-1) #define OUTPUT_CHUNK_MASK (OUTPUT_CHUNK_COUNT-1)
@ -233,7 +233,7 @@ static void play_tone(bool volume_set)
output_clear(); output_clear();
update_gen_step(); update_gen_step();
gen_thread_p = rb->create_thread(gen_thread_func, gen_thread_stack, gen_thread_id = rb->create_thread(gen_thread_func, gen_thread_stack,
sizeof(gen_thread_stack), 0, sizeof(gen_thread_stack), 0,
"test_sampr generator" "test_sampr generator"
IF_PRIO(, PRIORITY_PLAYBACK) IF_PRIO(, PRIORITY_PLAYBACK)
@ -260,7 +260,7 @@ static void play_tone(bool volume_set)
gen_quit = true; gen_quit = true;
rb->thread_wait(gen_thread_p); rb->thread_wait(gen_thread_id);
rb->pcm_play_stop(); rb->pcm_play_stop();

View file

@ -37,7 +37,7 @@
/***************************************************************************/ /***************************************************************************/
extern struct thread_entry *codec_thread_p; extern uintptr_t codec_thread_id;
/** General recording state **/ /** General recording state **/
static bool is_recording; /* We are recording */ static bool is_recording; /* We are recording */
@ -220,7 +220,7 @@ static struct event_queue pcmrec_queue SHAREDBSS_ATTR;
static struct queue_sender_list pcmrec_queue_send SHAREDBSS_ATTR; static struct queue_sender_list pcmrec_queue_send SHAREDBSS_ATTR;
static long pcmrec_stack[3*DEFAULT_STACK_SIZE/sizeof(long)]; static long pcmrec_stack[3*DEFAULT_STACK_SIZE/sizeof(long)];
static const char pcmrec_thread_name[] = "pcmrec"; static const char pcmrec_thread_name[] = "pcmrec";
static struct thread_entry *pcmrec_thread_p; static unsigned int pcmrec_thread_id = 0;
static void pcmrec_thread(void); static void pcmrec_thread(void);
@ -365,12 +365,12 @@ unsigned long pcm_rec_sample_rate(void)
void pcm_rec_init(void) void pcm_rec_init(void)
{ {
queue_init(&pcmrec_queue, true); queue_init(&pcmrec_queue, true);
pcmrec_thread_p = pcmrec_thread_id =
create_thread(pcmrec_thread, pcmrec_stack, sizeof(pcmrec_stack), create_thread(pcmrec_thread, pcmrec_stack, sizeof(pcmrec_stack),
0, pcmrec_thread_name IF_PRIO(, PRIORITY_RECORDING) 0, pcmrec_thread_name IF_PRIO(, PRIORITY_RECORDING)
IF_COP(, CPU)); IF_COP(, CPU));
queue_enable_queue_send(&pcmrec_queue, &pcmrec_queue_send, queue_enable_queue_send(&pcmrec_queue, &pcmrec_queue_send,
pcmrec_thread_p); pcmrec_thread_id);
} /* pcm_rec_init */ } /* pcm_rec_init */
/** audio_* group **/ /** audio_* group **/
@ -878,10 +878,10 @@ static void pcmrec_flush(unsigned flush_num)
priority until finished */ priority until finished */
logf("pcmrec: boost (%s)", logf("pcmrec: boost (%s)",
num >= flood_watermark ? "num" : "time"); num >= flood_watermark ? "num" : "time");
prio_pcmrec = thread_set_priority(NULL, prio_pcmrec = thread_set_priority(THREAD_ID_CURRENT,
thread_get_priority(NULL) - 4); thread_get_priority(THREAD_ID_CURRENT) - 4);
prio_codec = thread_set_priority(codec_thread_p, prio_codec = thread_set_priority(codec_thread_id,
thread_get_priority(codec_thread_p) - 4); thread_get_priority(codec_thread_id) - 4);
} }
#endif #endif
@ -931,8 +931,8 @@ static void pcmrec_flush(unsigned flush_num)
{ {
/* return to original priorities */ /* return to original priorities */
logf("pcmrec: unboost priority"); logf("pcmrec: unboost priority");
thread_set_priority(NULL, prio_pcmrec); thread_set_priority(THREAD_ID_CURRENT, prio_pcmrec);
thread_set_priority(codec_thread_p, prio_codec); thread_set_priority(codec_thread_id, prio_codec);
} }
last_flush_tick = current_tick; /* save tick when we left */ last_flush_tick = current_tick; /* save tick when we left */

View file

@ -54,7 +54,7 @@
#define VOICE_SAMPLE_DEPTH 16 /* Sample depth in bits */ #define VOICE_SAMPLE_DEPTH 16 /* Sample depth in bits */
/* Voice thread variables */ /* Voice thread variables */
static struct thread_entry *voice_thread_p = NULL; static unsigned int voice_thread_id = 0;
static long voice_stack[0x7c0/sizeof(long)] IBSS_ATTR_VOICE_STACK; static long voice_stack[0x7c0/sizeof(long)] IBSS_ATTR_VOICE_STACK;
static const char voice_thread_name[] = "voice"; static const char voice_thread_name[] = "voice";
@ -434,25 +434,25 @@ void voice_thread_init(void)
queue_init(&voice_queue, false); queue_init(&voice_queue, false);
mutex_init(&voice_mutex); mutex_init(&voice_mutex);
voice_thread_p = create_thread(voice_thread, voice_stack, voice_thread_id = create_thread(voice_thread, voice_stack,
sizeof(voice_stack), CREATE_THREAD_FROZEN, sizeof(voice_stack), CREATE_THREAD_FROZEN,
voice_thread_name IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU)); voice_thread_name IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU));
queue_enable_queue_send(&voice_queue, &voice_queue_sender_list, queue_enable_queue_send(&voice_queue, &voice_queue_sender_list,
voice_thread_p); voice_thread_id);
} /* voice_thread_init */ } /* voice_thread_init */
/* Unfreeze the voice thread */ /* Unfreeze the voice thread */
void voice_thread_resume(void) void voice_thread_resume(void)
{ {
logf("Thawing voice thread"); logf("Thawing voice thread");
thread_thaw(voice_thread_p); thread_thaw(voice_thread_id);
} }
#ifdef HAVE_PRIORITY_SCHEDULING #ifdef HAVE_PRIORITY_SCHEDULING
/* Set the voice thread priority */ /* Set the voice thread priority */
void voice_thread_set_priority(int priority) void voice_thread_set_priority(int priority)
{ {
thread_set_priority(voice_thread_p, priority); thread_set_priority(voice_thread_id, priority);
} }
#endif #endif

View file

@ -130,7 +130,7 @@ static long backlight_stack[DEFAULT_STACK_SIZE/sizeof(long)];
static const char backlight_thread_name[] = "backlight"; static const char backlight_thread_name[] = "backlight";
static struct event_queue backlight_queue; static struct event_queue backlight_queue;
#ifdef BACKLIGHT_DRIVER_CLOSE #ifdef BACKLIGHT_DRIVER_CLOSE
static struct thread_entry *backlight_thread_p = NULL; static unsigned int backlight_thread_id = 0;
#endif #endif
static int backlight_timer SHAREDBSS_ATTR; static int backlight_timer SHAREDBSS_ATTR;
@ -744,7 +744,7 @@ void backlight_init(void)
* call the appropriate backlight_set_*() functions, only changing light * call the appropriate backlight_set_*() functions, only changing light
* status if necessary. */ * status if necessary. */
#ifdef BACKLIGHT_DRIVER_CLOSE #ifdef BACKLIGHT_DRIVER_CLOSE
backlight_thread_p = backlight_thread_id =
#endif #endif
create_thread(backlight_thread, backlight_stack, create_thread(backlight_thread, backlight_stack,
sizeof(backlight_stack), 0, backlight_thread_name sizeof(backlight_stack), 0, backlight_thread_name
@ -756,13 +756,13 @@ void backlight_init(void)
#ifdef BACKLIGHT_DRIVER_CLOSE #ifdef BACKLIGHT_DRIVER_CLOSE
void backlight_close(void) void backlight_close(void)
{ {
struct thread_entry *thread = backlight_thread_p; unsigned int thread = backlight_thread_id;
/* Wait for thread to exit */ /* Wait for thread to exit */
if (thread == NULL) if (thread == 0)
return; return;
backlight_thread_p = NULL; backlight_thread_id = 0;
queue_post(&backlight_queue, BACKLIGHT_QUIT, 0); queue_post(&backlight_queue, BACKLIGHT_QUIT, 0);
thread_wait(thread); thread_wait(thread);

View file

@ -71,7 +71,7 @@
#endif #endif
#ifdef ATA_DRIVER_CLOSE #ifdef ATA_DRIVER_CLOSE
static struct thread_entry *ata_thread_p = NULL; static unsigned int ata_thread_id = 0;
#endif #endif
#if defined(MAX_PHYS_SECTOR_SIZE) && MEM == 64 #if defined(MAX_PHYS_SECTOR_SIZE) && MEM == 64
@ -94,7 +94,8 @@ static void ata_lock_init(struct ata_lock *l)
static void ata_lock_lock(struct ata_lock *l) static void ata_lock_lock(struct ata_lock *l)
{ {
struct thread_entry * const current = thread_get_current(); struct thread_entry * const current =
thread_id_entry(THREAD_ID_CURRENT);
if (current == l->thread) if (current == l->thread)
{ {
@ -1350,7 +1351,7 @@ int ata_init(void)
last_disk_activity = current_tick; last_disk_activity = current_tick;
#ifdef ATA_DRIVER_CLOSE #ifdef ATA_DRIVER_CLOSE
ata_thread_p = ata_thread_id =
#endif #endif
create_thread(ata_thread, ata_stack, create_thread(ata_thread, ata_stack,
sizeof(ata_stack), 0, ata_thread_name sizeof(ata_stack), 0, ata_thread_name
@ -1370,15 +1371,15 @@ int ata_init(void)
#ifdef ATA_DRIVER_CLOSE #ifdef ATA_DRIVER_CLOSE
void ata_close(void) void ata_close(void)
{ {
struct thread_entry *thread = ata_thread_p; unsigned int thread_id = ata_thread_id;
if (thread == NULL) if (thread_id == 0)
return; return;
ata_thread_p = NULL; ata_thread_id = 0;
queue_post(&ata_queue, Q_CLOSE, 0); queue_post(&ata_queue, Q_CLOSE, 0);
thread_wait(thread); thread_wait(thread_id);
} }
#endif /* ATA_DRIVER_CLOSE */ #endif /* ATA_DRIVER_CLOSE */

View file

@ -261,7 +261,7 @@ extern void queue_post(struct event_queue *q, long id, intptr_t data);
#ifdef HAVE_EXTENDED_MESSAGING_AND_NAME #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
extern void queue_enable_queue_send(struct event_queue *q, extern void queue_enable_queue_send(struct event_queue *q,
struct queue_sender_list *send, struct queue_sender_list *send,
struct thread_entry *owner); unsigned int owner_id);
extern intptr_t queue_send(struct event_queue *q, long id, intptr_t data); extern intptr_t queue_send(struct event_queue *q, long id, intptr_t data);
extern void queue_reply(struct event_queue *q, intptr_t retval); extern void queue_reply(struct event_queue *q, intptr_t retval);
extern bool queue_in_queue_send(struct event_queue *q); extern bool queue_in_queue_send(struct event_queue *q);

View file

@ -58,9 +58,6 @@
#define NUM_PRIORITIES 32 #define NUM_PRIORITIES 32
#define PRIORITY_IDLE 32 /* Priority representative of no tasks */ #define PRIORITY_IDLE 32 /* Priority representative of no tasks */
/* TODO: Only a minor tweak to create_thread would be needed to let
* thread slots be caller allocated - no essential threading functionality
* depends upon an array */
#if CONFIG_CODEC == SWCODEC #if CONFIG_CODEC == SWCODEC
#ifdef HAVE_RECORDING #ifdef HAVE_RECORDING
@ -280,6 +277,7 @@ struct thread_entry
int skip_count; /* Number of times skipped if higher priority int skip_count; /* Number of times skipped if higher priority
thread was running */ thread was running */
#endif #endif
uint16_t id; /* Current slot id */
unsigned short stack_size; /* Size of stack in bytes */ unsigned short stack_size; /* Size of stack in bytes */
#ifdef HAVE_PRIORITY_SCHEDULING #ifdef HAVE_PRIORITY_SCHEDULING
unsigned char base_priority; /* Base priority (set explicitly during unsigned char base_priority; /* Base priority (set explicitly during
@ -298,6 +296,16 @@ struct thread_entry
#endif #endif
}; };
/*** Macros for internal use ***/
/* Thread ID, 16 bits = |VVVVVVVV|SSSSSSSS| */
#define THREAD_ID_VERSION_SHIFT 8
#define THREAD_ID_VERSION_MASK 0xff00
#define THREAD_ID_SLOT_MASK 0x00ff
#define THREAD_ID_INIT(n) ((1u << THREAD_ID_VERSION_SHIFT) | (n))
/* Specify current thread in a function taking an ID. */
#define THREAD_ID_CURRENT ((unsigned int)-1)
#if NUM_CORES > 1 #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 */
@ -475,8 +483,8 @@ void init_threads(void);
/* Allocate a thread in the scheduler */ /* Allocate a thread in the scheduler */
#define CREATE_THREAD_FROZEN 0x00000001 /* Thread is frozen at create time */ #define CREATE_THREAD_FROZEN 0x00000001 /* Thread is frozen at create time */
struct thread_entry* unsigned int create_thread(void (*function)(void),
create_thread(void (*function)(void), void* stack, size_t stack_size, void* stack, size_t stack_size,
unsigned flags, const char *name unsigned flags, const char *name
IF_PRIO(, int priority) IF_PRIO(, int priority)
IF_COP(, unsigned int core)); IF_COP(, unsigned int core));
@ -489,17 +497,19 @@ void cancel_cpu_boost(void);
#define trigger_cpu_boost() #define trigger_cpu_boost()
#define cancel_cpu_boost() #define cancel_cpu_boost()
#endif #endif
/* Return thread entry from id */
struct thread_entry *thread_id_entry(unsigned int thread_id);
/* Make a frozed thread runnable (when started with CREATE_THREAD_FROZEN). /* Make a frozed thread runnable (when started with CREATE_THREAD_FROZEN).
* Has no effect on a thread not frozen. */ * Has no effect on a thread not frozen. */
void thread_thaw(struct thread_entry *thread); void thread_thaw(unsigned int thread_id);
/* Wait for a thread to exit */ /* Wait for a thread to exit */
void thread_wait(struct thread_entry *thread); void thread_wait(unsigned int thread_id);
/* Exit the current thread */ /* Exit the current thread */
void thread_exit(void); void thread_exit(void);
#if defined(DEBUG) || defined(ROCKBOX_HAS_LOGF) #if defined(DEBUG) || defined(ROCKBOX_HAS_LOGF)
#define ALLOW_REMOVE_THREAD #define ALLOW_REMOVE_THREAD
/* Remove a thread from the scheduler */ /* Remove a thread from the scheduler */
void remove_thread(struct thread_entry *thread); void remove_thread(unsigned int thread_id);
#endif #endif
/* Switch to next runnable thread */ /* Switch to next runnable thread */
@ -526,13 +536,13 @@ unsigned int thread_queue_wake(struct thread_entry **list);
unsigned int wakeup_thread(struct thread_entry **list); unsigned int wakeup_thread(struct thread_entry **list);
#ifdef HAVE_PRIORITY_SCHEDULING #ifdef HAVE_PRIORITY_SCHEDULING
int thread_set_priority(struct thread_entry *thread, int priority); int thread_set_priority(unsigned int thread_id, int priority);
int thread_get_priority(struct thread_entry *thread); int thread_get_priority(unsigned int thread_id);
#endif /* HAVE_PRIORITY_SCHEDULING */ #endif /* HAVE_PRIORITY_SCHEDULING */
#if NUM_CORES > 1 #if NUM_CORES > 1
unsigned int switch_core(unsigned int new_core); unsigned int switch_core(unsigned int new_core);
#endif #endif
struct thread_entry * thread_get_current(void); unsigned int thread_get_current(void);
/* Debugging info - only! */ /* Debugging info - only! */
int thread_stack_usage(const struct thread_entry *thread); int thread_stack_usage(const struct thread_entry *thread);

View file

@ -352,11 +352,12 @@ static void queue_remove_sender_thread_cb(struct thread_entry *thread)
* specified for priority inheritance to operate. * specified for priority inheritance to operate.
* *
* Use of queue_wait(_w_tmo) by multiple threads on a queue using synchronous * Use of queue_wait(_w_tmo) by multiple threads on a queue using synchronous
* messages results in an undefined order of message replies. * messages results in an undefined order of message replies or possible default
* replies if two or more waits happen before a reply is done.
*/ */
void queue_enable_queue_send(struct event_queue *q, void queue_enable_queue_send(struct event_queue *q,
struct queue_sender_list *send, struct queue_sender_list *send,
struct thread_entry *owner) unsigned int owner_id)
{ {
int oldlevel = disable_irq_save(); int oldlevel = disable_irq_save();
corelock_lock(&q->cl); corelock_lock(&q->cl);
@ -367,9 +368,11 @@ void queue_enable_queue_send(struct event_queue *q,
#ifdef HAVE_PRIORITY_SCHEDULING #ifdef HAVE_PRIORITY_SCHEDULING
send->blocker.wakeup_protocol = wakeup_priority_protocol_release; send->blocker.wakeup_protocol = wakeup_priority_protocol_release;
send->blocker.priority = PRIORITY_IDLE; send->blocker.priority = PRIORITY_IDLE;
send->blocker.thread = owner; if(owner_id != 0)
if(owner != NULL) {
send->blocker.thread = thread_id_entry(owner_id);
q->blocker_p = &send->blocker; q->blocker_p = &send->blocker;
}
#endif #endif
q->send = send; q->send = send;
} }
@ -377,7 +380,7 @@ void queue_enable_queue_send(struct event_queue *q,
corelock_unlock(&q->cl); corelock_unlock(&q->cl);
restore_irq(oldlevel); restore_irq(oldlevel);
(void)owner; (void)owner_id;
} }
/* Unblock a blocked thread at a given event index */ /* Unblock a blocked thread at a given event index */
@ -532,7 +535,7 @@ void queue_wait(struct event_queue *q, struct queue_event *ev)
#ifdef HAVE_PRIORITY_SCHEDULING #ifdef HAVE_PRIORITY_SCHEDULING
KERNEL_ASSERT(QUEUE_GET_THREAD(q) == NULL || KERNEL_ASSERT(QUEUE_GET_THREAD(q) == NULL ||
QUEUE_GET_THREAD(q) == thread_get_current(), QUEUE_GET_THREAD(q) == cores[CURRENT_CORE].running,
"queue_wait->wrong thread\n"); "queue_wait->wrong thread\n");
#endif #endif
@ -579,7 +582,7 @@ void queue_wait_w_tmo(struct event_queue *q, struct queue_event *ev, int ticks)
#ifdef HAVE_EXTENDED_MESSAGING_AND_NAME #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
KERNEL_ASSERT(QUEUE_GET_THREAD(q) == NULL || KERNEL_ASSERT(QUEUE_GET_THREAD(q) == NULL ||
QUEUE_GET_THREAD(q) == thread_get_current(), QUEUE_GET_THREAD(q) == cores[CURRENT_CORE].running,
"queue_wait_w_tmo->wrong thread\n"); "queue_wait_w_tmo->wrong thread\n");
#endif #endif
@ -914,10 +917,10 @@ void mutex_lock(struct mutex *m)
void mutex_unlock(struct mutex *m) void mutex_unlock(struct mutex *m)
{ {
/* unlocker not being the owner is an unlocking violation */ /* unlocker not being the owner is an unlocking violation */
KERNEL_ASSERT(MUTEX_GET_THREAD(m) == thread_get_current(), KERNEL_ASSERT(MUTEX_GET_THREAD(m) == cores[CURRENT_CORE].running,
"mutex_unlock->wrong thread (%s != %s)\n", "mutex_unlock->wrong thread (%s != %s)\n",
MUTEX_GET_THREAD(m)->name, MUTEX_GET_THREAD(m)->name,
thread_get_current()->name); cores[CURRENT_CORE].running->name);
if(m->count > 0) if(m->count > 0)
{ {
@ -990,7 +993,7 @@ void spinlock_lock(struct spinlock *l)
void spinlock_unlock(struct spinlock *l) void spinlock_unlock(struct spinlock *l)
{ {
/* unlocker not being the owner is an unlocking violation */ /* unlocker not being the owner is an unlocking violation */
KERNEL_ASSERT(l->thread == thread_get_current(), KERNEL_ASSERT(l->thread == cores[CURRENT_CORE].running,
"spinlock_unlock->wrong thread\n"); "spinlock_unlock->wrong thread\n");
if(l->count > 0) if(l->count > 0)

View file

@ -69,7 +69,7 @@ static const unsigned char pmic_ints_regs[2] =
#ifdef PMIC_DRIVER_CLOSE #ifdef PMIC_DRIVER_CLOSE
static bool pmic_close = false; static bool pmic_close = false;
static struct thread_entry *mc13783_thread_p = NULL; static unsigned int mc13783_thread_id = 0;
#endif #endif
static void mc13783_interrupt_thread(void) static void mc13783_interrupt_thread(void)
@ -149,7 +149,7 @@ void mc13783_init(void)
MC13783_GPIO_ISR = (1ul << MC13783_GPIO_LINE); MC13783_GPIO_ISR = (1ul << MC13783_GPIO_LINE);
#ifdef PMIC_DRIVER_CLOSE #ifdef PMIC_DRIVER_CLOSE
mc13783_thread_p = mc13783_thread_id =
#endif #endif
create_thread(mc13783_interrupt_thread, create_thread(mc13783_interrupt_thread,
mc13783_thread_stack, sizeof(mc13783_thread_stack), 0, mc13783_thread_stack, sizeof(mc13783_thread_stack), 0,
@ -159,16 +159,16 @@ void mc13783_init(void)
#ifdef PMIC_DRIVER_CLOSE #ifdef PMIC_DRIVER_CLOSE
void mc13783_close(void) void mc13783_close(void)
{ {
struct thread_entry *thread = mc13783_thread_p; unsigned int thread_id = mc13783_thread_p;
if (thread == NULL) if (thread_id == 0)
return; return;
mc13783_thread_p = NULL; mc13783_thread_id = 0;
pmic_close = true; pmic_close = true;
wakeup_signal(&mc13783_wake); wakeup_signal(&mc13783_wake);
thread_wait(thread); thread_wait(thread_id);
} }
#endif /* PMIC_DRIVER_CLOSE */ #endif /* PMIC_DRIVER_CLOSE */

View file

@ -1691,8 +1691,8 @@ struct thread_entry *
struct thread_entry *next; struct thread_entry *next;
int bl_pr; int bl_pr;
THREAD_ASSERT(thread_get_current() == bl_t, THREAD_ASSERT(cores[CURRENT_CORE].running == bl_t,
"UPPT->wrong thread", thread_get_current()); "UPPT->wrong thread", cores[CURRENT_CORE].running);
LOCK_THREAD(bl_t); LOCK_THREAD(bl_t);
@ -2031,7 +2031,7 @@ void switch_thread(void)
} }
#ifdef RB_PROFILE #ifdef RB_PROFILE
profile_thread_stopped(thread - threads); profile_thread_stopped(thread->id & THREAD_ID_SLOT_MASK);
#endif #endif
/* Begin task switching by saving our current context so that we can /* Begin task switching by saving our current context so that we can
@ -2136,7 +2136,7 @@ void switch_thread(void)
load_context(&thread->context); load_context(&thread->context);
#ifdef RB_PROFILE #ifdef RB_PROFILE
profile_thread_started(thread - threads); profile_thread_started(thread->id & THREAD_ID_SLOT_MASK);
#endif #endif
} }
@ -2315,6 +2315,24 @@ unsigned int thread_queue_wake(struct thread_entry **list)
return result; return result;
} }
/*---------------------------------------------------------------------------
* Assign the thread slot a new ID. Version is 1-255.
*---------------------------------------------------------------------------
*/
static void new_thread_id(unsigned int slot_num,
struct thread_entry *thread)
{
unsigned int version =
(thread->id + (1u << THREAD_ID_VERSION_SHIFT))
& THREAD_ID_VERSION_MASK;
/* If wrapped to 0, make it 1 */
if (version == 0)
version = 1u << THREAD_ID_VERSION_SHIFT;
thread->id = version | (slot_num & THREAD_ID_SLOT_MASK);
}
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
* Find an empty thread slot or MAXTHREADS if none found. The slot returned * Find an empty thread slot or MAXTHREADS if none found. The slot returned
* will be locked on multicore. * will be locked on multicore.
@ -2349,6 +2367,17 @@ static struct thread_entry * find_empty_thread_slot(void)
return thread; return thread;
} }
/*---------------------------------------------------------------------------
* Return the thread_entry pointer for a thread_id. Return the current
* thread if the ID is 0 (alias for current).
*---------------------------------------------------------------------------
*/
struct thread_entry * thread_id_entry(unsigned int thread_id)
{
return (thread_id == THREAD_ID_CURRENT) ?
cores[CURRENT_CORE].running :
&threads[thread_id & THREAD_ID_SLOT_MASK];
}
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
* Place the current core in idle mode - woken up on interrupt or wake * Place the current core in idle mode - woken up on interrupt or wake
@ -2369,8 +2398,8 @@ void core_idle(void)
* Return ID if context area could be allocated, else NULL. * Return ID if context area could be allocated, else NULL.
*--------------------------------------------------------------------------- *---------------------------------------------------------------------------
*/ */
struct thread_entry* unsigned int create_thread(void (*function)(void),
create_thread(void (*function)(void), void* stack, size_t stack_size, void* stack, size_t stack_size,
unsigned flags, const char *name unsigned flags, const char *name
IF_PRIO(, int priority) IF_PRIO(, int priority)
IF_COP(, unsigned int core)) IF_COP(, unsigned int core))
@ -2385,7 +2414,7 @@ struct thread_entry*
thread = find_empty_thread_slot(); thread = find_empty_thread_slot();
if (thread == NULL) if (thread == NULL)
{ {
return NULL; return 0;
} }
oldlevel = disable_irq_save(); oldlevel = disable_irq_save();
@ -2443,15 +2472,15 @@ struct thread_entry*
THREAD_STARTUP_INIT(core, thread, function); THREAD_STARTUP_INIT(core, thread, function);
thread->state = state; thread->state = state;
i = thread->id; /* Snapshot while locked */
if (state == STATE_RUNNING) if (state == STATE_RUNNING)
core_schedule_wakeup(thread); core_schedule_wakeup(thread);
UNLOCK_THREAD(thread); UNLOCK_THREAD(thread);
restore_irq(oldlevel); restore_irq(oldlevel);
return thread; return i;
} }
#ifdef HAVE_SCHEDULER_BOOSTCTRL #ifdef HAVE_SCHEDULER_BOOSTCTRL
@ -2489,18 +2518,17 @@ void cancel_cpu_boost(void)
* Parameter is the ID as returned from create_thread(). * Parameter is the ID as returned from create_thread().
*--------------------------------------------------------------------------- *---------------------------------------------------------------------------
*/ */
void thread_wait(struct thread_entry *thread) void thread_wait(unsigned int thread_id)
{ {
struct thread_entry *current = cores[CURRENT_CORE].running; struct thread_entry *current = cores[CURRENT_CORE].running;
struct thread_entry *thread = thread_id_entry(thread_id);
if (thread == NULL)
thread = current;
/* Lock thread-as-waitable-object lock */ /* Lock thread-as-waitable-object lock */
corelock_lock(&thread->waiter_cl); corelock_lock(&thread->waiter_cl);
/* Be sure it hasn't been killed yet */ /* Be sure it hasn't been killed yet */
if (thread->state != STATE_KILLED) if (thread_id == THREAD_ID_CURRENT ||
(thread->id == thread_id && thread->state != STATE_KILLED))
{ {
IF_COP( current->obj_cl = &thread->waiter_cl; ) IF_COP( current->obj_cl = &thread->waiter_cl; )
current->bqp = &thread->queue; current->bqp = &thread->queue;
@ -2538,9 +2566,10 @@ void thread_exit(void)
if (current->name == THREAD_DESTRUCT) if (current->name == THREAD_DESTRUCT)
{ {
/* Thread being killed - become a waiter */ /* Thread being killed - become a waiter */
unsigned int id = current->id;
UNLOCK_THREAD(current); UNLOCK_THREAD(current);
corelock_unlock(&current->waiter_cl); corelock_unlock(&current->waiter_cl);
thread_wait(current); thread_wait(id);
THREAD_PANICF("thread_exit->WK:*R", current); THREAD_PANICF("thread_exit->WK:*R", current);
} }
#endif #endif
@ -2568,7 +2597,13 @@ void thread_exit(void)
} }
flush_icache(); flush_icache();
/* At this point, this thread isn't using resources allocated for
* execution except the slot itself. */
#endif #endif
/* Update ID for this slot */
new_thread_id(current->id, current);
current->name = NULL; current->name = NULL;
/* Signal this thread */ /* Signal this thread */
@ -2593,7 +2628,7 @@ void thread_exit(void)
* leave various objects in an undefined state. * leave various objects in an undefined state.
*--------------------------------------------------------------------------- *---------------------------------------------------------------------------
*/ */
void remove_thread(struct thread_entry *thread) void remove_thread(unsigned int thread_id)
{ {
#if NUM_CORES > 1 #if NUM_CORES > 1
/* core is not constant here because of core switching */ /* core is not constant here because of core switching */
@ -2604,13 +2639,11 @@ void remove_thread(struct thread_entry *thread)
const unsigned int core = CURRENT_CORE; const unsigned int core = CURRENT_CORE;
#endif #endif
struct thread_entry *current = cores[core].running; struct thread_entry *current = cores[core].running;
struct thread_entry *thread = thread_id_entry(thread_id);
unsigned state; unsigned state;
int oldlevel; int oldlevel;
if (thread == NULL)
thread = current;
if (thread == current) if (thread == current)
thread_exit(); /* Current thread - do normal exit */ thread_exit(); /* Current thread - do normal exit */
@ -2621,10 +2654,8 @@ void remove_thread(struct thread_entry *thread)
state = thread->state; state = thread->state;
if (state == STATE_KILLED) if (thread->id != thread_id || state == STATE_KILLED)
{
goto thread_killed; goto thread_killed;
}
#if NUM_CORES > 1 #if NUM_CORES > 1
if (thread->name == THREAD_DESTRUCT) if (thread->name == THREAD_DESTRUCT)
@ -2633,7 +2664,7 @@ void remove_thread(struct thread_entry *thread)
UNLOCK_THREAD(thread); UNLOCK_THREAD(thread);
corelock_unlock(&thread->waiter_cl); corelock_unlock(&thread->waiter_cl);
restore_irq(oldlevel); restore_irq(oldlevel);
thread_wait(thread); thread_wait(thread_id);
return; return;
} }
@ -2741,6 +2772,7 @@ IF_COP( retry_state: )
/* Otherwise thread is frozen and hasn't run yet */ /* Otherwise thread is frozen and hasn't run yet */
} }
new_thread_id(thread_id, thread);
thread->state = STATE_KILLED; thread->state = STATE_KILLED;
/* If thread was waiting on itself, it will have been removed above. /* If thread was waiting on itself, it will have been removed above.
@ -2773,17 +2805,15 @@ thread_killed: /* Thread was already killed */
* needed inheritance changes also may happen. * needed inheritance changes also may happen.
*--------------------------------------------------------------------------- *---------------------------------------------------------------------------
*/ */
int thread_set_priority(struct thread_entry *thread, int priority) int thread_set_priority(unsigned int thread_id, int priority)
{ {
int old_base_priority = -1; int old_base_priority = -1;
struct thread_entry *thread = thread_id_entry(thread_id);
/* A little safety measure */ /* A little safety measure */
if (priority < HIGHEST_PRIORITY || priority > LOWEST_PRIORITY) if (priority < HIGHEST_PRIORITY || priority > LOWEST_PRIORITY)
return -1; return -1;
if (thread == NULL)
thread = cores[CURRENT_CORE].running;
/* Thread could be on any list and therefore on an interrupt accessible /* Thread could be on any list and therefore on an interrupt accessible
one - disable interrupts */ one - disable interrupts */
int oldlevel = disable_irq_save(); int oldlevel = disable_irq_save();
@ -2791,7 +2821,8 @@ int thread_set_priority(struct thread_entry *thread, int priority)
LOCK_THREAD(thread); LOCK_THREAD(thread);
/* Make sure it's not killed */ /* Make sure it's not killed */
if (thread->state != STATE_KILLED) if (thread_id == THREAD_ID_CURRENT ||
(thread->id == thread_id && thread->state != STATE_KILLED))
{ {
int old_priority = thread->priority; int old_priority = thread->priority;
@ -2908,13 +2939,19 @@ int thread_set_priority(struct thread_entry *thread, int priority)
* Returns the current base priority for a thread. * Returns the current base priority for a thread.
*--------------------------------------------------------------------------- *---------------------------------------------------------------------------
*/ */
int thread_get_priority(struct thread_entry *thread) int thread_get_priority(unsigned int thread_id)
{ {
/* Simple, quick probe. */ struct thread_entry *thread = thread_id_entry(thread_id);
if (thread == NULL) int base_priority = thread->base_priority;
thread = cores[CURRENT_CORE].running;
return thread->base_priority; /* Simply check without locking slot. It may or may not be valid by the
* time the function returns anyway. If all tests pass, it is the
* correct value for when it was valid. */
if (thread_id != THREAD_ID_CURRENT &&
(thread->id != thread_id || thread->state == STATE_KILLED))
base_priority = -1;
return base_priority;
} }
#endif /* HAVE_PRIORITY_SCHEDULING */ #endif /* HAVE_PRIORITY_SCHEDULING */
@ -2924,12 +2961,16 @@ int thread_get_priority(struct thread_entry *thread)
* virtue of the slot having a state of STATE_FROZEN. * virtue of the slot having a state of STATE_FROZEN.
*--------------------------------------------------------------------------- *---------------------------------------------------------------------------
*/ */
void thread_thaw(struct thread_entry *thread) void thread_thaw(unsigned int thread_id)
{ {
struct thread_entry *thread = thread_id_entry(thread_id);
int oldlevel = disable_irq_save(); int oldlevel = disable_irq_save();
LOCK_THREAD(thread); LOCK_THREAD(thread);
if (thread->state == STATE_FROZEN) /* If thread is the current one, it cannot be frozen, therefore
* there is no need to check that. */
if (thread->id == thread_id && thread->state == STATE_FROZEN)
core_schedule_wakeup(thread); core_schedule_wakeup(thread);
UNLOCK_THREAD(thread); UNLOCK_THREAD(thread);
@ -2940,9 +2981,9 @@ void thread_thaw(struct thread_entry *thread)
* Return the ID of the currently executing thread. * Return the ID of the currently executing thread.
*--------------------------------------------------------------------------- *---------------------------------------------------------------------------
*/ */
struct thread_entry * thread_get_current(void) unsigned int thread_get_current(void)
{ {
return cores[CURRENT_CORE].running; return cores[CURRENT_CORE].running->id;
} }
#if NUM_CORES > 1 #if NUM_CORES > 1
@ -2967,9 +3008,10 @@ unsigned int switch_core(unsigned int new_core)
if (current->name == THREAD_DESTRUCT) if (current->name == THREAD_DESTRUCT)
{ {
/* Thread being killed - deactivate and let process complete */ /* Thread being killed - deactivate and let process complete */
unsigned int id = current->id;
UNLOCK_THREAD(current); UNLOCK_THREAD(current);
restore_irq(oldlevel); restore_irq(oldlevel);
thread_wait(current); thread_wait(id);
/* Should never be reached */ /* Should never be reached */
THREAD_PANICF("switch_core->D:*R", current); THREAD_PANICF("switch_core->D:*R", current);
} }
@ -3034,6 +3076,19 @@ void init_threads(void)
const unsigned int core = CURRENT_CORE; const unsigned int core = CURRENT_CORE;
struct thread_entry *thread; struct thread_entry *thread;
if (core == CPU)
{
/* Initialize core locks and IDs in all slots */
int n;
for (n = 0; n < MAXTHREADS; n++)
{
thread = &threads[n];
corelock_init(&thread->waiter_cl);
corelock_init(&thread->slot_cl);
thread->id = THREAD_ID_INIT(n);
}
}
/* CPU will initialize first and then sleep */ /* CPU will initialize first and then sleep */
thread = find_empty_thread_slot(); thread = find_empty_thread_slot();
@ -3060,8 +3115,6 @@ void init_threads(void)
thread->priority = PRIORITY_USER_INTERFACE; thread->priority = PRIORITY_USER_INTERFACE;
rtr_add_entry(core, PRIORITY_USER_INTERFACE); rtr_add_entry(core, PRIORITY_USER_INTERFACE);
#endif #endif
corelock_init(&thread->waiter_cl);
corelock_init(&thread->slot_cl);
add_to_list_l(&cores[core].running, thread); add_to_list_l(&cores[core].running, thread);
@ -3070,6 +3123,7 @@ void init_threads(void)
thread->stack = stackbegin; thread->stack = stackbegin;
thread->stack_size = (uintptr_t)stackend - (uintptr_t)stackbegin; thread->stack_size = (uintptr_t)stackend - (uintptr_t)stackbegin;
#if NUM_CORES > 1 /* This code path will not be run on single core targets */ #if NUM_CORES > 1 /* This code path will not be run on single core targets */
/* Initialize all locking for the slots */
/* Wait for other processors to finish their inits since create_thread /* Wait for other processors to finish their inits since create_thread
* isn't safe to call until the kernel inits are done. The first * isn't safe to call until the kernel inits are done. The first
* threads created in the system must of course be created by CPU. */ * threads created in the system must of course be created by CPU. */

View file

@ -78,7 +78,7 @@ static int usb_mmc_countdown = 0;
#ifdef USB_FULL_INIT #ifdef USB_FULL_INIT
static long usb_stack[(DEFAULT_STACK_SIZE + 0x800)/sizeof(long)]; static long usb_stack[(DEFAULT_STACK_SIZE + 0x800)/sizeof(long)];
static const char usb_thread_name[] = "usb"; static const char usb_thread_name[] = "usb";
static struct thread_entry *usb_thread_entry; static unsigned int usb_thread_entry = 0;
#endif #endif
static struct event_queue usb_queue; static struct event_queue usb_queue;
static int last_usb_status; static int last_usb_status;
@ -539,10 +539,10 @@ void usb_start_monitoring(void)
#ifdef USB_DRIVER_CLOSE #ifdef USB_DRIVER_CLOSE
void usb_close(void) void usb_close(void)
{ {
struct thread_entry *thread = usb_thread_entry; uintptr_t thread = usb_thread_entry;
usb_thread_entry = NULL; usb_thread_entry = 0;
if (thread == NULL) if (thread == 0)
return; return;
tick_remove_task(usb_tick); tick_remove_task(usb_tick);

View file

@ -93,6 +93,38 @@ void thread_sdl_shutdown(void)
SDL_DestroyMutex(m); SDL_DestroyMutex(m);
} }
static void new_thread_id(unsigned int slot_num,
struct thread_entry *thread)
{
unsigned int version =
(thread->id + (1u << THREAD_ID_VERSION_SHIFT))
& THREAD_ID_VERSION_MASK;
if (version == 0)
version = 1u << THREAD_ID_VERSION_SHIFT;
thread->id = version | (slot_num & THREAD_ID_SLOT_MASK);
}
static struct thread_entry * find_empty_thread_slot(void)
{
struct thread_entry *thread = NULL;
int n;
for (n = 0; n < MAXTHREADS; n++)
{
int state = threads[n].state;
if (state == STATE_KILLED)
{
thread = &threads[n];
break;
}
}
return thread;
}
/* Do main thread creation in this file scope to avoid the need to double- /* Do main thread creation in this file scope to avoid the need to double-
return to a prior call-level which would be unaware of the fact setjmp return to a prior call-level which would be unaware of the fact setjmp
was used */ was used */
@ -119,6 +151,8 @@ static int thread_sdl_app_main(void *param)
bool thread_sdl_init(void *param) bool thread_sdl_init(void *param)
{ {
struct thread_entry *thread; struct thread_entry *thread;
int n;
memset(cores, 0, sizeof(cores)); memset(cores, 0, sizeof(cores));
memset(threads, 0, sizeof(threads)); memset(threads, 0, sizeof(threads));
@ -130,6 +164,10 @@ bool thread_sdl_init(void *param)
return false; return false;
} }
/* Initialize all IDs */
for (n = 0; n < MAXTHREADS; n++)
threads[n].id = THREAD_ID_INIT(n);
/* Slot 0 is reserved for the main thread - initialize it here and /* Slot 0 is reserved for the main thread - initialize it here and
then create the SDL thread - it is possible to have a quick, early then create the SDL thread - it is possible to have a quick, early
shutdown try to access the structure. */ shutdown try to access the structure. */
@ -179,23 +217,11 @@ void * thread_sdl_thread_unlock(void)
return current; return current;
} }
static struct thread_entry * find_empty_thread_slot(void) struct thread_entry * thread_id_entry(unsigned int thread_id)
{ {
struct thread_entry *thread = NULL; return (thread_id == THREAD_ID_CURRENT) ?
int n; cores[CURRENT_CORE].running :
&threads[thread_id & THREAD_ID_SLOT_MASK];
for (n = 0; n < MAXTHREADS; n++)
{
int state = threads[n].state;
if (state == STATE_KILLED)
{
thread = &threads[n];
break;
}
}
return thread;
} }
static void add_to_list_l(struct thread_entry **list, static void add_to_list_l(struct thread_entry **list,
@ -239,9 +265,9 @@ static void remove_from_list_l(struct thread_entry **list,
thread->l.next->l.prev = thread->l.prev; thread->l.next->l.prev = thread->l.prev;
} }
struct thread_entry *thread_get_current(void) unsigned int thread_get_current(void)
{ {
return cores[CURRENT_CORE].running; return cores[CURRENT_CORE].running->id;
} }
void switch_thread(void) void switch_thread(void)
@ -389,9 +415,11 @@ unsigned int thread_queue_wake(struct thread_entry **list)
return result; return result;
} }
void thread_thaw(struct thread_entry *thread) void thread_thaw(unsigned int thread_id)
{ {
if (thread->state == STATE_FROZEN) struct thread_entry *thread = thread_id_entry(thread_id);
if (thread->id == thread_id && thread->state == STATE_FROZEN)
{ {
thread->state = STATE_RUNNING; thread->state = STATE_RUNNING;
SDL_SemPost(thread->context.s); SDL_SemPost(thread->context.s);
@ -441,8 +469,8 @@ int runthread(void *data)
return 0; return 0;
} }
struct thread_entry* unsigned int create_thread(void (*function)(void),
create_thread(void (*function)(void), void* stack, size_t stack_size, void* stack, size_t stack_size,
unsigned flags, const char *name) unsigned flags, const char *name)
{ {
struct thread_entry *thread; struct thread_entry *thread;
@ -455,14 +483,14 @@ struct thread_entry*
if (thread == NULL) if (thread == NULL)
{ {
DEBUGF("Failed to find thread slot\n"); DEBUGF("Failed to find thread slot\n");
return NULL; return 0;
} }
s = SDL_CreateSemaphore(0); s = SDL_CreateSemaphore(0);
if (s == NULL) if (s == NULL)
{ {
DEBUGF("Failed to create semaphore\n"); DEBUGF("Failed to create semaphore\n");
return NULL; return 0;
} }
t = SDL_CreateThread(runthread, thread); t = SDL_CreateThread(runthread, thread);
@ -470,7 +498,7 @@ struct thread_entry*
{ {
DEBUGF("Failed to create SDL thread\n"); DEBUGF("Failed to create SDL thread\n");
SDL_DestroySemaphore(s); SDL_DestroySemaphore(s);
return NULL; return 0;
} }
thread->stack = stack; thread->stack = stack;
@ -485,7 +513,7 @@ struct thread_entry*
THREAD_SDL_DEBUGF("New Thread: %d (%s)\n", THREAD_SDL_DEBUGF("New Thread: %d (%s)\n",
thread - threads, THREAD_SDL_GET_NAME(thread)); thread - threads, THREAD_SDL_GET_NAME(thread));
return thread; return thread->id;
} }
void init_threads(void) void init_threads(void)
@ -501,18 +529,22 @@ void init_threads(void)
0, THREAD_SDL_GET_NAME(&threads[0])); 0, THREAD_SDL_GET_NAME(&threads[0]));
} }
void remove_thread(struct thread_entry *thread) #ifndef ALLOW_REMOVE_THREAD
static void remove_thread(unsigned int thread_id)
#else
void remove_thread(unsigned int thread_id)
#endif
{ {
struct thread_entry *current = cores[CURRENT_CORE].running; struct thread_entry *current = cores[CURRENT_CORE].running;
struct thread_entry *thread = thread_id_entry(thread_id);
SDL_Thread *t; SDL_Thread *t;
SDL_sem *s; SDL_sem *s;
int oldlevel = disable_irq_save(); if (thread_id != THREAD_ID_CURRENT && thread->id != thread_id)
return;
if (thread == NULL) int oldlevel = disable_irq_save();
{
thread = current;
}
t = thread->context.t; t = thread->context.t;
s = thread->context.s; s = thread->context.s;
@ -540,6 +572,7 @@ void remove_thread(struct thread_entry *thread)
THREAD_SDL_DEBUGF("Removing thread: %d (%s)\n", THREAD_SDL_DEBUGF("Removing thread: %d (%s)\n",
thread - threads, THREAD_SDL_GET_NAME(thread)); thread - threads, THREAD_SDL_GET_NAME(thread));
new_thread_id(thread->id, thread);
thread->state = STATE_KILLED; thread->state = STATE_KILLED;
thread_queue_wake(&thread->queue); thread_queue_wake(&thread->queue);
@ -559,17 +592,16 @@ void remove_thread(struct thread_entry *thread)
void thread_exit(void) void thread_exit(void)
{ {
remove_thread(NULL); remove_thread(THREAD_ID_CURRENT);
} }
void thread_wait(struct thread_entry *thread) void thread_wait(unsigned int thread_id)
{ {
struct thread_entry *current = cores[CURRENT_CORE].running; struct thread_entry *current = cores[CURRENT_CORE].running;
struct thread_entry *thread = thread_id_entry(thread_id);
if (thread == NULL) if (thread_id == THREAD_ID_CURRENT ||
thread = current; (thread->id == thread_id && thread->state != STATE_KILLED))
if (thread->state != STATE_KILLED)
{ {
current->bqp = &thread->queue; current->bqp = &thread->queue;
block_thread(current); block_thread(current);
@ -583,11 +615,6 @@ int thread_stack_usage(const struct thread_entry *thread)
(void)thread; (void)thread;
} }
unsigned thread_get_status(const struct thread_entry *thread)
{
return thread->state;
}
/* Return name if one or ID if none */ /* Return name if one or ID if none */
void thread_get_name(char *buffer, int size, void thread_get_name(char *buffer, int size,
struct thread_entry *thread) struct thread_entry *thread)