summaryrefslogtreecommitdiff
path: root/firmware/kernel.c
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2007-03-09 08:03:18 +0000
committerMichael Sevakis <jethead71@rockbox.org>2007-03-09 08:03:18 +0000
commitdee43ece2086e15894934b754e47cb7ce5882cda (patch)
tree9238a5c80fe4382975387ec90eca61bda8d4ed8f /firmware/kernel.c
parentf4b83e68594f076cdfe510cd2e23b7f57fd158b5 (diff)
downloadrockbox-dee43ece2086e15894934b754e47cb7ce5882cda.tar.gz
rockbox-dee43ece2086e15894934b754e47cb7ce5882cda.zip
Put an end to priority inversion in the ata driver. Gave up trying to have fully atomic dual use mutexes so just replaced the ata driver locking with spins. Maybe I'll have better luck later. Things should run smoothly with database updates and such happening in the background.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12688 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/kernel.c')
-rw-r--r--firmware/kernel.c79
1 files changed, 52 insertions, 27 deletions
diff --git a/firmware/kernel.c b/firmware/kernel.c
index 313530ffba..db7249fdee 100644
--- a/firmware/kernel.c
+++ b/firmware/kernel.c
@@ -656,48 +656,73 @@ void mutex_init(struct mutex *m)
656 m->thread = NULL; 656 m->thread = NULL;
657} 657}
658 658
659#ifdef CPU_PP 659/* PortalPlayer chips have 2 cores, therefore need atomic mutexes
660/* PortalPlayer chips have 2 cores, therefore need atomic mutexes */ 660 * Just use it for ARM, Coldfire and whatever else well...why not?
661 */
661 662
662static inline bool test_and_set(bool *x, bool v) 663/* Macros generate better code than an inline function is this case */
663{ 664#if defined (CPU_PP) || defined (CPU_ARM)
664 asm volatile ( 665#define test_and_set(x_, v_) \
665 "swpb %0, %0, [%1]\n" 666({ \
666 : "+r"(v) 667 uint32_t old; \
667 : "r"(x) 668 asm volatile ( \
668 ); 669 "swpb %[old], %[v], [%[x]] \r\n" \
669 return v; 670 : [old]"=r"(old) \
670} 671 : [v]"r"((uint32_t)v_), [x]"r"((uint32_t *)x_) \
672 ); \
673 old; \
674 })
675#elif defined (CPU_COLDFIRE)
676#define test_and_set(x_, v_) \
677({ \
678 uint8_t old; \
679 asm volatile ( \
680 "bset.l %[v], (%[x]) \r\n" \
681 "sne.b %[old] \r\n" \
682 : [old]"=d,d"(old) \
683 : [v]"i,d"((uint32_t)v_), [x]"a,a"((uint32_t *)x_) \
684 ); \
685 old; \
686 })
687#else
688/* default for no asm version */
689#define test_and_set(x_, v_) \
690({ \
691 uint32_t old = *(uint32_t *)x_; \
692 *(uint32_t *)x_ = v_; \
693 old; \
694 })
695#endif
671 696
672void mutex_lock(struct mutex *m) 697void mutex_lock(struct mutex *m)
673{ 698{
674 if (test_and_set(&m->locked,true)) 699 if (test_and_set(&m->locked, 1))
675 { 700 {
676 /* Wait until the lock is open... */ 701 /* Wait until the lock is open... */
677 block_thread(&m->thread); 702 block_thread(&m->thread);
678 } 703 }
679} 704}
680 705
681#else 706void mutex_unlock(struct mutex *m)
682void mutex_lock(struct mutex *m)
683{ 707{
684 if (m->locked) 708 if (m->thread == NULL)
709 m->locked = 0;
710 else
711 wakeup_thread(&m->thread);
712}
713
714void spinlock_lock(struct mutex *m)
715{
716 while (test_and_set(&m->locked, 1))
685 { 717 {
686 /* Wait until the lock is open... */ 718 /* wait until the lock is open... */
687 block_thread(&m->thread); 719 switch_thread(true, NULL);
688 } 720 }
689
690 /* ...and lock it */
691 m->locked = true;
692} 721}
693#endif
694 722
695void mutex_unlock(struct mutex *m) 723void spinlock_unlock(struct mutex *m)
696{ 724{
697 if (m->thread == NULL) 725 m->locked = 0;
698 m->locked = false;
699 else
700 wakeup_thread(&m->thread);
701} 726}
702 727
703#endif 728#endif /* ndef SIMULATOR */