diff options
Diffstat (limited to 'src/scheduler.c')
| -rw-r--r-- | src/scheduler.c | 96 |
1 files changed, 52 insertions, 44 deletions
diff --git a/src/scheduler.c b/src/scheduler.c index c03c20d030..353fdad5cb 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -38,19 +38,18 @@ rt_uint32_t rt_thread_ready_priority_group; #if RT_THREAD_PRIORITY_MAX > 32 /* Maximum priority level, 256 */ rt_uint8_t rt_thread_ready_table[32]; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ #ifndef RT_USING_SMP extern volatile rt_uint8_t rt_interrupt_nest; static rt_int16_t rt_scheduler_lock_nest; struct rt_thread *rt_current_thread = RT_NULL; rt_uint8_t rt_current_priority; -#endif /*RT_USING_SMP*/ - -rt_list_t rt_thread_defunct; +#endif /* RT_USING_SMP */ #ifdef RT_USING_HOOK static void (*rt_scheduler_hook)(struct rt_thread *from, struct rt_thread *to); +static void (*rt_scheduler_switch_hook)(struct rt_thread *tid); /** * @addtogroup Hook @@ -70,19 +69,25 @@ rt_scheduler_sethook(void (*hook)(struct rt_thread *from, struct rt_thread *to)) rt_scheduler_hook = hook; } +void +rt_scheduler_switch_sethook(void (*hook)(struct rt_thread *tid)) +{ + rt_scheduler_switch_hook = hook; +} + /**@}*/ -#endif +#endif /* RT_USING_HOOK */ #ifdef RT_USING_OVERFLOW_CHECK static void _rt_scheduler_stack_check(struct rt_thread *thread) { RT_ASSERT(thread != RT_NULL); -#if defined(ARCH_CPU_STACK_GROWS_UPWARD) +#ifdef ARCH_CPU_STACK_GROWS_UPWARD if (*((rt_uint8_t *)((rt_ubase_t)thread->stack_addr + thread->stack_size - 1)) != '#' || #else if (*((rt_uint8_t *)thread->stack_addr) != '#' || -#endif +#endif /* ARCH_CPU_STACK_GROWS_UPWARD */ (rt_ubase_t)thread->sp <= (rt_ubase_t)thread->stack_addr || (rt_ubase_t)thread->sp > (rt_ubase_t)thread->stack_addr + (rt_ubase_t)thread->stack_size) @@ -94,7 +99,7 @@ static void _rt_scheduler_stack_check(struct rt_thread *thread) level = rt_hw_interrupt_disable(); while (level); } -#if defined(ARCH_CPU_STACK_GROWS_UPWARD) +#ifdef ARCH_CPU_STACK_GROWS_UPWARD else if ((rt_ubase_t)thread->sp > ((rt_ubase_t)thread->stack_addr + thread->stack_size)) { rt_kprintf("warning: %s stack is close to the top of stack address.\n", @@ -106,9 +111,9 @@ static void _rt_scheduler_stack_check(struct rt_thread *thread) rt_kprintf("warning: %s stack is close to end of stack address.\n", thread->name); } -#endif +#endif /* ARCH_CPU_STACK_GROWS_UPWARD */ } -#endif +#endif /* RT_USING_OVERFLOW_CHECK */ /* * get the highest priority thread in ready queue @@ -129,7 +134,7 @@ static struct rt_thread* _get_highest_priority_thread(rt_ubase_t *highest_prio) #else highest_ready_priority = __rt_ffs(rt_thread_ready_priority_group) - 1; local_highest_ready_priority = __rt_ffs(pcpu->priority_group) - 1; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ /* get highest ready priority thread */ if (highest_ready_priority < local_highest_ready_priority) @@ -162,7 +167,7 @@ static struct rt_thread* _get_highest_priority_thread(rt_ubase_t *highest_prio) highest_ready_priority = (number << 3) + __rt_ffs(rt_thread_ready_table[number]) - 1; #else highest_ready_priority = __rt_ffs(rt_thread_ready_priority_group) - 1; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ /* get highest ready priority thread */ highest_priority_thread = rt_list_entry(rt_thread_priority_table[highest_ready_priority].next, @@ -173,7 +178,7 @@ static struct rt_thread* _get_highest_priority_thread(rt_ubase_t *highest_prio) return highest_priority_thread; } -#endif +#endif /* RT_USING_SMP */ /** * @ingroup SystemInit @@ -183,12 +188,12 @@ void rt_system_scheduler_init(void) { #ifdef RT_USING_SMP int cpu; -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ register rt_base_t offset; #ifndef RT_USING_SMP rt_scheduler_lock_nest = 0; -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("start scheduler: max priority 0x%02x\n", RT_THREAD_PRIORITY_MAX)); @@ -213,9 +218,9 @@ void rt_system_scheduler_init(void) #if RT_THREAD_PRIORITY_MAX > 32 rt_memset(pcpu->ready_table, 0, sizeof(pcpu->ready_table)); -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ } -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ /* initialize ready priority group */ rt_thread_ready_priority_group = 0; @@ -223,10 +228,7 @@ void rt_system_scheduler_init(void) #if RT_THREAD_PRIORITY_MAX > 32 /* initialize ready table */ rt_memset(rt_thread_ready_table, 0, sizeof(rt_thread_ready_table)); -#endif - - /* initialize thread defunct */ - rt_list_init(&rt_thread_defunct); +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ } /** @@ -245,7 +247,7 @@ void rt_system_scheduler_start(void) to_thread->oncpu = rt_hw_cpu_id(); #else rt_current_thread = to_thread; -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ rt_schedule_remove_thread(to_thread); to_thread->stat = RT_THREAD_RUNNING; @@ -255,7 +257,7 @@ void rt_system_scheduler_start(void) rt_hw_context_switch_to((rt_ubase_t)&to_thread->sp, to_thread); #else rt_hw_context_switch_to((rt_ubase_t)&to_thread->sp); -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ /* never come back */ } @@ -319,7 +321,7 @@ void rt_schedule(void) rt_thread_resume(current_thread); } } -#endif +#endif /* RT_USING_SIGNALS */ if (current_thread->scheduler_lock_nest == 1) /* whether lock scheduler */ { @@ -367,7 +369,9 @@ void rt_schedule(void) #ifdef RT_USING_OVERFLOW_CHECK _rt_scheduler_stack_check(to_thread); -#endif +#endif /* RT_USING_OVERFLOW_CHECK */ + + RT_OBJECT_HOOK_CALL(rt_scheduler_switch_hook, (current_thread)); rt_hw_context_switch((rt_ubase_t)¤t_thread->sp, (rt_ubase_t)&to_thread->sp, to_thread); @@ -396,7 +400,7 @@ void rt_schedule(void) { rt_hw_interrupt_enable(level); } -#endif +#endif /* RT_USING_SIGNALS */ __exit: return ; @@ -404,7 +408,7 @@ __exit: #else /** * This function will perform one schedule. It will select one thread - * with the highest priority level, then switch to it. + * with the highest priority level, and switch to it immediately. */ void rt_schedule(void) { @@ -472,12 +476,14 @@ void rt_schedule(void) #ifdef RT_USING_OVERFLOW_CHECK _rt_scheduler_stack_check(to_thread); -#endif +#endif /* RT_USING_OVERFLOW_CHECK */ if (rt_interrupt_nest == 0) { extern void rt_thread_handle_sig(rt_bool_t clean_state); + RT_OBJECT_HOOK_CALL(rt_scheduler_switch_hook, (from_thread)); + rt_hw_context_switch((rt_ubase_t)&from_thread->sp, (rt_ubase_t)&to_thread->sp); @@ -502,7 +508,7 @@ void rt_schedule(void) { rt_hw_interrupt_enable(level); } -#endif +#endif /* RT_USING_SIGNALS */ goto __exit; } else @@ -527,7 +533,7 @@ void rt_schedule(void) __exit: return; } -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ /** * This function checks if a scheduling is needed after IRQ context. If yes, @@ -559,7 +565,7 @@ void rt_scheduler_do_irq_switch(void *context) rt_thread_resume(current_thread); } } -#endif +#endif /* RT_USING_SIGNALS */ if (pcpu->irq_switch_flag == 0) { @@ -608,12 +614,14 @@ void rt_scheduler_do_irq_switch(void *context) #ifdef RT_USING_OVERFLOW_CHECK _rt_scheduler_stack_check(to_thread); -#endif +#endif /* RT_USING_OVERFLOW_CHECK */ RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("switch in interrupt\n")); current_thread->cpus_lock_nest--; current_thread->scheduler_lock_nest--; + RT_OBJECT_HOOK_CALL(rt_scheduler_switch_hook, (current_thread)); + rt_hw_context_switch_interrupt(context, (rt_ubase_t)¤t_thread->sp, (rt_ubase_t)&to_thread->sp, to_thread); } @@ -621,7 +629,7 @@ void rt_scheduler_do_irq_switch(void *context) } rt_hw_interrupt_enable(level); } -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ /* * This function will insert a thread to system ready queue. The state of @@ -661,7 +669,7 @@ void rt_schedule_insert_thread(struct rt_thread *thread) { #if RT_THREAD_PRIORITY_MAX > 32 rt_thread_ready_table[thread->number] |= thread->high_mask; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ rt_thread_ready_priority_group |= thread->number_mask; rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]), @@ -675,7 +683,7 @@ void rt_schedule_insert_thread(struct rt_thread *thread) #if RT_THREAD_PRIORITY_MAX > 32 pcpu->ready_table[thread->number] |= thread->high_mask; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ pcpu->priority_group |= thread->number_mask; rt_list_insert_before(&(rt_cpu_index(bind_cpu)->priority_table[thread->current_priority]), @@ -724,14 +732,14 @@ void rt_schedule_insert_thread(struct rt_thread *thread) /* set priority mask */ #if RT_THREAD_PRIORITY_MAX > 32 rt_thread_ready_table[thread->number] |= thread->high_mask; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ rt_thread_ready_priority_group |= thread->number_mask; __exit: /* enable interrupt */ rt_hw_interrupt_enable(temp); } -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ /* * This function will remove a thread from system ready queue. @@ -768,7 +776,7 @@ void rt_schedule_remove_thread(struct rt_thread *thread) } #else rt_thread_ready_priority_group &= ~thread->number_mask; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ } } else @@ -785,7 +793,7 @@ void rt_schedule_remove_thread(struct rt_thread *thread) } #else pcpu->priority_group &= ~thread->number_mask; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ } } @@ -818,13 +826,13 @@ void rt_schedule_remove_thread(struct rt_thread *thread) } #else rt_thread_ready_priority_group &= ~thread->number_mask; -#endif +#endif /* RT_THREAD_PRIORITY_MAX > 32 */ } /* enable interrupt */ rt_hw_interrupt_enable(level); } -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ /** * This function will lock the thread scheduler. @@ -885,7 +893,7 @@ void rt_enter_critical(void) /* enable interrupt */ rt_hw_interrupt_enable(level); } -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ RTM_EXPORT(rt_enter_critical); /** @@ -959,7 +967,7 @@ void rt_exit_critical(void) rt_hw_interrupt_enable(level); } } -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ RTM_EXPORT(rt_exit_critical); /** @@ -975,7 +983,7 @@ rt_uint16_t rt_critical_level(void) return current_thread->critical_lock_nest; #else return rt_scheduler_lock_nest; -#endif /*RT_USING_SMP*/ +#endif /* RT_USING_SMP */ } RTM_EXPORT(rt_critical_level); |
