summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2008-01-24 13:35:13 +0000
committerMichael Sevakis <jethead71@rockbox.org>2008-01-24 13:35:13 +0000
commitef1f7d3bf980639d656ff6794ecdd0eb64207420 (patch)
tree64d4dcdbafcdbb2215e97d5591d6fbc18af040ec
parent4cfae09f02f119dceb8e90ce439dbf43eb5203e7 (diff)
downloadrockbox-ef1f7d3bf980639d656ff6794ecdd0eb64207420.tar.gz
rockbox-ef1f7d3bf980639d656ff6794ecdd0eb64207420.zip
SPC Codec: Ensure no crash occurs on load failure which could cause emulation to be run without a program loaded on dual core (DSP wasn't initialized yet). The load failures come from core buffering not having the atomic audio file fully loaded before the codec requests the buffer (it gets as many bytes as can be provided) which IMHO isn't very atomic :). Changes in thread execution order after dumping spinlocks for general use simply revealed the buffering race condition. No fix for that will be hacked into the codec itself but should be fixed in the core. Add my copyright to files I had a significant part in developing per request of Adam Gashlin.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16154 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/codecs/spc.c37
-rw-r--r--apps/codecs/spc/spc_codec.h1
-rw-r--r--apps/codecs/spc/spc_dsp.c3
-rw-r--r--apps/codecs/spc/spc_emu.c6
4 files changed, 32 insertions, 15 deletions
diff --git a/apps/codecs/spc.c b/apps/codecs/spc.c
index 33618f1c85..0a608dfa4a 100644
--- a/apps/codecs/spc.c
+++ b/apps/codecs/spc.c
@@ -7,6 +7,7 @@
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2007-2008 Michael Sevakis (jhMikeS)
10 * Copyright (C) 2006-2007 Adam Gashlin (hcs) 11 * Copyright (C) 2006-2007 Adam Gashlin (hcs)
11 * Copyright (C) 2004-2007 Shay Green (blargg) 12 * Copyright (C) 2004-2007 Shay Green (blargg)
12 * Copyright (C) 2002 Brad Martin 13 * Copyright (C) 2002 Brad Martin
@@ -278,8 +279,12 @@ static intptr_t emu_thread_send_msg(long id, intptr_t data)
278 chunk->data = data; 279 chunk->data = data;
279 /* Release it to the emu thread */ 280 /* Release it to the emu thread */
280 samples_release_rdbuf(); 281 samples_release_rdbuf();
281 /* Wait for a response */ 282
282 ci->event_wait(&sample_queue.emu_evt_reply, STATE_SIGNALED); 283 if (id != SPC_EMU_QUIT) {
284 /* Wait for a response */
285 ci->event_wait(&sample_queue.emu_evt_reply, STATE_SIGNALED);
286 }
287
283 return sample_queue.retval; 288 return sample_queue.retval;
284} 289}
285 290
@@ -298,16 +303,19 @@ static bool emu_thread_process_msg(struct sample_queue_chunk *chunk)
298 invalidate_icache(); 303 invalidate_icache();
299 SPC_Init(&spc_emu); 304 SPC_Init(&spc_emu);
300 sample_queue.retval = SPC_load_spc(&spc_emu, ld->buf, ld->size); 305 sample_queue.retval = SPC_load_spc(&spc_emu, ld->buf, ld->size);
306
307 /* Empty the audio queue */
308 /* This is a dirty hack a timeout based wait would make unnescessary but
309 still safe because the other thread is known to be waiting for a reply
310 and is not using the objects. */
311 ci->semaphore_init(&sample_queue.emu_sem_tail, 2, 2);
312 ci->semaphore_init(&sample_queue.emu_sem_head, 2, 0);
313 sample_queue.head = sample_queue.tail = 0;
301 } 314 }
302 315
303 /* Empty the audio queue */ 316 if (id != SPC_EMU_QUIT) {
304 /* This is a dirty hack a timeout based wait would make unnescessary but 317 ci->event_set_state(&sample_queue.emu_evt_reply, STATE_SIGNALED);
305 still safe because the other thread is known to be waiting for a reply 318 }
306 and is not using the objects. */
307 ci->semaphore_init(&sample_queue.emu_sem_tail, 2, 2);
308 ci->semaphore_init(&sample_queue.emu_sem_head, 2, 0);
309 sample_queue.head = sample_queue.tail = 0;
310 ci->event_set_state(&sample_queue.emu_evt_reply, STATE_SIGNALED);
311 319
312 return ret; 320 return ret;
313} 321}
@@ -373,9 +381,12 @@ static inline int load_spc_buffer(uint8_t *buf, size_t size)
373 381
374static inline void spc_emu_quit(void) 382static inline void spc_emu_quit(void)
375{ 383{
376 emu_thread_send_msg(SPC_EMU_QUIT, 0); 384 if (emu_thread_p != NULL) {
377 /* Wait for emu thread to be killed */ 385 emu_thread_send_msg(SPC_EMU_QUIT, 0);
378 ci->thread_wait(emu_thread_p); 386 /* Wait for emu thread to be killed */
387 ci->thread_wait(emu_thread_p);
388 invalidate_icache();
389 }
379} 390}
380 391
381static inline bool spc_play_get_samples(int32_t **samples) 392static inline bool spc_play_get_samples(int32_t **samples)
diff --git a/apps/codecs/spc/spc_codec.h b/apps/codecs/spc/spc_codec.h
index 013f5363ca..a18aece645 100644
--- a/apps/codecs/spc/spc_codec.h
+++ b/apps/codecs/spc/spc_codec.h
@@ -7,6 +7,7 @@
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2007-2008 Michael Sevakis (jhMikeS)
10 * Copyright (C) 2006-2007 Adam Gashlin (hcs) 11 * Copyright (C) 2006-2007 Adam Gashlin (hcs)
11 * Copyright (C) 2004-2007 Shay Green (blargg) 12 * Copyright (C) 2004-2007 Shay Green (blargg)
12 * Copyright (C) 2002 Brad Martin 13 * Copyright (C) 2002 Brad Martin
diff --git a/apps/codecs/spc/spc_dsp.c b/apps/codecs/spc/spc_dsp.c
index 19986fd8a8..dda80e93ce 100644
--- a/apps/codecs/spc/spc_dsp.c
+++ b/apps/codecs/spc/spc_dsp.c
@@ -7,6 +7,7 @@
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2007-2008 Michael Sevakis (jhMikeS)
10 * Copyright (C) 2006-2007 Adam Gashlin (hcs) 11 * Copyright (C) 2006-2007 Adam Gashlin (hcs)
11 * Copyright (C) 2004-2007 Shay Green (blargg) 12 * Copyright (C) 2004-2007 Shay Green (blargg)
12 * Copyright (C) 2002 Brad Martin 13 * Copyright (C) 2002 Brad Martin
@@ -31,7 +32,7 @@ int32_t fir_buf[FIR_BUF_CNT]
31#endif 32#endif
32#if SPC_BRRCACHE 33#if SPC_BRRCACHE
33/* a little extra for samples that go past end */ 34/* a little extra for samples that go past end */
34int16_t BRRcache [BRR_CACHE_SIZE]; 35int16_t BRRcache [BRR_CACHE_SIZE] CACHEALIGN_ATTR;
35#endif 36#endif
36 37
37void DSP_write( struct Spc_Dsp* this, int i, int data ) 38void DSP_write( struct Spc_Dsp* this, int i, int data )
diff --git a/apps/codecs/spc/spc_emu.c b/apps/codecs/spc/spc_emu.c
index 30aaf5d64b..bd9c005ee5 100644
--- a/apps/codecs/spc/spc_emu.c
+++ b/apps/codecs/spc/spc_emu.c
@@ -27,7 +27,7 @@
27/* DSP Based on Brad Martin's OpenSPC DSP emulator */ 27/* DSP Based on Brad Martin's OpenSPC DSP emulator */
28/* tag reading from sexyspc by John Brawn (John_Brawn@yahoo.com) and others */ 28/* tag reading from sexyspc by John Brawn (John_Brawn@yahoo.com) and others */
29 29
30struct cpu_ram_t ram; 30struct cpu_ram_t ram CACHEALIGN_ATTR;
31 31
32/**************** Timers ****************/ 32/**************** Timers ****************/
33 33
@@ -76,6 +76,10 @@ void SPC_Init( THIS )
76 this->boot_rom [sizeof this->boot_rom - 2] = 0xC0; 76 this->boot_rom [sizeof this->boot_rom - 2] = 0xC0;
77 this->boot_rom [sizeof this->boot_rom - 1] = 0xFF; 77 this->boot_rom [sizeof this->boot_rom - 1] = 0xFF;
78 ci->memset( this->boot_rom, 0, sizeof this->boot_rom - 2 ); 78 ci->memset( this->boot_rom, 0, sizeof this->boot_rom - 2 );
79
80 /* Have DSP in a defined state in case EMU is run and hasn't loaded
81 * a program yet */
82 DSP_reset(&this->dsp);
79} 83}
80 84
81static void SPC_load_state( THIS, struct cpu_regs_t const* cpu_state, 85static void SPC_load_state( THIS, struct cpu_regs_t const* cpu_state,