summaryrefslogtreecommitdiff
path: root/firmware/kernel.c
diff options
context:
space:
mode:
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 */