summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2007-10-06 15:01:37 +0000
committerMichael Sevakis <jethead71@rockbox.org>2007-10-06 15:01:37 +0000
commitf6de0d4083a4fcb6da57f271e1f8ccaf715e571d (patch)
treed9ff262690167784c0c65d9c1eb2a3ad2e97b479
parenta5133307c79c24c5809a498818f45addefdf252b (diff)
downloadrockbox-f6de0d4083a4fcb6da57f271e1f8ccaf715e571d.tar.gz
rockbox-f6de0d4083a4fcb6da57f271e1f8ccaf715e571d.zip
Discontinue any use of 'swp(b)' on PP5020. While clocking is stable, some testing revealed this instruction can still cause problems without concurrent access. Make sure mpegplayer is safe while not using spinlock (no longer atomic) between cores to protect the stream byte counters - use nonwrapping head and tail pointers.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15005 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugins/mpegplayer/mpegplayer.c59
-rw-r--r--firmware/export/thread.h2
2 files changed, 19 insertions, 42 deletions
diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c
index 8b15ff03ce..54fdf05355 100644
--- a/apps/plugins/mpegplayer/mpegplayer.c
+++ b/apps/plugins/mpegplayer/mpegplayer.c
@@ -201,7 +201,8 @@ typedef struct
201 uint8_t* next_packet; /* Next stream packet beginning */ 201 uint8_t* next_packet; /* Next stream packet beginning */
202 202
203 size_t guard_bytes; /* Number of bytes in guardbuf used */ 203 size_t guard_bytes; /* Number of bytes in guardbuf used */
204 size_t buffer_remaining; /* How much data is left in the buffer */ 204 uint64_t buffer_tail; /* Accumulation of bytes added */
205 uint64_t buffer_head; /* Accumulation of bytes removed */
205 uint32_t curr_pts; /* Current presentation timestamp */ 206 uint32_t curr_pts; /* Current presentation timestamp */
206 uint32_t curr_time; /* Current time in samples */ 207 uint32_t curr_time; /* Current time in samples */
207 uint32_t tagged; /* curr_pts is valid */ 208 uint32_t tagged; /* curr_pts is valid */
@@ -300,7 +301,8 @@ static intptr_t str_send_msg(Stream *str, int id, intptr_t data)
300 return str->dispatch_fn(str, msg); 301 return str->dispatch_fn(str, msg);
301#endif 302#endif
302 303
303 /* Only one thread at a time, please */ 304 /* Only one thread at a time, please - only one core may safely send
305 right now */
304 rb->spinlock_lock(&str->msg_lock); 306 rb->spinlock_lock(&str->msg_lock);
305 307
306 str->ev.id = id; 308 str->ev.id = id;
@@ -335,24 +337,6 @@ static uint8_t *disk_buf IBSS_ATTR;
335static uint8_t *disk_buf_end IBSS_ATTR; 337static uint8_t *disk_buf_end IBSS_ATTR;
336static uint8_t *disk_buf_tail IBSS_ATTR; 338static uint8_t *disk_buf_tail IBSS_ATTR;
337static size_t buffer_size IBSS_ATTR; 339static size_t buffer_size IBSS_ATTR;
338#if NUM_CORES > 1
339/* Some stream variables are shared between cores */
340struct mutex stream_lock IBSS_ATTR;
341static inline void init_stream_lock(void)
342 { rb->spinlock_init(&stream_lock); }
343static inline void lock_stream(void)
344 { rb->spinlock_lock(&stream_lock); }
345static inline void unlock_stream(void)
346 { rb->spinlock_unlock(&stream_lock); }
347#else
348/* No RMW issue here */
349static inline void init_stream_lock(void)
350 { }
351static inline void lock_stream(void)
352 { }
353static inline void unlock_stream(void)
354 { }
355#endif
356 340
357#define MSG_BUFFER_NEARLY_EMPTY 1 341#define MSG_BUFFER_NEARLY_EMPTY 1
358#define MSG_EXIT_REQUESTED 2 342#define MSG_EXIT_REQUESTED 2
@@ -677,22 +661,17 @@ static void get_next_data( Stream* str )
677 661
678 if (str->curr_packet != NULL) 662 if (str->curr_packet != NULL)
679 { 663 {
680 lock_stream();
681
682 if (str->curr_packet < str->prev_packet) 664 if (str->curr_packet < str->prev_packet)
683 { 665 {
684 str->buffer_remaining -= (disk_buf_end - str->prev_packet) + 666 str->buffer_head += (disk_buf_end - str->prev_packet) +
685 (str->curr_packet - disk_buf); 667 (str->curr_packet - disk_buf);
686 str->buffer_remaining -= str->guard_bytes;
687 str->guard_bytes = 0; 668 str->guard_bytes = 0;
688 } 669 }
689 else 670 else
690 { 671 {
691 str->buffer_remaining -= (str->curr_packet - str->prev_packet); 672 str->buffer_head += (str->curr_packet - str->prev_packet);
692 } 673 }
693 674
694 unlock_stream();
695
696 str->prev_packet = str->curr_packet; 675 str->prev_packet = str->curr_packet;
697 } 676 }
698 677
@@ -1898,11 +1877,14 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
1898 disk_buf_tail = buffer+disk_buf_len; 1877 disk_buf_tail = buffer+disk_buf_len;
1899 file_remaining -= disk_buf_len; 1878 file_remaining -= disk_buf_len;
1900 1879
1901 video_str.guard_bytes = audio_str.guard_bytes = 0; 1880 audio_str.guard_bytes = 0;
1902 video_str.prev_packet = disk_buf;
1903 audio_str.prev_packet = disk_buf; 1881 audio_str.prev_packet = disk_buf;
1904 video_str.buffer_remaining = disk_buf_len; 1882 audio_str.buffer_head = 0;
1905 audio_str.buffer_remaining = disk_buf_len; 1883 audio_str.buffer_tail = disk_buf_len;
1884 video_str.guard_bytes = 0;
1885 video_str.prev_packet = disk_buf;
1886 video_str.buffer_head = 0;
1887 video_str.buffer_tail = disk_buf_len;
1906 1888
1907 rb->spinlock_init(&audio_str.msg_lock); 1889 rb->spinlock_init(&audio_str.msg_lock);
1908 rb->spinlock_init(&video_str.msg_lock); 1890 rb->spinlock_init(&video_str.msg_lock);
@@ -1913,8 +1895,6 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
1913 gray_show(true); 1895 gray_show(true);
1914#endif 1896#endif
1915 1897
1916 init_stream_lock();
1917
1918#if NUM_CORES > 1 1898#if NUM_CORES > 1
1919 flush_icache(); 1899 flush_icache();
1920#endif 1900#endif
@@ -1940,8 +1920,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
1940 /* Wait until both threads have finished their work */ 1920 /* Wait until both threads have finished their work */
1941 while ((audio_str.status >= 0) || (video_str.status >= 0)) 1921 while ((audio_str.status >= 0) || (video_str.status >= 0))
1942 { 1922 {
1943 size_t audio_remaining = audio_str.buffer_remaining; 1923 size_t audio_remaining = audio_str.buffer_tail - audio_str.buffer_head;
1944 size_t video_remaining = video_str.buffer_remaining; 1924 size_t video_remaining = video_str.buffer_tail - video_str.buffer_head;
1945 1925
1946 if (MIN(audio_remaining,video_remaining) < MPEG_LOW_WATERMARK) { 1926 if (MIN(audio_remaining,video_remaining) < MPEG_LOW_WATERMARK) {
1947 1927
@@ -1957,11 +1937,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
1957 bytes_to_read -= n; 1937 bytes_to_read -= n;
1958 file_remaining -= n; 1938 file_remaining -= n;
1959 1939
1960 lock_stream(); 1940 audio_str.buffer_tail += n;
1961 audio_str.buffer_remaining += n; 1941 video_str.buffer_tail += n;
1962 video_str.buffer_remaining += n;
1963 unlock_stream();
1964
1965 disk_buf_tail += n; 1942 disk_buf_tail += n;
1966 1943
1967 rb->yield(); 1944 rb->yield();
diff --git a/firmware/export/thread.h b/firmware/export/thread.h
index e16baa2256..7c683ddde5 100644
--- a/firmware/export/thread.h
+++ b/firmware/export/thread.h
@@ -150,7 +150,7 @@ struct core_entry {
150 */ 150 */
151 151
152/* Macros generate better code than an inline function is this case */ 152/* Macros generate better code than an inline function is this case */
153#if defined (CPU_PP) || defined (CPU_ARM) 153#if (defined (CPU_PP) || defined (CPU_ARM)) && CONFIG_CPU != PP5020
154#define test_and_set(x_, v_) \ 154#define test_and_set(x_, v_) \
155({ \ 155({ \
156 uint32_t old; \ 156 uint32_t old; \