From 8cfbd3604fac14f629244e521ad24ffa9938c790 Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Wed, 10 Dec 2008 08:57:10 +0000 Subject: 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 --- apps/buffering.c | 8 +- apps/codecs.h | 10 +- apps/codecs/mpa.c | 8 +- apps/codecs/spc.c | 12 +- apps/pcmbuf.c | 8 +- apps/playback.c | 16 +-- apps/plugin.c | 6 +- apps/plugin.h | 26 ++-- apps/plugins/alpine_cdc.c | 2 +- apps/plugins/battery_bench.c | 4 +- apps/plugins/mpegplayer/audio_thread.c | 6 +- apps/plugins/mpegplayer/disk_buf.c | 8 +- apps/plugins/mpegplayer/disk_buf.h | 2 +- apps/plugins/mpegplayer/mpeg_parser.c | 2 +- apps/plugins/mpegplayer/stream_mgr.c | 20 +-- apps/plugins/mpegplayer/stream_mgr.h | 2 +- apps/plugins/mpegplayer/stream_thread.h | 2 +- apps/plugins/mpegplayer/video_thread.c | 6 +- apps/plugins/pictureflow.c | 4 +- apps/plugins/test_codec.c | 4 +- apps/plugins/test_sampr.c | 14 +-- apps/recorder/pcm_record.c | 20 +-- apps/voice_thread.c | 10 +- firmware/backlight.c | 10 +- firmware/drivers/ata.c | 15 +-- firmware/export/kernel.h | 2 +- firmware/export/thread.h | 38 +++--- firmware/kernel.c | 23 ++-- .../target/arm/imx31/gigabeat-s/mc13783-imx31.c | 12 +- firmware/thread.c | 140 ++++++++++++++------- firmware/usb.c | 8 +- uisimulator/sdl/thread-sdl.c | 115 ++++++++++------- 32 files changed, 329 insertions(+), 234 deletions(-) diff --git a/apps/buffering.c b/apps/buffering.c index dfc90065d6..6160869498 100644 --- a/apps/buffering.c +++ b/apps/buffering.c @@ -184,7 +184,7 @@ enum { static void buffering_thread(void); static long buffering_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]; 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 queue_sender_list buffering_queue_sender_list; @@ -1468,13 +1468,13 @@ void buffering_init(void) conf_watermark = BUFFERING_DEFAULT_WATERMARK; 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, buffering_thread_name IF_PRIO(, PRIORITY_BUFFERING) IF_COP(, CPU)); queue_enable_queue_send(&buffering_queue, &buffering_queue_sender_list, - buffering_thread_p); + buffering_thread_id); } /* Initialise the buffering subsystem */ @@ -1501,7 +1501,7 @@ bool buffering_reset(char *buf, size_t buflen) high_watermark = 3*buflen / 4; #endif - thread_thaw(buffering_thread_p); + thread_thaw(buffering_thread_id); return true; } diff --git a/apps/codecs.h b/apps/codecs.h index 4194524e6d..d765daba2a 100644 --- a/apps/codecs.h +++ b/apps/codecs.h @@ -82,12 +82,12 @@ #define CODEC_ENC_MAGIC 0x52454E43 /* RENC */ /* 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 backwards compatibility (and please take the opportunity to sort in any 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 */ enum codec_status { @@ -164,14 +164,14 @@ struct codec_api { void (*yield)(void); #if NUM_CORES > 1 - struct thread_entry * + unsigned int (*create_thread)(void (*function)(void), void* stack, size_t stack_size, unsigned flags, const char *name IF_PRIO(, int priority) IF_COP(, unsigned int core)); - void (*thread_thaw)(struct thread_entry *thread); - void (*thread_wait)(struct thread_entry *thread); + void (*thread_thaw)(unsigned int thread_id); + void (*thread_wait)(unsigned int thread_id); void (*semaphore_init)(struct semaphore *s, int max, int start); void (*semaphore_wait)(struct semaphore *s); void (*semaphore_release)(struct semaphore *s); diff --git a/apps/codecs/mpa.c b/apps/codecs/mpa.c index 7732622383..37a1afadfa 100644 --- a/apps/codecs/mpa.c +++ b/apps/codecs/mpa.c @@ -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 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) @@ -249,14 +249,14 @@ static bool mad_synth_thread_create(void) ci->semaphore_init(&synth_done_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, sizeof(mad_synth_thread_stack), 0, mad_synth_thread_name IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, COP)); - if (mad_synth_thread_p == NULL) + if (mad_synth_thread_id == 0) return false; return true; @@ -267,7 +267,7 @@ static void mad_synth_thread_quit(void) /*mop up COP thread*/ die=1; ci->semaphore_release(&synth_pending_sem); - ci->thread_wait(mad_synth_thread_p); + ci->thread_wait(mad_synth_thread_id); invalidate_icache(); } #else diff --git a/apps/codecs/spc.c b/apps/codecs/spc.c index 380cfbdb8b..14d28dfca8 100644 --- a/apps/codecs/spc.c +++ b/apps/codecs/spc.c @@ -197,7 +197,7 @@ static int spc_emu_thread_stack[DEFAULT_STACK_SIZE/sizeof(int)] CACHEALIGN_ATTR; 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 { @@ -352,11 +352,11 @@ static void spc_emu_thread(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, spc_emu_thread_name IF_PRIO(, PRIORITY_PLAYBACK), COP); - if (emu_thread_p == NULL) + if (emu_thread_id == 0) return false; /* 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; /* Start it running */ - ci->thread_thaw(emu_thread_p); + ci->thread_thaw(emu_thread_id); 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) { - if (emu_thread_p != NULL) { + if (emu_thread_id != 0) { emu_thread_send_msg(SPC_EMU_QUIT, 0); /* Wait for emu thread to be killed */ - ci->thread_wait(emu_thread_p); + ci->thread_wait(emu_thread_id); invalidate_icache(); } } diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c index c7db4d3101..9ca5fbf5cf 100644 --- a/apps/pcmbuf.c +++ b/apps/pcmbuf.c @@ -115,7 +115,7 @@ static bool pcmbuf_flush; static int codec_thread_priority = PRIORITY_PLAYBACK; #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 * static variable names */ @@ -258,13 +258,13 @@ static void boost_codec_thread(bool boost) if (priority != codec_thread_priority) { codec_thread_priority = priority; - thread_set_priority(codec_thread_p, priority); + thread_set_priority(codec_thread_id, priority); voice_thread_set_priority(priority); } } 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); 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 a clip */ #ifndef SIMULATOR - if (thread_get_current() == codec_thread_p) + if (thread_get_current() == codec_thread_id) #endif /* SIMULATOR */ { #ifdef HAVE_PRIORITY_SCHEDULING diff --git a/apps/playback.c b/apps/playback.c index 50c4017200..3aed12e918 100644 --- a/apps/playback.c +++ b/apps/playback.c @@ -299,7 +299,7 @@ static struct queue_sender_list codec_queue_sender_list; static long codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)] IBSS_ATTR; 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 */ static struct event_queue pcmbuf_queue SHAREDBSS_ATTR; @@ -2499,7 +2499,7 @@ static void audio_thread(void) */ void audio_init(void) { - struct thread_entry *audio_thread_p; + unsigned int audio_thread_id; /* Can never do this twice */ if (audio_is_initialized) @@ -2543,22 +2543,22 @@ void audio_init(void) talk first */ talk_init(); - codec_thread_p = create_thread( + codec_thread_id = create_thread( codec_thread, codec_stack, sizeof(codec_stack), CREATE_THREAD_FROZEN, codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU)); 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, audio_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU)); queue_enable_queue_send(&audio_queue, &audio_queue_sender_list, - audio_thread_p); + audio_thread_id); #ifdef PLAYBACK_VOICE voice_thread_init(); @@ -2599,8 +2599,8 @@ void audio_init(void) #ifdef PLAYBACK_VOICE voice_thread_resume(); #endif - thread_thaw(codec_thread_p); - thread_thaw(audio_thread_p); + thread_thaw(codec_thread_id); + thread_thaw(audio_thread_id); } /* audio_init */ diff --git a/apps/plugin.c b/apps/plugin.c index de2dd3f7c7..e55ecd46a7 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -146,7 +146,8 @@ static const struct plugin_api rockbox_api = { font_get_width, screen_clear_area, gui_scrollbar_draw, -#endif +#endif /* HAVE_LCD_BITMAP */ + get_codepage_name, backlight_on, backlight_off, @@ -482,6 +483,7 @@ static const struct plugin_api rockbox_api = { &statusbars, gui_syncstatusbar_draw, /* options */ + get_settings_list, find_setting, option_screen, set_option, @@ -619,8 +621,6 @@ static const struct plugin_api rockbox_api = { appsversion, /* new stuff at the end, sort into place next time the API gets incompatible */ - get_settings_list, - get_codepage_name, }; int plugin_load(const char* plugin, const void* parameter) diff --git a/apps/plugin.h b/apps/plugin.h index fd01e15bbd..e91c866098 100644 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -7,7 +7,7 @@ * \/ \/ \/ \/ \/ * $Id$ * - * Copyright (C) 2002 Björn Stenberg + * Copyright (C) 2002 Björn Stenberg * * This program is free software; you can redistribute it and/or * 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 */ /* 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 backwards compatibility (and please take the opportunity to sort in any 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 */ enum plugin_status { @@ -244,6 +244,7 @@ struct plugin_api { int min_shown, int max_shown, unsigned flags); #endif /* HAVE_LCD_BITMAP */ + const char* (*get_codepage_name)(int cp); /* backlight */ /* 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_ex)(long event, void (*callback)(void *), void *parameter); struct thread_entry* threads; - struct thread_entry* (*create_thread)(void (*function)(void), void* stack, - size_t stack_size, unsigned flags, - const char *name - IF_PRIO(, int priority) - IF_COP(, unsigned int core)); + unsigned int (*create_thread)(void (*function)(void), void* stack, + size_t stack_size, unsigned flags, + const char *name + IF_PRIO(, int priority) + IF_COP(, unsigned int core)); void (*thread_exit)(void); - void (*thread_wait)(struct thread_entry *thread); + void (*thread_wait)(unsigned int thread_id); #if CONFIG_CODEC == SWCODEC void (*mutex_init)(struct mutex *m); void (*mutex_lock)(struct mutex *m); @@ -456,7 +457,7 @@ struct plugin_api { #if CONFIG_CODEC == SWCODEC void (*queue_enable_queue_send)(struct event_queue *q, struct queue_sender_list *send, - struct thread_entry *owner); + unsigned int thread_id); bool (*queue_empty)(const struct event_queue *q); void (*queue_wait)(struct event_queue *q, struct queue_event *ev); 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); /* options */ + const struct settings_list* (*get_settings_list)(int*count); const struct settings_list* (*find_setting)(const void* variable, int *id); bool (*option_screen)(const struct settings_list *setting, struct viewport parent[NB_SCREENS], @@ -771,7 +773,7 @@ struct plugin_api { char *buf, int buflen); #endif - void (*thread_thaw)(struct thread_entry *thread); + void (*thread_thaw)(unsigned int thread_id); #ifdef HAVE_SEMAPHORE_OBJECTS void (*semaphore_init)(struct semaphore *s, int max, int start); @@ -782,8 +784,6 @@ struct plugin_api { const char *appsversion; /* new stuff at the end, sort into place next time the API gets incompatible */ - const struct settings_list* (*get_settings_list)(int*count); - const char* (*get_codepage_name)(int cp); }; /* plugin header */ diff --git a/apps/plugins/alpine_cdc.c b/apps/plugins/alpine_cdc.c index dfffc3b3cd..d15e26ae36 100644 --- a/apps/plugins/alpine_cdc.c +++ b/apps/plugins/alpine_cdc.c @@ -206,7 +206,7 @@ struct { bool foreground; /* set as long as we're owning the UI */ 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; static const struct plugin_api* rb; /* here is the global API struct pointer */ diff --git a/apps/plugins/battery_bench.c b/apps/plugins/battery_bench.c index b951b01432..0c30ebabc3 100644 --- a/apps/plugins/battery_bench.c +++ b/apps/plugins/battery_bench.c @@ -216,7 +216,7 @@ 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 bool in_usb_mode; static unsigned int buf_idx; @@ -537,7 +537,7 @@ int main(void) if ((thread_id = rb->create_thread(thread, thread_stack, sizeof(thread_stack), 0, "Battery Benchmark" IF_PRIO(, PRIORITY_BACKGROUND) - IF_COP(, CPU))) == NULL) + IF_COP(, CPU))) == 0) { rb->splash(HZ, "Cannot create thread!"); return PLUGIN_ERROR; diff --git a/apps/plugins/mpegplayer/audio_thread.c b/apps/plugins/mpegplayer/audio_thread.c index 45226575c9..2fb46efd56 100644 --- a/apps/plugins/mpegplayer/audio_thread.c +++ b/apps/plugins/mpegplayer/audio_thread.c @@ -732,7 +732,7 @@ bool audio_thread_init(void) rb->queue_enable_queue_send(audio_str.hdr.q, &audio_str_queue_send, audio_str.thread); - if (audio_str.thread == NULL) + if (audio_str.thread == 0) return false; /* Wait for thread to initialize */ @@ -744,11 +744,11 @@ bool audio_thread_init(void) /* Stops the audio thread */ void audio_thread_exit(void) { - if (audio_str.thread != NULL) + if (audio_str.thread != 0) { str_post_msg(&audio_str, STREAM_QUIT, 0); rb->thread_wait(audio_str.thread); - audio_str.thread = NULL; + audio_str.thread = 0; } #ifndef SIMULATOR diff --git a/apps/plugins/mpegplayer/disk_buf.c b/apps/plugins/mpegplayer/disk_buf.c index df5e005b50..c008139356 100644 --- a/apps/plugins/mpegplayer/disk_buf.c +++ b/apps/plugins/mpegplayer/disk_buf.c @@ -835,7 +835,7 @@ void disk_buf_reply_msg(intptr_t retval) bool disk_buf_init(void) { - disk_buf.thread = NULL; + disk_buf.thread = 0; list_initialize(&nf_list); 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, disk_buf.thread); - if (disk_buf.thread == NULL) + if (disk_buf.thread == 0) return false; /* Wait for thread to initialize */ @@ -904,10 +904,10 @@ bool disk_buf_init(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->thread_wait(disk_buf.thread); - disk_buf.thread = NULL; + disk_buf.thread = 0; } } diff --git a/apps/plugins/mpegplayer/disk_buf.h b/apps/plugins/mpegplayer/disk_buf.h index b6399c81d1..e16939a92e 100644 --- a/apps/plugins/mpegplayer/disk_buf.h +++ b/apps/plugins/mpegplayer/disk_buf.h @@ -62,7 +62,7 @@ struct dbuf_range * playback events as well as buffering */ struct disk_buf { - struct thread_entry *thread; + unsigned int thread; struct event_queue *q; uint8_t *start; /* Start pointer */ uint8_t *end; /* End of buffer pointer less MPEG_GUARDBUF_SIZE. The diff --git a/apps/plugins/mpegplayer/mpeg_parser.c b/apps/plugins/mpegplayer/mpeg_parser.c index 54a6f23d92..42c388b375 100644 --- a/apps/plugins/mpegplayer/mpeg_parser.c +++ b/apps/plugins/mpegplayer/mpeg_parser.c @@ -1027,7 +1027,7 @@ intptr_t parser_send_video_msg(long id, intptr_t data) { 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 * behind the scenes */ diff --git a/apps/plugins/mpegplayer/stream_mgr.c b/apps/plugins/mpegplayer/stream_mgr.c index 424d2fe503..222ffb7d6b 100644 --- a/apps/plugins/mpegplayer/stream_mgr.c +++ b/apps/plugins/mpegplayer/stream_mgr.c @@ -908,7 +908,7 @@ static void stream_mgr_thread(void) /* Opens a new file */ 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_ERROR; } @@ -916,7 +916,7 @@ int stream_open(const char *filename) /* Plays the current file starting at time 'start' */ int stream_play(void) { - if (stream_mgr.thread != NULL) + if (stream_mgr.thread != 0) return stream_mgr_send_msg(STREAM_PLAY, 0); return STREAM_ERROR; } @@ -924,7 +924,7 @@ int stream_play(void) /* Pauses playback if playing */ int stream_pause(void) { - if (stream_mgr.thread != NULL) + if (stream_mgr.thread != 0) return stream_mgr_send_msg(STREAM_PAUSE, false); return STREAM_ERROR; } @@ -932,7 +932,7 @@ int stream_pause(void) /* Resumes playback if paused */ int stream_resume(void) { - if (stream_mgr.thread != NULL) + if (stream_mgr.thread != 0) return stream_mgr_send_msg(STREAM_PAUSE, true); return STREAM_ERROR; } @@ -940,7 +940,7 @@ int stream_resume(void) /* Stops playback if not stopped */ int stream_stop(void) { - if (stream_mgr.thread != NULL) + if (stream_mgr.thread != 0) return stream_mgr_send_msg(STREAM_STOP, 0); return STREAM_ERROR; } @@ -950,7 +950,7 @@ int stream_seek(uint32_t time, int whence) { int ret; - if (stream_mgr.thread == NULL) + if (stream_mgr.thread == 0) return STREAM_ERROR; stream_mgr_lock(); @@ -968,7 +968,7 @@ int stream_seek(uint32_t time, int whence) /* Closes the current file */ int stream_close(void) { - if (stream_mgr.thread != NULL) + if (stream_mgr.thread != 0) return stream_mgr_send_msg(STREAM_CLOSE, 0); return STREAM_ERROR; } @@ -1018,7 +1018,7 @@ int stream_init(void) rb->queue_enable_queue_send(stream_mgr.q, &stream_mgr_queue_send, stream_mgr.thread); - if (stream_mgr.thread == NULL) + if (stream_mgr.thread == 0) { rb->splash(HZ, "Could not create stream manager thread!"); return STREAM_ERROR; @@ -1073,11 +1073,11 @@ void stream_exit(void) disk_buf_exit(); pcm_output_exit(); - if (stream_mgr.thread != NULL) + if (stream_mgr.thread != 0) { stream_mgr_post_msg(STREAM_QUIT, 0); rb->thread_wait(stream_mgr.thread); - stream_mgr.thread = NULL; + stream_mgr.thread = 0; } #ifndef HAVE_LCD_COLOR diff --git a/apps/plugins/mpegplayer/stream_mgr.h b/apps/plugins/mpegplayer/stream_mgr.h index e3ea9207e6..a00b39f189 100644 --- a/apps/plugins/mpegplayer/stream_mgr.h +++ b/apps/plugins/mpegplayer/stream_mgr.h @@ -27,7 +27,7 @@ * coordination with assistance from the parser */ 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 */ const char *filename; /* Current filename */ uint32_t resume_time; /* The stream tick where playback was diff --git a/apps/plugins/mpegplayer/stream_thread.h b/apps/plugins/mpegplayer/stream_thread.h index d6e42d274f..30bf46e6ff 100644 --- a/apps/plugins/mpegplayer/stream_thread.h +++ b/apps/plugins/mpegplayer/stream_thread.h @@ -45,7 +45,7 @@ struct stream_hdr struct stream { 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_end; /* Current stream packet end */ struct list_item l; /* List of streams - either reserve pool diff --git a/apps/plugins/mpegplayer/video_thread.c b/apps/plugins/mpegplayer/video_thread.c index 100904b01b..8b84686a3b 100644 --- a/apps/plugins/mpegplayer/video_thread.c +++ b/apps/plugins/mpegplayer/video_thread.c @@ -1009,7 +1009,7 @@ bool video_thread_init(void) rb->queue_enable_queue_send(video_str.hdr.q, &video_str_queue_send, video_str.thread); - if (video_str.thread == NULL) + if (video_str.thread == 0) return false; /* Wait for thread to initialize */ @@ -1022,11 +1022,11 @@ bool video_thread_init(void) /* Terminates the video thread */ void video_thread_exit(void) { - if (video_str.thread != NULL) + if (video_str.thread != 0) { str_post_msg(&video_str, STREAM_QUIT, 0); rb->thread_wait(video_str.thread); IF_COP(invalidate_icache()); - video_str.thread = NULL; + video_str.thread = 0; } } diff --git a/apps/plugins/pictureflow.c b/apps/plugins/pictureflow.c index 29e8a749d5..232c3f6bc4 100644 --- a/apps/plugins/pictureflow.c +++ b/apps/plugins/pictureflow.c @@ -218,7 +218,7 @@ struct mutex slide_cache_stack_lock; static int empty_slide_hid; -struct thread_entry *thread_id; +unsigned int thread_id; struct event_queue thread_q; static char tmp_path_name[MAX_PATH]; @@ -831,7 +831,7 @@ bool create_pf_thread(void) IF_PRIO(, PRIORITY_BACKGROUND) IF_COP(, CPU) ) - ) == NULL) { + ) == 0) { return false; } thread_is_running = true; diff --git a/apps/plugins/test_codec.c b/apps/plugins/test_codec.c index b1f5aff385..17effd8dfd 100644 --- a/apps/plugins/test_codec.c +++ b/apps/plugins/test_codec.c @@ -525,7 +525,7 @@ static enum plugin_status test_track(const char* filename) long ticks; unsigned long speed; unsigned long duration; - struct thread_entry* codecthread_id; + unsigned int codecthread_id; const char* ch; /* 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, 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); goto exit; diff --git a/apps/plugins/test_sampr.c b/apps/plugins/test_sampr.c index 77f9b8a779..1131a7a989 100644 --- a/apps/plugins/test_sampr.c +++ b/apps/plugins/test_sampr.c @@ -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 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_MASK (OUTPUT_CHUNK_COUNT-1) @@ -233,11 +233,11 @@ static void play_tone(bool volume_set) output_clear(); update_gen_step(); - gen_thread_p = rb->create_thread(gen_thread_func, gen_thread_stack, - sizeof(gen_thread_stack), 0, - "test_sampr generator" - IF_PRIO(, PRIORITY_PLAYBACK) - IF_COP(, CPU)); + gen_thread_id = rb->create_thread(gen_thread_func, gen_thread_stack, + sizeof(gen_thread_stack), 0, + "test_sampr generator" + IF_PRIO(, PRIORITY_PLAYBACK) + IF_COP(, CPU)); rb->pcm_play_data(get_more, NULL, 0); @@ -260,7 +260,7 @@ static void play_tone(bool volume_set) gen_quit = true; - rb->thread_wait(gen_thread_p); + rb->thread_wait(gen_thread_id); rb->pcm_play_stop(); diff --git a/apps/recorder/pcm_record.c b/apps/recorder/pcm_record.c index dbbc6901ec..9ceb68c796 100644 --- a/apps/recorder/pcm_record.c +++ b/apps/recorder/pcm_record.c @@ -37,7 +37,7 @@ /***************************************************************************/ -extern struct thread_entry *codec_thread_p; +extern uintptr_t codec_thread_id; /** General recording state **/ 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 long pcmrec_stack[3*DEFAULT_STACK_SIZE/sizeof(long)]; 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); @@ -365,12 +365,12 @@ unsigned long pcm_rec_sample_rate(void) void pcm_rec_init(void) { queue_init(&pcmrec_queue, true); - pcmrec_thread_p = + pcmrec_thread_id = create_thread(pcmrec_thread, pcmrec_stack, sizeof(pcmrec_stack), 0, pcmrec_thread_name IF_PRIO(, PRIORITY_RECORDING) IF_COP(, CPU)); queue_enable_queue_send(&pcmrec_queue, &pcmrec_queue_send, - pcmrec_thread_p); + pcmrec_thread_id); } /* pcm_rec_init */ /** audio_* group **/ @@ -878,10 +878,10 @@ static void pcmrec_flush(unsigned flush_num) priority until finished */ logf("pcmrec: boost (%s)", num >= flood_watermark ? "num" : "time"); - prio_pcmrec = thread_set_priority(NULL, - thread_get_priority(NULL) - 4); - prio_codec = thread_set_priority(codec_thread_p, - thread_get_priority(codec_thread_p) - 4); + prio_pcmrec = thread_set_priority(THREAD_ID_CURRENT, + thread_get_priority(THREAD_ID_CURRENT) - 4); + prio_codec = thread_set_priority(codec_thread_id, + thread_get_priority(codec_thread_id) - 4); } #endif @@ -931,8 +931,8 @@ static void pcmrec_flush(unsigned flush_num) { /* return to original priorities */ logf("pcmrec: unboost priority"); - thread_set_priority(NULL, prio_pcmrec); - thread_set_priority(codec_thread_p, prio_codec); + thread_set_priority(THREAD_ID_CURRENT, prio_pcmrec); + thread_set_priority(codec_thread_id, prio_codec); } last_flush_tick = current_tick; /* save tick when we left */ diff --git a/apps/voice_thread.c b/apps/voice_thread.c index 084c3872c6..86e80cece3 100644 --- a/apps/voice_thread.c +++ b/apps/voice_thread.c @@ -54,7 +54,7 @@ #define VOICE_SAMPLE_DEPTH 16 /* Sample depth in bits */ /* 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 const char voice_thread_name[] = "voice"; @@ -434,25 +434,25 @@ void voice_thread_init(void) queue_init(&voice_queue, false); 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, voice_thread_name IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU)); queue_enable_queue_send(&voice_queue, &voice_queue_sender_list, - voice_thread_p); + voice_thread_id); } /* voice_thread_init */ /* Unfreeze the voice thread */ void voice_thread_resume(void) { logf("Thawing voice thread"); - thread_thaw(voice_thread_p); + thread_thaw(voice_thread_id); } #ifdef HAVE_PRIORITY_SCHEDULING /* Set the voice thread priority */ void voice_thread_set_priority(int priority) { - thread_set_priority(voice_thread_p, priority); + thread_set_priority(voice_thread_id, priority); } #endif diff --git a/firmware/backlight.c b/firmware/backlight.c index 07cc9532be..66cc6df569 100644 --- a/firmware/backlight.c +++ b/firmware/backlight.c @@ -130,7 +130,7 @@ static long backlight_stack[DEFAULT_STACK_SIZE/sizeof(long)]; static const char backlight_thread_name[] = "backlight"; static struct event_queue backlight_queue; #ifdef BACKLIGHT_DRIVER_CLOSE -static struct thread_entry *backlight_thread_p = NULL; +static unsigned int backlight_thread_id = 0; #endif static int backlight_timer SHAREDBSS_ATTR; @@ -744,7 +744,7 @@ void backlight_init(void) * call the appropriate backlight_set_*() functions, only changing light * status if necessary. */ #ifdef BACKLIGHT_DRIVER_CLOSE - backlight_thread_p = + backlight_thread_id = #endif create_thread(backlight_thread, backlight_stack, sizeof(backlight_stack), 0, backlight_thread_name @@ -756,13 +756,13 @@ void backlight_init(void) #ifdef BACKLIGHT_DRIVER_CLOSE void backlight_close(void) { - struct thread_entry *thread = backlight_thread_p; + unsigned int thread = backlight_thread_id; /* Wait for thread to exit */ - if (thread == NULL) + if (thread == 0) return; - backlight_thread_p = NULL; + backlight_thread_id = 0; queue_post(&backlight_queue, BACKLIGHT_QUIT, 0); thread_wait(thread); diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c index 00a7c3e19a..e3fa3e8958 100644 --- a/firmware/drivers/ata.c +++ b/firmware/drivers/ata.c @@ -71,7 +71,7 @@ #endif #ifdef ATA_DRIVER_CLOSE -static struct thread_entry *ata_thread_p = NULL; +static unsigned int ata_thread_id = 0; #endif #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) { - struct thread_entry * const current = thread_get_current(); + struct thread_entry * const current = + thread_id_entry(THREAD_ID_CURRENT); if (current == l->thread) { @@ -1350,7 +1351,7 @@ int ata_init(void) last_disk_activity = current_tick; #ifdef ATA_DRIVER_CLOSE - ata_thread_p = + ata_thread_id = #endif create_thread(ata_thread, ata_stack, sizeof(ata_stack), 0, ata_thread_name @@ -1370,15 +1371,15 @@ int ata_init(void) #ifdef ATA_DRIVER_CLOSE 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; - ata_thread_p = NULL; + ata_thread_id = 0; queue_post(&ata_queue, Q_CLOSE, 0); - thread_wait(thread); + thread_wait(thread_id); } #endif /* ATA_DRIVER_CLOSE */ diff --git a/firmware/export/kernel.h b/firmware/export/kernel.h index beba58eb21..ef65463e5d 100644 --- a/firmware/export/kernel.h +++ b/firmware/export/kernel.h @@ -261,7 +261,7 @@ extern void queue_post(struct event_queue *q, long id, intptr_t data); #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME extern void queue_enable_queue_send(struct event_queue *q, 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 void queue_reply(struct event_queue *q, intptr_t retval); extern bool queue_in_queue_send(struct event_queue *q); diff --git a/firmware/export/thread.h b/firmware/export/thread.h index c4dfbf4ed3..4c1e952347 100644 --- a/firmware/export/thread.h +++ b/firmware/export/thread.h @@ -58,9 +58,6 @@ #define NUM_PRIORITIES 32 #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 #ifdef HAVE_RECORDING @@ -280,6 +277,7 @@ struct thread_entry int skip_count; /* Number of times skipped if higher priority thread was running */ #endif + uint16_t id; /* Current slot id */ unsigned short stack_size; /* Size of stack in bytes */ #ifdef HAVE_PRIORITY_SCHEDULING unsigned char base_priority; /* Base priority (set explicitly during @@ -298,6 +296,16 @@ struct thread_entry #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 /* Operations to be performed just before stopping a thread and starting a new one if specified before calling switch_thread */ @@ -475,11 +483,11 @@ void init_threads(void); /* Allocate a thread in the scheduler */ #define CREATE_THREAD_FROZEN 0x00000001 /* Thread is frozen at create time */ -struct thread_entry* - create_thread(void (*function)(void), void* stack, size_t stack_size, - unsigned flags, const char *name - IF_PRIO(, int priority) - IF_COP(, unsigned int core)); +unsigned int create_thread(void (*function)(void), + void* stack, size_t stack_size, + unsigned flags, const char *name + IF_PRIO(, int priority) + IF_COP(, unsigned int core)); /* Set and clear the CPU frequency boost flag for the calling thread */ #ifdef HAVE_SCHEDULER_BOOSTCTRL @@ -489,17 +497,19 @@ void cancel_cpu_boost(void); #define trigger_cpu_boost() #define cancel_cpu_boost() #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). * 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 */ -void thread_wait(struct thread_entry *thread); +void thread_wait(unsigned int thread_id); /* Exit the current thread */ void thread_exit(void); #if defined(DEBUG) || defined(ROCKBOX_HAS_LOGF) #define ALLOW_REMOVE_THREAD /* Remove a thread from the scheduler */ -void remove_thread(struct thread_entry *thread); +void remove_thread(unsigned int thread_id); #endif /* 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); #ifdef HAVE_PRIORITY_SCHEDULING -int thread_set_priority(struct thread_entry *thread, int priority); -int thread_get_priority(struct thread_entry *thread); +int thread_set_priority(unsigned int thread_id, int priority); +int thread_get_priority(unsigned int thread_id); #endif /* HAVE_PRIORITY_SCHEDULING */ #if NUM_CORES > 1 unsigned int switch_core(unsigned int new_core); #endif -struct thread_entry * thread_get_current(void); +unsigned int thread_get_current(void); /* Debugging info - only! */ int thread_stack_usage(const struct thread_entry *thread); diff --git a/firmware/kernel.c b/firmware/kernel.c index 920893818a..553f6721a1 100644 --- a/firmware/kernel.c +++ b/firmware/kernel.c @@ -352,11 +352,12 @@ static void queue_remove_sender_thread_cb(struct thread_entry *thread) * specified for priority inheritance to operate. * * 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, struct queue_sender_list *send, - struct thread_entry *owner) + unsigned int owner_id) { int oldlevel = disable_irq_save(); corelock_lock(&q->cl); @@ -367,9 +368,11 @@ void queue_enable_queue_send(struct event_queue *q, #ifdef HAVE_PRIORITY_SCHEDULING send->blocker.wakeup_protocol = wakeup_priority_protocol_release; send->blocker.priority = PRIORITY_IDLE; - send->blocker.thread = owner; - if(owner != NULL) + if(owner_id != 0) + { + send->blocker.thread = thread_id_entry(owner_id); q->blocker_p = &send->blocker; + } #endif q->send = send; } @@ -377,7 +380,7 @@ void queue_enable_queue_send(struct event_queue *q, corelock_unlock(&q->cl); restore_irq(oldlevel); - (void)owner; + (void)owner_id; } /* 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 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"); #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 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"); #endif @@ -914,10 +917,10 @@ void mutex_lock(struct mutex *m) void mutex_unlock(struct mutex *m) { /* 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_GET_THREAD(m)->name, - thread_get_current()->name); + cores[CURRENT_CORE].running->name); if(m->count > 0) { @@ -990,7 +993,7 @@ void spinlock_lock(struct spinlock *l) void spinlock_unlock(struct spinlock *l) { /* 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"); if(l->count > 0) diff --git a/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c b/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c index c185994bfc..81849d0852 100644 --- a/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c @@ -69,7 +69,7 @@ static const unsigned char pmic_ints_regs[2] = #ifdef PMIC_DRIVER_CLOSE static bool pmic_close = false; -static struct thread_entry *mc13783_thread_p = NULL; +static unsigned int mc13783_thread_id = 0; #endif static void mc13783_interrupt_thread(void) @@ -149,7 +149,7 @@ void mc13783_init(void) MC13783_GPIO_ISR = (1ul << MC13783_GPIO_LINE); #ifdef PMIC_DRIVER_CLOSE - mc13783_thread_p = + mc13783_thread_id = #endif create_thread(mc13783_interrupt_thread, mc13783_thread_stack, sizeof(mc13783_thread_stack), 0, @@ -159,16 +159,16 @@ void mc13783_init(void) #ifdef PMIC_DRIVER_CLOSE 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; - mc13783_thread_p = NULL; + mc13783_thread_id = 0; pmic_close = true; wakeup_signal(&mc13783_wake); - thread_wait(thread); + thread_wait(thread_id); } #endif /* PMIC_DRIVER_CLOSE */ diff --git a/firmware/thread.c b/firmware/thread.c index c500fc4818..377c3355b4 100644 --- a/firmware/thread.c +++ b/firmware/thread.c @@ -1691,8 +1691,8 @@ struct thread_entry * struct thread_entry *next; int bl_pr; - THREAD_ASSERT(thread_get_current() == bl_t, - "UPPT->wrong thread", thread_get_current()); + THREAD_ASSERT(cores[CURRENT_CORE].running == bl_t, + "UPPT->wrong thread", cores[CURRENT_CORE].running); LOCK_THREAD(bl_t); @@ -2031,7 +2031,7 @@ void switch_thread(void) } #ifdef RB_PROFILE - profile_thread_stopped(thread - threads); + profile_thread_stopped(thread->id & THREAD_ID_SLOT_MASK); #endif /* Begin task switching by saving our current context so that we can @@ -2136,7 +2136,7 @@ void switch_thread(void) load_context(&thread->context); #ifdef RB_PROFILE - profile_thread_started(thread - threads); + profile_thread_started(thread->id & THREAD_ID_SLOT_MASK); #endif } @@ -2315,6 +2315,24 @@ unsigned int thread_queue_wake(struct thread_entry **list) 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 * will be locked on multicore. @@ -2349,6 +2367,17 @@ static struct thread_entry * find_empty_thread_slot(void) 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 @@ -2369,11 +2398,11 @@ void core_idle(void) * Return ID if context area could be allocated, else NULL. *--------------------------------------------------------------------------- */ -struct thread_entry* - create_thread(void (*function)(void), void* stack, size_t stack_size, - unsigned flags, const char *name - IF_PRIO(, int priority) - IF_COP(, unsigned int core)) +unsigned int create_thread(void (*function)(void), + void* stack, size_t stack_size, + unsigned flags, const char *name + IF_PRIO(, int priority) + IF_COP(, unsigned int core)) { unsigned int i; unsigned int stack_words; @@ -2385,7 +2414,7 @@ struct thread_entry* thread = find_empty_thread_slot(); if (thread == NULL) { - return NULL; + return 0; } oldlevel = disable_irq_save(); @@ -2443,15 +2472,15 @@ struct thread_entry* THREAD_STARTUP_INIT(core, thread, function); thread->state = state; + i = thread->id; /* Snapshot while locked */ if (state == STATE_RUNNING) core_schedule_wakeup(thread); UNLOCK_THREAD(thread); - restore_irq(oldlevel); - return thread; + return i; } #ifdef HAVE_SCHEDULER_BOOSTCTRL @@ -2489,18 +2518,17 @@ void cancel_cpu_boost(void) * 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; - - if (thread == NULL) - thread = current; + struct thread_entry *thread = thread_id_entry(thread_id); /* Lock thread-as-waitable-object lock */ corelock_lock(&thread->waiter_cl); /* 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; ) current->bqp = &thread->queue; @@ -2538,9 +2566,10 @@ void thread_exit(void) if (current->name == THREAD_DESTRUCT) { /* Thread being killed - become a waiter */ + unsigned int id = current->id; UNLOCK_THREAD(current); corelock_unlock(¤t->waiter_cl); - thread_wait(current); + thread_wait(id); THREAD_PANICF("thread_exit->WK:*R", current); } #endif @@ -2568,7 +2597,13 @@ void thread_exit(void) } flush_icache(); + + /* At this point, this thread isn't using resources allocated for + * execution except the slot itself. */ #endif + + /* Update ID for this slot */ + new_thread_id(current->id, current); current->name = NULL; /* Signal this thread */ @@ -2593,7 +2628,7 @@ void thread_exit(void) * 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 /* 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; #endif struct thread_entry *current = cores[core].running; + struct thread_entry *thread = thread_id_entry(thread_id); unsigned state; int oldlevel; - if (thread == NULL) - thread = current; - if (thread == current) thread_exit(); /* Current thread - do normal exit */ @@ -2621,10 +2654,8 @@ void remove_thread(struct thread_entry *thread) state = thread->state; - if (state == STATE_KILLED) - { + if (thread->id != thread_id || state == STATE_KILLED) goto thread_killed; - } #if NUM_CORES > 1 if (thread->name == THREAD_DESTRUCT) @@ -2633,7 +2664,7 @@ void remove_thread(struct thread_entry *thread) UNLOCK_THREAD(thread); corelock_unlock(&thread->waiter_cl); restore_irq(oldlevel); - thread_wait(thread); + thread_wait(thread_id); return; } @@ -2741,6 +2772,7 @@ IF_COP( retry_state: ) /* Otherwise thread is frozen and hasn't run yet */ } + new_thread_id(thread_id, thread); thread->state = STATE_KILLED; /* 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. *--------------------------------------------------------------------------- */ -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; + struct thread_entry *thread = thread_id_entry(thread_id); /* A little safety measure */ if (priority < HIGHEST_PRIORITY || priority > LOWEST_PRIORITY) return -1; - if (thread == NULL) - thread = cores[CURRENT_CORE].running; - /* Thread could be on any list and therefore on an interrupt accessible one - disable interrupts */ int oldlevel = disable_irq_save(); @@ -2791,7 +2821,8 @@ int thread_set_priority(struct thread_entry *thread, int priority) LOCK_THREAD(thread); /* 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; @@ -2908,13 +2939,19 @@ int thread_set_priority(struct thread_entry *thread, int priority) * 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. */ - if (thread == NULL) - thread = cores[CURRENT_CORE].running; + struct thread_entry *thread = thread_id_entry(thread_id); + int base_priority = thread->base_priority; - 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 */ @@ -2924,12 +2961,16 @@ int thread_get_priority(struct thread_entry *thread) * 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(); + 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); UNLOCK_THREAD(thread); @@ -2940,9 +2981,9 @@ void thread_thaw(struct thread_entry *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 @@ -2967,9 +3008,10 @@ unsigned int switch_core(unsigned int new_core) if (current->name == THREAD_DESTRUCT) { /* Thread being killed - deactivate and let process complete */ + unsigned int id = current->id; UNLOCK_THREAD(current); restore_irq(oldlevel); - thread_wait(current); + thread_wait(id); /* Should never be reached */ THREAD_PANICF("switch_core->D:*R", current); } @@ -3034,6 +3076,19 @@ void init_threads(void) const unsigned int core = CURRENT_CORE; 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 */ thread = find_empty_thread_slot(); @@ -3060,8 +3115,6 @@ void init_threads(void) thread->priority = PRIORITY_USER_INTERFACE; rtr_add_entry(core, PRIORITY_USER_INTERFACE); #endif - corelock_init(&thread->waiter_cl); - corelock_init(&thread->slot_cl); add_to_list_l(&cores[core].running, thread); @@ -3070,6 +3123,7 @@ void init_threads(void) thread->stack = 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 */ + /* Initialize all locking for the slots */ /* Wait for other processors to finish their inits since create_thread * 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. */ diff --git a/firmware/usb.c b/firmware/usb.c index f9bfbc4dbf..2bff53e5d6 100644 --- a/firmware/usb.c +++ b/firmware/usb.c @@ -78,7 +78,7 @@ static int usb_mmc_countdown = 0; #ifdef USB_FULL_INIT static long usb_stack[(DEFAULT_STACK_SIZE + 0x800)/sizeof(long)]; static const char usb_thread_name[] = "usb"; -static struct thread_entry *usb_thread_entry; +static unsigned int usb_thread_entry = 0; #endif static struct event_queue usb_queue; static int last_usb_status; @@ -539,10 +539,10 @@ void usb_start_monitoring(void) #ifdef USB_DRIVER_CLOSE void usb_close(void) { - struct thread_entry *thread = usb_thread_entry; - usb_thread_entry = NULL; + uintptr_t thread = usb_thread_entry; + usb_thread_entry = 0; - if (thread == NULL) + if (thread == 0) return; tick_remove_task(usb_tick); diff --git a/uisimulator/sdl/thread-sdl.c b/uisimulator/sdl/thread-sdl.c index 905a017ee0..ab1086dd7d 100644 --- a/uisimulator/sdl/thread-sdl.c +++ b/uisimulator/sdl/thread-sdl.c @@ -93,6 +93,38 @@ void thread_sdl_shutdown(void) 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- return to a prior call-level which would be unaware of the fact setjmp was used */ @@ -119,6 +151,8 @@ static int thread_sdl_app_main(void *param) bool thread_sdl_init(void *param) { struct thread_entry *thread; + int n; + memset(cores, 0, sizeof(cores)); memset(threads, 0, sizeof(threads)); @@ -130,6 +164,10 @@ bool thread_sdl_init(void *param) 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 then create the SDL thread - it is possible to have a quick, early shutdown try to access the structure. */ @@ -179,23 +217,11 @@ void * thread_sdl_thread_unlock(void) 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; - int n; - - for (n = 0; n < MAXTHREADS; n++) - { - int state = threads[n].state; - - if (state == STATE_KILLED) - { - thread = &threads[n]; - break; - } - } - - return thread; + return (thread_id == THREAD_ID_CURRENT) ? + cores[CURRENT_CORE].running : + &threads[thread_id & THREAD_ID_SLOT_MASK]; } 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; } -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) @@ -389,9 +415,11 @@ unsigned int thread_queue_wake(struct thread_entry **list) 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; SDL_SemPost(thread->context.s); @@ -441,9 +469,9 @@ int runthread(void *data) return 0; } -struct thread_entry* - create_thread(void (*function)(void), void* stack, size_t stack_size, - unsigned flags, const char *name) +unsigned int create_thread(void (*function)(void), + void* stack, size_t stack_size, + unsigned flags, const char *name) { struct thread_entry *thread; SDL_Thread* t; @@ -455,14 +483,14 @@ struct thread_entry* if (thread == NULL) { DEBUGF("Failed to find thread slot\n"); - return NULL; + return 0; } s = SDL_CreateSemaphore(0); if (s == NULL) { DEBUGF("Failed to create semaphore\n"); - return NULL; + return 0; } t = SDL_CreateThread(runthread, thread); @@ -470,7 +498,7 @@ struct thread_entry* { DEBUGF("Failed to create SDL thread\n"); SDL_DestroySemaphore(s); - return NULL; + return 0; } thread->stack = stack; @@ -485,7 +513,7 @@ struct thread_entry* THREAD_SDL_DEBUGF("New Thread: %d (%s)\n", thread - threads, THREAD_SDL_GET_NAME(thread)); - return thread; + return thread->id; } void init_threads(void) @@ -501,18 +529,22 @@ void init_threads(void) 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 *thread = thread_id_entry(thread_id); + SDL_Thread *t; SDL_sem *s; - int oldlevel = disable_irq_save(); + if (thread_id != THREAD_ID_CURRENT && thread->id != thread_id) + return; - if (thread == NULL) - { - thread = current; - } + int oldlevel = disable_irq_save(); t = thread->context.t; s = thread->context.s; @@ -540,6 +572,7 @@ void remove_thread(struct thread_entry *thread) THREAD_SDL_DEBUGF("Removing thread: %d (%s)\n", thread - threads, THREAD_SDL_GET_NAME(thread)); + new_thread_id(thread->id, thread); thread->state = STATE_KILLED; thread_queue_wake(&thread->queue); @@ -559,17 +592,16 @@ void remove_thread(struct thread_entry *thread) 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 *thread = thread_id_entry(thread_id); - if (thread == NULL) - thread = current; - - if (thread->state != STATE_KILLED) + if (thread_id == THREAD_ID_CURRENT || + (thread->id == thread_id && thread->state != STATE_KILLED)) { current->bqp = &thread->queue; block_thread(current); @@ -583,11 +615,6 @@ int thread_stack_usage(const struct thread_entry *thread) (void)thread; } -unsigned thread_get_status(const struct thread_entry *thread) -{ - return thread->state; -} - /* Return name if one or ID if none */ void thread_get_name(char *buffer, int size, struct thread_entry *thread) -- cgit v1.2.3