summaryrefslogtreecommitdiff
path: root/uisimulator/sdl
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2007-09-08 12:20:53 +0000
committerMichael Sevakis <jethead71@rockbox.org>2007-09-08 12:20:53 +0000
commitf64ebb1c1f10e8d15fcc4879d781703c86c5fb8b (patch)
tree065072709c699ac6dc3eb640368bd3f4106144e4 /uisimulator/sdl
parent69b4654ea28049c7e8637d521327ba10ae405f8b (diff)
downloadrockbox-f64ebb1c1f10e8d15fcc4879d781703c86c5fb8b.tar.gz
rockbox-f64ebb1c1f10e8d15fcc4879d781703c86c5fb8b.zip
Sim I/O and threading that runs more like on target. Tweakable if any genuine slowness imitation is required for any one of them. One point of concern is the sim shutdown on an OS other than Linux just because terminating threads in a manner other than having the do it themselves is kind of dirty IMHO.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14639 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'uisimulator/sdl')
-rw-r--r--uisimulator/sdl/kernel.c126
-rw-r--r--uisimulator/sdl/thread-sdl.c343
-rw-r--r--uisimulator/sdl/thread-sdl.h5
-rw-r--r--uisimulator/sdl/uisdl.c15
4 files changed, 386 insertions, 103 deletions
diff --git a/uisimulator/sdl/kernel.c b/uisimulator/sdl/kernel.c
index 2b194a24ae..91d1afa1b9 100644
--- a/uisimulator/sdl/kernel.c
+++ b/uisimulator/sdl/kernel.c
@@ -25,25 +25,19 @@
25#include "thread.h" 25#include "thread.h"
26#include "debug.h" 26#include "debug.h"
27 27
28volatile long current_tick = 0;
28static void (*tick_funcs[MAX_NUM_TICK_TASKS])(void); 29static void (*tick_funcs[MAX_NUM_TICK_TASKS])(void);
29 30
30/* This array holds all queues that are initiated. It is used for broadcast. */ 31/* This array holds all queues that are initiated. It is used for broadcast. */
31static struct event_queue *all_queues[32]; 32static struct event_queue *all_queues[32];
32static int num_queues = 0; 33static int num_queues = 0;
33 34
34int set_irq_level (int level)
35{
36 static int _lv = 0;
37 return (_lv = level);
38}
39
40#ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 35#ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
41/* Moves waiting thread's descriptor to the current sender when a 36/* Moves waiting thread's descriptor to the current sender when a
42 message is dequeued */ 37 message is dequeued */
43static void queue_fetch_sender(struct queue_sender_list *send, 38static void queue_fetch_sender(struct queue_sender_list *send,
44 unsigned int i) 39 unsigned int i)
45{ 40{
46 int old_level = set_irq_level(15<<4);
47 struct thread_entry **spp = &send->senders[i]; 41 struct thread_entry **spp = &send->senders[i];
48 42
49 if(*spp) 43 if(*spp)
@@ -51,8 +45,6 @@ static void queue_fetch_sender(struct queue_sender_list *send,
51 send->curr_sender = *spp; 45 send->curr_sender = *spp;
52 *spp = NULL; 46 *spp = NULL;
53 } 47 }
54
55 set_irq_level(old_level);
56} 48}
57 49
58/* Puts the specified return value in the waiting thread's return value 50/* Puts the specified return value in the waiting thread's return value
@@ -61,7 +53,12 @@ static void queue_release_sender(struct thread_entry **sender,
61 intptr_t retval) 53 intptr_t retval)
62{ 54{
63 (*sender)->retval = retval; 55 (*sender)->retval = retval;
64 *sender = NULL; 56 wakeup_thread(sender);
57 if(*sender != NULL)
58 {
59 fprintf(stderr, "queue->send slot ovf: %08X\n", (int)*sender);
60 exit(-1);
61 }
65} 62}
66 63
67/* Releases any waiting threads that are queued with queue_send - 64/* Releases any waiting threads that are queued with queue_send -
@@ -88,8 +85,12 @@ static void queue_release_all_senders(struct event_queue *q)
88void queue_enable_queue_send(struct event_queue *q, 85void queue_enable_queue_send(struct event_queue *q,
89 struct queue_sender_list *send) 86 struct queue_sender_list *send)
90{ 87{
91 q->send = send; 88 q->send = NULL;
92 memset(send, 0, sizeof(*send)); 89 if(send)
90 {
91 q->send = send;
92 memset(send, 0, sizeof(*send));
93 }
93} 94}
94#endif /* HAVE_EXTENDED_MESSAGING_AND_NAME */ 95#endif /* HAVE_EXTENDED_MESSAGING_AND_NAME */
95 96
@@ -104,6 +105,11 @@ void queue_init(struct event_queue *q, bool register_queue)
104 105
105 if(register_queue) 106 if(register_queue)
106 { 107 {
108 if(num_queues >= 32)
109 {
110 fprintf(stderr, "queue_init->out of queues");
111 exit(-1);
112 }
107 /* Add it to the all_queues array */ 113 /* Add it to the all_queues array */
108 all_queues[num_queues++] = q; 114 all_queues[num_queues++] = q;
109 } 115 }
@@ -114,13 +120,6 @@ void queue_delete(struct event_queue *q)
114 int i; 120 int i;
115 bool found = false; 121 bool found = false;
116 122
117#ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
118 /* Release waiting threads and reply to any dequeued message
119 waiting for one. */
120 queue_release_all_senders(q);
121 queue_reply(q, 0);
122#endif
123
124 /* Find the queue to be deleted */ 123 /* Find the queue to be deleted */
125 for(i = 0;i < num_queues;i++) 124 for(i = 0;i < num_queues;i++)
126 { 125 {
@@ -141,15 +140,28 @@ void queue_delete(struct event_queue *q)
141 140
142 num_queues--; 141 num_queues--;
143 } 142 }
143
144 /* Release threads waiting on queue head */
145 wakeup_thread(&q->thread);
146
147#ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
148 /* Release waiting threads and reply to any dequeued message
149 waiting for one. */
150 queue_release_all_senders(q);
151 queue_reply(q, 0);
152#endif
153
154 q->read = 0;
155 q->write = 0;
144} 156}
145 157
146void queue_wait(struct event_queue *q, struct event *ev) 158void queue_wait(struct event_queue *q, struct event *ev)
147{ 159{
148 unsigned int rd; 160 unsigned int rd;
149 161
150 while(q->read == q->write) 162 if (q->read == q->write)
151 { 163 {
152 switch_thread(true, NULL); 164 block_thread(&q->thread);
153 } 165 }
154 166
155 rd = q->read++ & QUEUE_LENGTH_MASK; 167 rd = q->read++ & QUEUE_LENGTH_MASK;
@@ -166,11 +178,9 @@ void queue_wait(struct event_queue *q, struct event *ev)
166 178
167void queue_wait_w_tmo(struct event_queue *q, struct event *ev, int ticks) 179void queue_wait_w_tmo(struct event_queue *q, struct event *ev, int ticks)
168{ 180{
169 unsigned int timeout = current_tick + ticks; 181 if (q->read == q->write && ticks > 0)
170
171 while(q->read == q->write && TIME_BEFORE( current_tick, timeout ))
172 { 182 {
173 sim_sleep(1); 183 block_thread_w_tmo(&q->thread, ticks);
174 } 184 }
175 185
176 if(q->read != q->write) 186 if(q->read != q->write)
@@ -194,7 +204,6 @@ void queue_wait_w_tmo(struct event_queue *q, struct event *ev, int ticks)
194 204
195void queue_post(struct event_queue *q, long id, intptr_t data) 205void queue_post(struct event_queue *q, long id, intptr_t data)
196{ 206{
197 int oldlevel = set_irq_level(15<<4);
198 unsigned int wr = q->write++ & QUEUE_LENGTH_MASK; 207 unsigned int wr = q->write++ & QUEUE_LENGTH_MASK;
199 208
200 q->events[wr].id = id; 209 q->events[wr].id = id;
@@ -213,13 +222,12 @@ void queue_post(struct event_queue *q, long id, intptr_t data)
213 } 222 }
214#endif 223#endif
215 224
216 set_irq_level(oldlevel); 225 wakeup_thread(&q->thread);
217} 226}
218 227
219#ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 228#ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
220intptr_t queue_send(struct event_queue *q, long id, intptr_t data) 229intptr_t queue_send(struct event_queue *q, long id, intptr_t data)
221{ 230{
222 int oldlevel = set_irq_level(15<<4);
223 unsigned int wr = q->write++ & QUEUE_LENGTH_MASK; 231 unsigned int wr = q->write++ & QUEUE_LENGTH_MASK;
224 232
225 q->events[wr].id = id; 233 q->events[wr].id = id;
@@ -228,7 +236,6 @@ intptr_t queue_send(struct event_queue *q, long id, intptr_t data)
228 if(q->send) 236 if(q->send)
229 { 237 {
230 struct thread_entry **spp = &q->send->senders[wr]; 238 struct thread_entry **spp = &q->send->senders[wr];
231 static struct thread_entry sender;
232 239
233 if(*spp) 240 if(*spp)
234 { 241 {
@@ -236,19 +243,13 @@ intptr_t queue_send(struct event_queue *q, long id, intptr_t data)
236 queue_release_sender(spp, 0); 243 queue_release_sender(spp, 0);
237 } 244 }
238 245
239 *spp = &sender; 246 wakeup_thread(&q->thread);
240
241 set_irq_level(oldlevel);
242 while (*spp != NULL)
243 {
244 switch_thread(true, NULL);
245 }
246 247
247 return sender.retval; 248 block_thread(spp);
249 return thread_get_current()->retval;
248 } 250 }
249 251
250 /* Function as queue_post if sending is not enabled */ 252 /* Function as queue_post if sending is not enabled */
251 set_irq_level(oldlevel);
252 return 0; 253 return 0;
253} 254}
254 255
@@ -289,8 +290,6 @@ void queue_clear(struct event_queue* q)
289 290
290void queue_remove_from_head(struct event_queue *q, long id) 291void queue_remove_from_head(struct event_queue *q, long id)
291{ 292{
292 int oldlevel = set_irq_level(15<<4);
293
294 while(q->read != q->write) 293 while(q->read != q->write)
295 { 294 {
296 unsigned int rd = q->read & QUEUE_LENGTH_MASK; 295 unsigned int rd = q->read & QUEUE_LENGTH_MASK;
@@ -314,8 +313,6 @@ void queue_remove_from_head(struct event_queue *q, long id)
314#endif 313#endif
315 q->read++; 314 q->read++;
316 } 315 }
317
318 set_irq_level(oldlevel);
319} 316}
320 317
321int queue_count(const struct event_queue *q) 318int queue_count(const struct event_queue *q)
@@ -335,12 +332,14 @@ int queue_broadcast(long id, intptr_t data)
335 return num_queues; 332 return num_queues;
336} 333}
337 334
338void switch_thread(bool save_context, struct thread_entry **blocked_list) 335void yield(void)
339{ 336{
340 (void)save_context; 337 switch_thread(true, NULL);
341 (void)blocked_list; 338}
342 339
343 yield (); 340void sleep(int ticks)
341{
342 sleep_thread(ticks);
344} 343}
345 344
346void sim_tick_tasks(void) 345void sim_tick_tasks(void)
@@ -370,7 +369,8 @@ int tick_add_task(void (*f)(void))
370 return 0; 369 return 0;
371 } 370 }
372 } 371 }
373 DEBUGF("Error! tick_add_task(): out of tasks"); 372 fprintf(stderr, "Error! tick_add_task(): out of tasks");
373 exit(-1);
374 return -1; 374 return -1;
375} 375}
376 376
@@ -395,29 +395,39 @@ int tick_remove_task(void (*f)(void))
395 multitasking, but is better than nothing at all */ 395 multitasking, but is better than nothing at all */
396void mutex_init(struct mutex *m) 396void mutex_init(struct mutex *m)
397{ 397{
398 m->locked = false; 398 m->thread = NULL;
399 m->locked = 0;
399} 400}
400 401
401void mutex_lock(struct mutex *m) 402void mutex_lock(struct mutex *m)
402{ 403{
403 while(m->locked) 404 if (test_and_set(&m->locked, 1))
404 switch_thread(true, NULL); 405 {
405 m->locked = true; 406 block_thread(&m->thread);
407 }
406} 408}
407 409
408void mutex_unlock(struct mutex *m) 410void mutex_unlock(struct mutex *m)
409{ 411{
410 m->locked = false; 412 if (m->thread != NULL)
413 {
414 wakeup_thread(&m->thread);
415 }
416 else
417 {
418 m->locked = 0;
419 }
411} 420}
412 421
413void spinlock_lock(struct mutex *m) 422void spinlock_lock(struct mutex *l)
414{ 423{
415 while(m->locked) 424 while(test_and_set(&l->locked, 1))
425 {
416 switch_thread(true, NULL); 426 switch_thread(true, NULL);
417 m->locked = true; 427 }
418} 428}
419 429
420void spinlock_unlock(struct mutex *m) 430void spinlock_unlock(struct mutex *l)
421{ 431{
422 m->locked = false; 432 l->locked = 0;
423} 433}
diff --git a/uisimulator/sdl/thread-sdl.c b/uisimulator/sdl/thread-sdl.c
index 90a4ecf4a7..5d2fe0b522 100644
--- a/uisimulator/sdl/thread-sdl.c
+++ b/uisimulator/sdl/thread-sdl.c
@@ -21,41 +21,157 @@
21#include <SDL.h> 21#include <SDL.h>
22#include <SDL_thread.h> 22#include <SDL_thread.h>
23#include <stdlib.h> 23#include <stdlib.h>
24#include <memory.h>
24#include "thread-sdl.h" 25#include "thread-sdl.h"
25#include "kernel.h" 26#include "kernel.h"
26#include "thread.h" 27#include "thread.h"
27#include "debug.h" 28#include "debug.h"
28 29
29SDL_Thread *threads[256]; 30/* Define this as 1 to show informational messages that are not errors. */
30int threadCount = 0; 31#define THREAD_SDL_DEBUGF_ENABLED 0
31volatile long current_tick = 0;
32SDL_mutex *m;
33 32
34void yield(void) 33#if THREAD_SDL_DEBUGF_ENABLED
34#define THREAD_SDL_DEBUGF(...) DEBUGF(__VA_ARGS__)
35static char __name[32];
36#define THREAD_SDL_GET_NAME(thread) \
37 ({ thread_get_name(__name, sizeof(__name)/sizeof(__name[0]), thread); __name; })
38#else
39#define THREAD_SDL_DEBUGF(...)
40#define THREAD_SDL_GET_NAME(thread)
41#endif
42
43#define THREAD_PANICF(str...) \
44 ({ fprintf(stderr, str); exit(-1); })
45
46struct thread_entry threads[MAXTHREADS]; /* Thread entries as in core */
47static SDL_mutex *m;
48static SDL_sem *s;
49static struct thread_entry *running;
50
51void kill_sim_threads(void)
52{
53 int i;
54 SDL_LockMutex(m);
55 for (i = 0; i < MAXTHREADS; i++)
56 {
57 struct thread_entry *thread = &threads[i];
58 if (thread->context.t != NULL)
59 {
60 SDL_LockMutex(m);
61 if (thread->statearg == STATE_RUNNING)
62 SDL_SemPost(s);
63 else
64 SDL_CondSignal(thread->context.c);
65 SDL_KillThread(thread->context.t);
66 SDL_DestroyCond(thread->context.c);
67 }
68 }
69 SDL_DestroyMutex(m);
70 SDL_DestroySemaphore(s);
71}
72
73static int find_empty_thread_slot(void)
74{
75 int n;
76
77 for (n = 0; n < MAXTHREADS; n++)
78 {
79 if (threads[n].name == NULL)
80 break;
81 }
82
83 return n;
84}
85
86static void add_to_list(struct thread_entry **list,
87 struct thread_entry *thread)
88{
89 if (*list == NULL)
90 {
91 /* Insert into unoccupied list */
92 thread->next = thread;
93 thread->prev = thread;
94 *list = thread;
95 }
96 else
97 {
98 /* Insert last */
99 thread->next = *list;
100 thread->prev = (*list)->prev;
101 thread->prev->next = thread;
102 (*list)->prev = thread;
103 }
104}
105
106static void remove_from_list(struct thread_entry **list,
107 struct thread_entry *thread)
35{ 108{
36 static int counter = 0; 109 if (thread == thread->next)
110 {
111 /* The only item */
112 *list = NULL;
113 return;
114 }
37 115
38 SDL_mutexV(m); 116 if (thread == *list)
39 if (counter++ >= 50)
40 { 117 {
41 SDL_Delay(1); 118 /* List becomes next item */
42 counter = 0; 119 *list = thread->next;
43 } 120 }
44 SDL_mutexP(m); 121
122 /* Fix links to jump over the removed entry. */
123 thread->prev->next = thread->next;
124 thread->next->prev = thread->prev;
45} 125}
46 126
47void sim_sleep(int ticks) 127struct thread_entry *thread_get_current(void)
48{ 128{
49 SDL_mutexV(m); 129 return running;
50 SDL_Delay((1000/HZ) * ticks); 130}
51 SDL_mutexP(m); 131
132void switch_thread(bool save_context, struct thread_entry **blocked_list)
133{
134 struct thread_entry *current = running;
135
136 SDL_UnlockMutex(m);
137
138 SDL_SemWait(s);
139
140 SDL_LockMutex(m);
141 running = current;
142
143 SDL_SemPost(s);
144
145 (void)save_context; (void)blocked_list;
146}
147
148void sleep_thread(int ticks)
149{
150 struct thread_entry *current;
151
152 current = running;
153 current->statearg = STATE_SLEEPING;
154
155 SDL_CondWaitTimeout(current->context.c, m, (1000/HZ) * ticks);
156 running = current;
157
158 current->statearg = STATE_RUNNING;
52} 159}
53 160
54int runthread(void *data) 161int runthread(void *data)
55{ 162{
56 SDL_mutexP(m); 163 struct thread_entry *current;
57 ((void(*)())data) (); 164
58 SDL_mutexV(m); 165 /* Cannot access thread variables before locking the mutex as the
166 data structures may not be filled-in yet. */
167 SDL_LockMutex(m);
168 running = (struct thread_entry *)data;
169 current = running;
170 current->context.start();
171
172 THREAD_SDL_DEBUGF("Thread Done: %d (%s)\n",
173 current - threads, THREAD_SDL_GET_NAME(current));
174 remove_thread(NULL);
59 return 0; 175 return 0;
60} 176}
61 177
@@ -64,37 +180,198 @@ struct thread_entry*
64 const char *name) 180 const char *name)
65{ 181{
66 /** Avoid compiler warnings */ 182 /** Avoid compiler warnings */
67 (void)stack;
68 (void)stack_size;
69 (void)name;
70 SDL_Thread* t; 183 SDL_Thread* t;
184 SDL_cond *cond;
185 int slot;
186
187 THREAD_SDL_DEBUGF("Creating thread: (%s)\n", name ? name : "");
71 188
72 if (threadCount == 256) { 189 slot = find_empty_thread_slot();
190 if (slot >= MAXTHREADS)
191 {
192 DEBUGF("Failed to find thread slot\n");
73 return NULL; 193 return NULL;
74 } 194 }
75 195
76 t = SDL_CreateThread(runthread, function); 196 cond = SDL_CreateCond();
77 threads[threadCount++] = t; 197 if (cond == NULL)
198 {
199 DEBUGF("Failed to create condition variable\n");
200 return NULL;
201 }
202
203 t = SDL_CreateThread(runthread, &threads[slot]);
204 if (t == NULL)
205 {
206 DEBUGF("Failed to create SDL thread\n");
207 SDL_DestroyCond(cond);
208 return NULL;
209 }
210
211 threads[slot].stack = stack;
212 threads[slot].stack_size = stack_size;
213 threads[slot].name = name;
214 threads[slot].statearg = STATE_RUNNING;
215 threads[slot].context.start = function;
216 threads[slot].context.t = t;
217 threads[slot].context.c = cond;
218
219 THREAD_SDL_DEBUGF("New Thread: %d (%s)\n",
220 slot, THREAD_SDL_GET_NAME(&threads[slot]));
221
222 return &threads[slot];
223}
224
225void block_thread(struct thread_entry **list)
226{
227 struct thread_entry *thread = running;
228
229 thread->statearg = STATE_BLOCKED;
230 add_to_list(list, thread);
231
232 SDL_CondWait(thread->context.c, m);
233 running = thread;
234}
235
236void block_thread_w_tmo(struct thread_entry **list, int ticks)
237{
238 struct thread_entry *thread = running;
239
240 thread->statearg = STATE_BLOCKED_W_TMO;
241 add_to_list(list, thread);
242
243 SDL_CondWaitTimeout(thread->context.c, m, (1000/HZ) * ticks);
244 running = thread;
245
246 if (thread->statearg == STATE_BLOCKED_W_TMO)
247 {
248 /* Timed out */
249 remove_from_list(list, thread);
250 thread->statearg = STATE_RUNNING;
251 }
252}
253
254void wakeup_thread(struct thread_entry **list)
255{
256 struct thread_entry *thread = *list;
78 257
79 yield(); 258 if (thread == NULL)
259 {
260 return;
261 }
80 262
81 /* The return value is never de-referenced outside thread.c so this 263 switch (thread->statearg)
82 nastiness should be fine. However, a better solution would be nice. 264 {
83 */ 265 case STATE_BLOCKED:
84 return (struct thread_entry*)t; 266 case STATE_BLOCKED_W_TMO:
267 remove_from_list(list, thread);
268 thread->statearg = STATE_RUNNING;
269 SDL_CondSignal(thread->context.c);
270 break;
271 }
85} 272}
86 273
87void init_threads(void) 274void init_threads(void)
88{ 275{
276 int slot;
277
89 m = SDL_CreateMutex(); 278 m = SDL_CreateMutex();
279 s = SDL_CreateSemaphore(0);
280
281 memset(threads, 0, sizeof(threads));
282
283 slot = find_empty_thread_slot();
284 if (slot >= MAXTHREADS)
285 {
286 THREAD_PANICF("Couldn't find slot for main thread.\n");
287 }
288
289 threads[slot].stack = " ";
290 threads[slot].stack_size = 8;
291 threads[slot].name = "main";
292 threads[slot].statearg = STATE_RUNNING;
293 threads[slot].context.t = gui_thread;
294 threads[slot].context.c = SDL_CreateCond();
295
296 running = &threads[slot];
297
298 THREAD_SDL_DEBUGF("First Thread: %d (%s)\n",
299 slot, THREAD_SDL_GET_NAME(&threads[slot]));
300
301 if (SDL_LockMutex(m) == -1) {
302 THREAD_PANICF("Couldn't lock mutex\n");
303 }
90 304
91 if (SDL_mutexP(m) == -1) { 305 if (SDL_SemPost(s) == -1) {
92 fprintf(stderr, "Couldn't lock mutex\n"); 306 THREAD_PANICF("Couldn't post to semaphore\n");
93 exit(-1);
94 } 307 }
95} 308}
96 309
97void remove_thread(struct thread_entry *thread) 310void remove_thread(struct thread_entry *thread)
98{ 311{
99 SDL_KillThread((SDL_Thread*) thread); 312 struct thread_entry *current = running;
313 SDL_Thread *t;
314 SDL_cond *c;
315
316 if (thread == NULL)
317 {
318 thread = current;
319 }
320
321 t = thread->context.t;
322 c = thread->context.c;
323 thread->context.t = NULL;
324
325 if (thread != current)
326 {
327 if (thread->statearg == STATE_RUNNING)
328 SDL_SemPost(s);
329 else
330 SDL_CondSignal(c);
331 }
332
333 THREAD_SDL_DEBUGF("Removing thread: %d (%s)\n",
334 thread - threads, THREAD_SDL_GET_NAME(thread));
335
336 thread->name = NULL;
337
338 SDL_DestroyCond(c);
339
340 if (thread == current)
341 {
342 SDL_UnlockMutex(m);
343 }
344
345 SDL_KillThread(t);
346}
347
348int thread_stack_usage(const struct thread_entry *thread)
349{
350 return 50;
351 (void)thread;
352}
353
354int thread_get_status(const struct thread_entry *thread)
355{
356 return thread->statearg;
357}
358
359/* Return name if one or ID if none */
360void thread_get_name(char *buffer, int size,
361 struct thread_entry *thread)
362{
363 if (size <= 0)
364 return;
365
366 *buffer = '\0';
367
368 if (thread)
369 {
370 /* Display thread name if one or ID if none */
371 bool named = thread->name && *thread->name;
372 const char *fmt = named ? "%s" : "%08lX";
373 intptr_t name = named ?
374 (intptr_t)thread->name : (intptr_t)thread;
375 snprintf(buffer, size, fmt, name);
376 }
100} 377}
diff --git a/uisimulator/sdl/thread-sdl.h b/uisimulator/sdl/thread-sdl.h
index 0bb6ded0d5..20641fb673 100644
--- a/uisimulator/sdl/thread-sdl.h
+++ b/uisimulator/sdl/thread-sdl.h
@@ -22,9 +22,8 @@
22 22
23#include "SDL_thread.h" 23#include "SDL_thread.h"
24 24
25extern SDL_Thread* threads[256]; 25extern SDL_Thread *gui_thread; /* The "main" thread */
26extern int threadCount; 26void kill_sim_threads(); /* Kill all the rockbox sim threads */
27extern SDL_mutex* mutex;
28 27
29#endif /* #ifndef __THREADSDL_H__ */ 28#endif /* #ifndef __THREADSDL_H__ */
30 29
diff --git a/uisimulator/sdl/uisdl.c b/uisimulator/sdl/uisdl.c
index 052fd4af83..37a0e6fe7a 100644
--- a/uisimulator/sdl/uisdl.c
+++ b/uisimulator/sdl/uisdl.c
@@ -41,6 +41,8 @@
41extern void app_main (void *); /* mod entry point */ 41extern void app_main (void *); /* mod entry point */
42extern void new_key(int key); 42extern void new_key(int key);
43extern void sim_tick_tasks(void); 43extern void sim_tick_tasks(void);
44extern void sim_io_init(void);
45extern void sim_io_shutdown(void);
44 46
45void button_event(int key, bool pressed); 47void button_event(int key, bool pressed);
46 48
@@ -167,16 +169,9 @@ bool gui_startup(void)
167 169
168bool gui_shutdown(void) 170bool gui_shutdown(void)
169{ 171{
170 int i;
171
172 SDL_KillThread(gui_thread);
173 SDL_RemoveTimer(tick_timer_id); 172 SDL_RemoveTimer(tick_timer_id);
174 173 kill_sim_threads();
175 for (i = 0; i < threadCount; i++) 174 sim_io_shutdown();
176 {
177 SDL_KillThread(threads[i]);
178 }
179
180 return true; 175 return true;
181} 176}
182 177
@@ -236,6 +231,8 @@ int main(int argc, char *argv[])
236 background = false; 231 background = false;
237 } 232 }
238 233
234 sim_io_init();
235
239 if (!gui_startup()) 236 if (!gui_startup())
240 return -1; 237 return -1;
241 238