diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2007-03-09 08:03:18 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2007-03-09 08:03:18 +0000 |
commit | dee43ece2086e15894934b754e47cb7ce5882cda (patch) | |
tree | 9238a5c80fe4382975387ec90eca61bda8d4ed8f /firmware | |
parent | f4b83e68594f076cdfe510cd2e23b7f57fd158b5 (diff) | |
download | rockbox-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')
-rw-r--r-- | firmware/drivers/ata.c | 44 | ||||
-rw-r--r-- | firmware/export/kernel.h | 10 | ||||
-rw-r--r-- | firmware/export/thread.h | 14 | ||||
-rw-r--r-- | firmware/kernel.c | 79 | ||||
-rw-r--r-- | firmware/thread.c | 43 |
5 files changed, 122 insertions, 68 deletions
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c index 76c0090a12..d2c80e0ae0 100644 --- a/firmware/drivers/ata.c +++ b/firmware/drivers/ata.c | |||
@@ -104,7 +104,7 @@ STATICIRAM int wait_for_bsy(void) | |||
104 | long timeout = current_tick + HZ*30; | 104 | long timeout = current_tick + HZ*30; |
105 | while (TIME_BEFORE(current_tick, timeout) && (ATA_STATUS & STATUS_BSY)) { | 105 | while (TIME_BEFORE(current_tick, timeout) && (ATA_STATUS & STATUS_BSY)) { |
106 | last_disk_activity = current_tick; | 106 | last_disk_activity = current_tick; |
107 | yield(); | 107 | priority_yield(); |
108 | } | 108 | } |
109 | 109 | ||
110 | if (TIME_BEFORE(current_tick, timeout)) | 110 | if (TIME_BEFORE(current_tick, timeout)) |
@@ -126,7 +126,7 @@ STATICIRAM int wait_for_rdy(void) | |||
126 | while (TIME_BEFORE(current_tick, timeout) && | 126 | while (TIME_BEFORE(current_tick, timeout) && |
127 | !(ATA_ALT_STATUS & STATUS_RDY)) { | 127 | !(ATA_ALT_STATUS & STATUS_RDY)) { |
128 | last_disk_activity = current_tick; | 128 | last_disk_activity = current_tick; |
129 | yield(); | 129 | priority_yield(); |
130 | } | 130 | } |
131 | 131 | ||
132 | if (TIME_BEFORE(current_tick, timeout)) | 132 | if (TIME_BEFORE(current_tick, timeout)) |
@@ -216,7 +216,7 @@ int ata_read_sectors(IF_MV2(int drive,) | |||
216 | #ifdef HAVE_MULTIVOLUME | 216 | #ifdef HAVE_MULTIVOLUME |
217 | (void)drive; /* unused for now */ | 217 | (void)drive; /* unused for now */ |
218 | #endif | 218 | #endif |
219 | mutex_lock(&ata_mtx); | 219 | spinlock_lock(&ata_mtx); |
220 | 220 | ||
221 | last_disk_activity = current_tick; | 221 | last_disk_activity = current_tick; |
222 | spinup_start = current_tick; | 222 | spinup_start = current_tick; |
@@ -227,14 +227,14 @@ int ata_read_sectors(IF_MV2(int drive,) | |||
227 | spinup = true; | 227 | spinup = true; |
228 | if (poweroff) { | 228 | if (poweroff) { |
229 | if (ata_power_on()) { | 229 | if (ata_power_on()) { |
230 | mutex_unlock(&ata_mtx); | 230 | spinlock_unlock(&ata_mtx); |
231 | ata_led(false); | 231 | ata_led(false); |
232 | return -1; | 232 | return -1; |
233 | } | 233 | } |
234 | } | 234 | } |
235 | else { | 235 | else { |
236 | if (perform_soft_reset()) { | 236 | if (perform_soft_reset()) { |
237 | mutex_unlock(&ata_mtx); | 237 | spinlock_unlock(&ata_mtx); |
238 | ata_led(false); | 238 | ata_led(false); |
239 | return -1; | 239 | return -1; |
240 | } | 240 | } |
@@ -246,7 +246,7 @@ int ata_read_sectors(IF_MV2(int drive,) | |||
246 | SET_REG(ATA_SELECT, ata_device); | 246 | SET_REG(ATA_SELECT, ata_device); |
247 | if (!wait_for_rdy()) | 247 | if (!wait_for_rdy()) |
248 | { | 248 | { |
249 | mutex_unlock(&ata_mtx); | 249 | spinlock_unlock(&ata_mtx); |
250 | ata_led(false); | 250 | ata_led(false); |
251 | return -2; | 251 | return -2; |
252 | } | 252 | } |
@@ -359,7 +359,7 @@ int ata_read_sectors(IF_MV2(int drive,) | |||
359 | } | 359 | } |
360 | ata_led(false); | 360 | ata_led(false); |
361 | 361 | ||
362 | mutex_unlock(&ata_mtx); | 362 | spinlock_unlock(&ata_mtx); |
363 | 363 | ||
364 | return ret; | 364 | return ret; |
365 | } | 365 | } |
@@ -417,7 +417,7 @@ int ata_write_sectors(IF_MV2(int drive,) | |||
417 | if (start == 0) | 417 | if (start == 0) |
418 | panicf("Writing on sector 0\n"); | 418 | panicf("Writing on sector 0\n"); |
419 | 419 | ||
420 | mutex_lock(&ata_mtx); | 420 | spinlock_lock(&ata_mtx); |
421 | 421 | ||
422 | last_disk_activity = current_tick; | 422 | last_disk_activity = current_tick; |
423 | spinup_start = current_tick; | 423 | spinup_start = current_tick; |
@@ -428,14 +428,14 @@ int ata_write_sectors(IF_MV2(int drive,) | |||
428 | spinup = true; | 428 | spinup = true; |
429 | if (poweroff) { | 429 | if (poweroff) { |
430 | if (ata_power_on()) { | 430 | if (ata_power_on()) { |
431 | mutex_unlock(&ata_mtx); | 431 | spinlock_unlock(&ata_mtx); |
432 | ata_led(false); | 432 | ata_led(false); |
433 | return -1; | 433 | return -1; |
434 | } | 434 | } |
435 | } | 435 | } |
436 | else { | 436 | else { |
437 | if (perform_soft_reset()) { | 437 | if (perform_soft_reset()) { |
438 | mutex_unlock(&ata_mtx); | 438 | spinlock_unlock(&ata_mtx); |
439 | ata_led(false); | 439 | ata_led(false); |
440 | return -1; | 440 | return -1; |
441 | } | 441 | } |
@@ -445,7 +445,7 @@ int ata_write_sectors(IF_MV2(int drive,) | |||
445 | SET_REG(ATA_SELECT, ata_device); | 445 | SET_REG(ATA_SELECT, ata_device); |
446 | if (!wait_for_rdy()) | 446 | if (!wait_for_rdy()) |
447 | { | 447 | { |
448 | mutex_unlock(&ata_mtx); | 448 | spinlock_unlock(&ata_mtx); |
449 | ata_led(false); | 449 | ata_led(false); |
450 | return -2; | 450 | return -2; |
451 | } | 451 | } |
@@ -507,7 +507,7 @@ int ata_write_sectors(IF_MV2(int drive,) | |||
507 | 507 | ||
508 | ata_led(false); | 508 | ata_led(false); |
509 | 509 | ||
510 | mutex_unlock(&ata_mtx); | 510 | spinlock_unlock(&ata_mtx); |
511 | 511 | ||
512 | return ret; | 512 | return ret; |
513 | } | 513 | } |
@@ -572,13 +572,13 @@ static int ata_perform_sleep(void) | |||
572 | { | 572 | { |
573 | int ret = 0; | 573 | int ret = 0; |
574 | 574 | ||
575 | mutex_lock(&ata_mtx); | 575 | spinlock_lock(&ata_mtx); |
576 | 576 | ||
577 | SET_REG(ATA_SELECT, ata_device); | 577 | SET_REG(ATA_SELECT, ata_device); |
578 | 578 | ||
579 | if(!wait_for_rdy()) { | 579 | if(!wait_for_rdy()) { |
580 | DEBUGF("ata_perform_sleep() - not RDY\n"); | 580 | DEBUGF("ata_perform_sleep() - not RDY\n"); |
581 | mutex_unlock(&ata_mtx); | 581 | spinlock_unlock(&ata_mtx); |
582 | return -1; | 582 | return -1; |
583 | } | 583 | } |
584 | 584 | ||
@@ -591,7 +591,7 @@ static int ata_perform_sleep(void) | |||
591 | } | 591 | } |
592 | 592 | ||
593 | sleeping = true; | 593 | sleeping = true; |
594 | mutex_unlock(&ata_mtx); | 594 | spinlock_unlock(&ata_mtx); |
595 | return ret; | 595 | return ret; |
596 | } | 596 | } |
597 | 597 | ||
@@ -649,9 +649,9 @@ static void ata_thread(void) | |||
649 | if ( !spinup && sleeping && !poweroff && | 649 | if ( !spinup && sleeping && !poweroff && |
650 | TIME_AFTER( current_tick, last_sleep + ATA_POWER_OFF_TIMEOUT )) | 650 | TIME_AFTER( current_tick, last_sleep + ATA_POWER_OFF_TIMEOUT )) |
651 | { | 651 | { |
652 | mutex_lock(&ata_mtx); | 652 | spinlock_lock(&ata_mtx); |
653 | ide_power_enable(false); | 653 | ide_power_enable(false); |
654 | mutex_unlock(&ata_mtx); | 654 | spinlock_unlock(&ata_mtx); |
655 | poweroff = true; | 655 | poweroff = true; |
656 | } | 656 | } |
657 | #endif | 657 | #endif |
@@ -663,11 +663,11 @@ static void ata_thread(void) | |||
663 | #ifndef USB_NONE | 663 | #ifndef USB_NONE |
664 | case SYS_USB_CONNECTED: | 664 | case SYS_USB_CONNECTED: |
665 | if (poweroff) { | 665 | if (poweroff) { |
666 | mutex_lock(&ata_mtx); | 666 | spinlock_lock(&ata_mtx); |
667 | ata_led(true); | 667 | ata_led(true); |
668 | ata_power_on(); | 668 | ata_power_on(); |
669 | ata_led(false); | 669 | ata_led(false); |
670 | mutex_unlock(&ata_mtx); | 670 | spinlock_unlock(&ata_mtx); |
671 | } | 671 | } |
672 | 672 | ||
673 | /* Tell the USB thread that we are safe */ | 673 | /* Tell the USB thread that we are safe */ |
@@ -741,11 +741,11 @@ int ata_soft_reset(void) | |||
741 | { | 741 | { |
742 | int ret; | 742 | int ret; |
743 | 743 | ||
744 | mutex_lock(&ata_mtx); | 744 | spinlock_lock(&ata_mtx); |
745 | 745 | ||
746 | ret = perform_soft_reset(); | 746 | ret = perform_soft_reset(); |
747 | 747 | ||
748 | mutex_unlock(&ata_mtx); | 748 | spinlock_unlock(&ata_mtx); |
749 | return ret; | 749 | return ret; |
750 | } | 750 | } |
751 | 751 | ||
@@ -936,7 +936,7 @@ int ata_init(void) | |||
936 | bool coldstart = ata_is_coldstart(); | 936 | bool coldstart = ata_is_coldstart(); |
937 | /* must be called before ata_device_init() */ | 937 | /* must be called before ata_device_init() */ |
938 | 938 | ||
939 | mutex_init(&ata_mtx); | 939 | spinlock_init(&ata_mtx); |
940 | 940 | ||
941 | ata_led(false); | 941 | ata_led(false); |
942 | ata_device_init(); | 942 | ata_device_init(); |
diff --git a/firmware/export/kernel.h b/firmware/export/kernel.h index ec8aa28a08..495e558175 100644 --- a/firmware/export/kernel.h +++ b/firmware/export/kernel.h | |||
@@ -83,10 +83,14 @@ struct event_queue | |||
83 | #endif | 83 | #endif |
84 | }; | 84 | }; |
85 | 85 | ||
86 | #define MTX_UNOWNED 0x00000000 | ||
87 | #define MTX_BLOCKED_WAITER 0x00000001 | ||
88 | #define MTX_SPIN_WAITER 0x00010001 | ||
89 | #define MTX_SPIN_OWNER 0x00020001 | ||
86 | struct mutex | 90 | struct mutex |
87 | { | 91 | { |
92 | uint32_t locked; | ||
88 | struct thread_entry *thread; | 93 | struct thread_entry *thread; |
89 | bool locked; | ||
90 | }; | 94 | }; |
91 | 95 | ||
92 | /* global tick variable */ | 96 | /* global tick variable */ |
@@ -126,8 +130,12 @@ extern void queue_remove_from_head(struct event_queue *q, long id); | |||
126 | extern int queue_broadcast(long id, intptr_t data); | 130 | extern int queue_broadcast(long id, intptr_t data); |
127 | 131 | ||
128 | extern void mutex_init(struct mutex *m); | 132 | extern void mutex_init(struct mutex *m); |
133 | static inline void spinlock_init(struct mutex *m) | ||
134 | { mutex_init(m); } /* Same thing for now */ | ||
129 | extern void mutex_lock(struct mutex *m); | 135 | extern void mutex_lock(struct mutex *m); |
130 | extern void mutex_unlock(struct mutex *m); | 136 | extern void mutex_unlock(struct mutex *m); |
137 | extern void spinlock_lock(struct mutex *m); | ||
138 | extern void spinlock_unlock(struct mutex *m); | ||
131 | extern void tick_start(unsigned int interval_in_ms); | 139 | extern void tick_start(unsigned int interval_in_ms); |
132 | 140 | ||
133 | #define IS_SYSEVENT(ev) ((ev & SYS_EVENT) == SYS_EVENT) | 141 | #define IS_SYSEVENT(ev) ((ev & SYS_EVENT) == SYS_EVENT) |
diff --git a/firmware/export/thread.h b/firmware/export/thread.h index 3a979722b9..7a9414c79f 100644 --- a/firmware/export/thread.h +++ b/firmware/export/thread.h | |||
@@ -105,6 +105,7 @@ struct thread_entry { | |||
105 | unsigned short stack_size; | 105 | unsigned short stack_size; |
106 | #ifdef HAVE_PRIORITY_SCHEDULING | 106 | #ifdef HAVE_PRIORITY_SCHEDULING |
107 | unsigned short priority; | 107 | unsigned short priority; |
108 | unsigned long priority_x; | ||
108 | long last_run; | 109 | long last_run; |
109 | #endif | 110 | #endif |
110 | struct thread_entry *next, *prev; | 111 | struct thread_entry *next, *prev; |
@@ -114,6 +115,10 @@ struct core_entry { | |||
114 | struct thread_entry threads[MAXTHREADS]; | 115 | struct thread_entry threads[MAXTHREADS]; |
115 | struct thread_entry *running; | 116 | struct thread_entry *running; |
116 | struct thread_entry *sleeping; | 117 | struct thread_entry *sleeping; |
118 | #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME | ||
119 | int switch_to_irq_level; | ||
120 | #define STAY_IRQ_LEVEL -1 | ||
121 | #endif | ||
117 | }; | 122 | }; |
118 | 123 | ||
119 | #ifdef HAVE_PRIORITY_SCHEDULING | 124 | #ifdef HAVE_PRIORITY_SCHEDULING |
@@ -149,7 +154,14 @@ void wakeup_thread(struct thread_entry **thread); | |||
149 | #ifdef HAVE_PRIORITY_SCHEDULING | 154 | #ifdef HAVE_PRIORITY_SCHEDULING |
150 | int thread_set_priority(struct thread_entry *thread, int priority); | 155 | int thread_set_priority(struct thread_entry *thread, int priority); |
151 | int thread_get_priority(struct thread_entry *thread); | 156 | int thread_get_priority(struct thread_entry *thread); |
152 | #endif | 157 | /* Yield that guarantees thread execution once per round regardless of |
158 | thread's scheduler priority - basically a transient realtime boost | ||
159 | without altering the scheduler's thread precedence. */ | ||
160 | void priority_yield(void); | ||
161 | #else | ||
162 | static inline void priority_yield(void) | ||
163 | { yield(); } | ||
164 | #endif /* HAVE_PRIORITY_SCHEDULING */ | ||
153 | struct thread_entry * thread_get_current(void); | 165 | struct thread_entry * thread_get_current(void); |
154 | void init_threads(void); | 166 | void init_threads(void); |
155 | int thread_stack_usage(const struct thread_entry *thread); | 167 | int thread_stack_usage(const struct thread_entry *thread); |
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 */ |
diff --git a/firmware/thread.c b/firmware/thread.c index 614286c422..8022d94862 100644 --- a/firmware/thread.c +++ b/firmware/thread.c | |||
@@ -39,11 +39,6 @@ static unsigned short highest_priority IBSS_ATTR; | |||
39 | static int boosted_threads IBSS_ATTR; | 39 | static int boosted_threads IBSS_ATTR; |
40 | #endif | 40 | #endif |
41 | 41 | ||
42 | #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME | ||
43 | #define STAY_IRQ_LEVEL -1 | ||
44 | static int switch_to_irq_level = STAY_IRQ_LEVEL; | ||
45 | #endif | ||
46 | |||
47 | /* Define to enable additional checks for blocking violations etc. */ | 42 | /* Define to enable additional checks for blocking violations etc. */ |
48 | #define THREAD_EXTRA_CHECKS | 43 | #define THREAD_EXTRA_CHECKS |
49 | 44 | ||
@@ -136,11 +131,11 @@ static inline void load_context(const void* addr) | |||
136 | "movem.l (%0),%%d0/%%d2-%%d7/%%a2-%%a7 \n" /* Load context */ | 131 | "movem.l (%0),%%d0/%%d2-%%d7/%%a2-%%a7 \n" /* Load context */ |
137 | "move.l %%d0,%%macsr \n" | 132 | "move.l %%d0,%%macsr \n" |
138 | "move.l (52,%0),%%d0 \n" /* Get start address */ | 133 | "move.l (52,%0),%%d0 \n" /* Get start address */ |
139 | "beq.b .running \n" /* NULL -> already running */ | 134 | "beq.b 1f \n" /* NULL -> already running */ |
140 | "clr.l (52,%0) \n" /* Clear start address.. */ | 135 | "clr.l (52,%0) \n" /* Clear start address.. */ |
141 | "move.l %%d0,%0 \n" | 136 | "move.l %%d0,%0 \n" |
142 | "jmp (%0) \n" /* ..and start the thread */ | 137 | "jmp (%0) \n" /* ..and start the thread */ |
143 | ".running: \n" | 138 | "1: \n" |
144 | : : "a" (addr) : "d0" /* only! */ | 139 | : : "a" (addr) : "d0" /* only! */ |
145 | ); | 140 | ); |
146 | } | 141 | } |
@@ -422,10 +417,10 @@ void switch_thread(bool save_context, struct thread_entry **blocked_list) | |||
422 | /* This has to be done after the scheduler is finished with the | 417 | /* This has to be done after the scheduler is finished with the |
423 | blocked_list pointer so that an IRQ can't kill us by attempting | 418 | blocked_list pointer so that an IRQ can't kill us by attempting |
424 | a wake but before attempting any core sleep. */ | 419 | a wake but before attempting any core sleep. */ |
425 | if (switch_to_irq_level != STAY_IRQ_LEVEL) | 420 | if (cores[CURRENT_CORE].switch_to_irq_level != STAY_IRQ_LEVEL) |
426 | { | 421 | { |
427 | int level = switch_to_irq_level; | 422 | int level = cores[CURRENT_CORE].switch_to_irq_level; |
428 | switch_to_irq_level = STAY_IRQ_LEVEL; | 423 | cores[CURRENT_CORE].switch_to_irq_level = STAY_IRQ_LEVEL; |
429 | set_irq_level(level); | 424 | set_irq_level(level); |
430 | } | 425 | } |
431 | #endif | 426 | #endif |
@@ -442,13 +437,14 @@ void switch_thread(bool save_context, struct thread_entry **blocked_list) | |||
442 | for (;;) | 437 | for (;;) |
443 | { | 438 | { |
444 | int priority = cores[CURRENT_CORE].running->priority; | 439 | int priority = cores[CURRENT_CORE].running->priority; |
445 | 440 | ||
446 | if (priority < highest_priority) | 441 | if (priority < highest_priority) |
447 | highest_priority = priority; | 442 | highest_priority = priority; |
448 | 443 | ||
449 | if (priority == highest_priority || | 444 | if (priority == highest_priority || |
450 | (current_tick - cores[CURRENT_CORE].running->last_run > | 445 | (current_tick - cores[CURRENT_CORE].running->last_run > |
451 | priority * 8)) | 446 | priority * 8) || |
447 | cores[CURRENT_CORE].running->priority_x != 0) | ||
452 | break; | 448 | break; |
453 | 449 | ||
454 | cores[CURRENT_CORE].running = cores[CURRENT_CORE].running->next; | 450 | cores[CURRENT_CORE].running = cores[CURRENT_CORE].running->next; |
@@ -567,7 +563,7 @@ void block_thread_w_tmo(struct thread_entry **list, int timeout) | |||
567 | #if defined(HAVE_EXTENDED_MESSAGING_AND_NAME) && !defined(SIMULATOR) | 563 | #if defined(HAVE_EXTENDED_MESSAGING_AND_NAME) && !defined(SIMULATOR) |
568 | void set_irq_level_and_block_thread(struct thread_entry **list, int level) | 564 | void set_irq_level_and_block_thread(struct thread_entry **list, int level) |
569 | { | 565 | { |
570 | switch_to_irq_level = level; | 566 | cores[CURRENT_CORE].switch_to_irq_level = level; |
571 | block_thread(list); | 567 | block_thread(list); |
572 | } | 568 | } |
573 | 569 | ||
@@ -575,7 +571,7 @@ void set_irq_level_and_block_thread(struct thread_entry **list, int level) | |||
575 | void set_irq_level_and_block_thread_w_tmo(struct thread_entry **list, | 571 | void set_irq_level_and_block_thread_w_tmo(struct thread_entry **list, |
576 | int timeout, int level) | 572 | int timeout, int level) |
577 | { | 573 | { |
578 | switch_to_irq_level = level; | 574 | cores[CURRENT_CORE].switch_to_irq_level = level; |
579 | block_thread_w_tmo(list, timeout); | 575 | block_thread_w_tmo(list, timeout); |
580 | } | 576 | } |
581 | #endif | 577 | #endif |
@@ -688,6 +684,7 @@ struct thread_entry* | |||
688 | thread->stack_size = stack_size; | 684 | thread->stack_size = stack_size; |
689 | thread->statearg = 0; | 685 | thread->statearg = 0; |
690 | #ifdef HAVE_PRIORITY_SCHEDULING | 686 | #ifdef HAVE_PRIORITY_SCHEDULING |
687 | thread->priority_x = 0; | ||
691 | thread->priority = priority; | 688 | thread->priority = priority; |
692 | highest_priority = 100; | 689 | highest_priority = 100; |
693 | #endif | 690 | #endif |
@@ -759,7 +756,7 @@ int thread_set_priority(struct thread_entry *thread, int priority) | |||
759 | 756 | ||
760 | if (thread == NULL) | 757 | if (thread == NULL) |
761 | thread = cores[CURRENT_CORE].running; | 758 | thread = cores[CURRENT_CORE].running; |
762 | 759 | ||
763 | old_priority = thread->priority; | 760 | old_priority = thread->priority; |
764 | thread->priority = priority; | 761 | thread->priority = priority; |
765 | highest_priority = 100; | 762 | highest_priority = 100; |
@@ -774,7 +771,15 @@ int thread_get_priority(struct thread_entry *thread) | |||
774 | 771 | ||
775 | return thread->priority; | 772 | return thread->priority; |
776 | } | 773 | } |
777 | #endif | 774 | |
775 | void priority_yield(void) | ||
776 | { | ||
777 | struct thread_entry *thread = cores[CURRENT_CORE].running; | ||
778 | thread->priority_x = 1; | ||
779 | switch_thread(true, NULL); | ||
780 | thread->priority_x = 0; | ||
781 | } | ||
782 | #endif /* HAVE_PRIORITY_SCHEDULING */ | ||
778 | 783 | ||
779 | struct thread_entry * thread_get_current(void) | 784 | struct thread_entry * thread_get_current(void) |
780 | { | 785 | { |
@@ -789,10 +794,14 @@ void init_threads(void) | |||
789 | memset(cores, 0, sizeof cores); | 794 | memset(cores, 0, sizeof cores); |
790 | cores[core].sleeping = NULL; | 795 | cores[core].sleeping = NULL; |
791 | cores[core].running = NULL; | 796 | cores[core].running = NULL; |
797 | #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME | ||
798 | cores[core].switch_to_irq_level = STAY_IRQ_LEVEL; | ||
799 | #endif | ||
792 | cores[core].threads[0].name = main_thread_name; | 800 | cores[core].threads[0].name = main_thread_name; |
793 | cores[core].threads[0].statearg = 0; | 801 | cores[core].threads[0].statearg = 0; |
794 | #ifdef HAVE_PRIORITY_SCHEDULING | 802 | #ifdef HAVE_PRIORITY_SCHEDULING |
795 | cores[core].threads[0].priority = PRIORITY_USER_INTERFACE; | 803 | cores[core].threads[0].priority = PRIORITY_USER_INTERFACE; |
804 | cores[core].threads[0].priority_x = 0; | ||
796 | highest_priority = 100; | 805 | highest_priority = 100; |
797 | #endif | 806 | #endif |
798 | #ifdef HAVE_SCHEDULER_BOOSTCTRL | 807 | #ifdef HAVE_SCHEDULER_BOOSTCTRL |