diff options
Diffstat (limited to 'firmware/thread.c')
-rw-r--r-- | firmware/thread.c | 43 |
1 files changed, 26 insertions, 17 deletions
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 |