diff options
Diffstat (limited to 'firmware/kernel.c')
-rw-r--r-- | firmware/kernel.c | 79 |
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 | ||
662 | static 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 | ||
672 | void mutex_lock(struct mutex *m) | 697 | void 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 | 706 | void mutex_unlock(struct mutex *m) |
682 | void 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 | |||
714 | void 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 | ||
695 | void mutex_unlock(struct mutex *m) | 723 | void 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 */ |