summaryrefslogtreecommitdiffstats
path: root/uisimulator/sdl/thread-sdl.c
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2008-12-10 08:57:10 +0000
committerMichael Sevakis <jethead71@rockbox.org>2008-12-10 08:57:10 +0000
commit8cfbd3604fac14f629244e521ad24ffa9938c790 (patch)
tree16dc096519b8b537bb7d4b73e0c97f5f33ee752b /uisimulator/sdl/thread-sdl.c
parent40ff47c7eea41ac893d7af5c5b97ace52a5ffade (diff)
downloadrockbox-8cfbd3604fac14f629244e521ad24ffa9938c790.tar.gz
rockbox-8cfbd3604fac14f629244e521ad24ffa9938c790.tar.bz2
rockbox-8cfbd3604fac14f629244e521ad24ffa9938c790.zip
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
Diffstat (limited to 'uisimulator/sdl/thread-sdl.c')
-rw-r--r--uisimulator/sdl/thread-sdl.c115
1 files changed, 71 insertions, 44 deletions
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)