📄 scheduler.c.svn-base
字号:
/* * File : scheduler.c * This file is part of RT-Thread RTOS * COPYRIGHT (C) 2006, RT-Thread Development Team * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.fayfayspace.org/license/LICENSE. * * Change Logs: * Date Author Notes * 2006-03-17 Bernard the first version * 2006-04-28 Bernard fix the scheduler algorthm * 2006-04-30 Bernard add SCHEDULER_DEBUG * 2006-05-27 Bernard fix the scheduler algorthm for same priority thread * schedule * 2006-06-04 Bernard rewrite the scheduler algorithm *//** * @addtogroup Kernel *//*@{*/#include <rtthread.h>#include <rthw.h>#include "kservice.h"// #define SCHEDULER_DEBUGstatic rt_int16 rt_scheduler_lock_nest;extern rt_uint32 rt_interrupt_nest;rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];struct rt_thread* rt_current_thread;rt_uint8 rt_current_priority;rt_uint32 rt_thread_ready_priority_group;rt_uint8 rt_thread_ready_table[32];rt_uint8 rt_lowest_bitmap[] ={ /* 00 */ 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 10 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 20 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 30 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 40 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 50 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 60 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 70 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 80 */ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 90 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* A0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* B0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* C0 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* D0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* E0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* F0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};void rt_system_scheduler_init(){ register rt_base_t offset; rt_scheduler_lock_nest = 0; for (offset = 0; offset < RT_THREAD_PRIORITY_MAX; offset ++) { rt_list_init(&rt_thread_priority_table[offset]); } rt_current_priority = RT_THREAD_PRIORITY_MAX - 1; rt_current_thread = RT_NULL; /* init ready priority group */ rt_thread_ready_priority_group = 0; /* init ready table */ rt_memset(rt_thread_ready_table, 0, sizeof(rt_thread_ready_table));}/** * @brief do a thread-schedule * * This function will perform one schedule. It will select one thread * with highest priority, then switch to it. */void rt_schedule(){ register rt_uint8 number; register rt_base_t level; register rt_uint8 highest_ready_priority; struct rt_thread *to_thread; struct rt_thread *from_thread; /* disable interrupt */ level = rt_hw_interrupt_disable(); /* check the scheduler is enabled or not */ if(rt_scheduler_lock_nest == 0) { /* find out the highest priority task */ if (rt_thread_ready_priority_group & 0xff) { number = rt_lowest_bitmap[rt_thread_ready_priority_group & 0xff]; } else if (rt_thread_ready_priority_group & 0xff00) { number = rt_lowest_bitmap[(rt_thread_ready_priority_group >> 8) & 0xff] + 8; } else if (rt_thread_ready_priority_group & 0xff0000) { number = rt_lowest_bitmap[(rt_thread_ready_priority_group >> 16) & 0xff] + 16; } else { number = rt_lowest_bitmap[(rt_thread_ready_priority_group >> 24) & 0xff] + 24; } highest_ready_priority = (number << 3) + rt_lowest_bitmap[rt_thread_ready_table[number]]; /* get switch to thread */ to_thread = rt_list_entry(rt_thread_priority_table[highest_ready_priority].next, struct rt_thread, tlist); /* if the destination thread is not the same as current thread */ if (to_thread != rt_current_thread) { rt_current_priority = highest_ready_priority; from_thread = rt_current_thread; rt_current_thread = to_thread; /* switch to new thread */#ifdef SCHEDULER_DEBUG rt_kprintf("switch to priority#%d thread:%s\n", highest_ready_priority, to_thread->name);#endif if (rt_interrupt_nest == 0) { rt_hw_context_switch((rt_uint32)&from_thread->sp, (rt_uint32)&to_thread->sp); } else {#ifdef SCHEDULER_DEBUG rt_kprintf("switch in interrupt\n");#endif rt_hw_context_switch_interrupt((rt_uint32)&from_thread->sp, (rt_uint32)&to_thread->sp); } } } /* enable interrupt */ rt_hw_interrupt_enable(level);}void rt_schedule_insert_thread(struct rt_thread* thread){ register rt_base_t temp; RT_ASSERT(thread != RT_NULL); /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* insert thread to ready list */ rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]), &(thread->tlist)); /* set priority mask */#ifdef SCHEDULER_DEBUG rt_kprintf("insert thread, the priority: %d 0x%x %d\n", thread->number, thread->number_mask, thread->high_mask);#endif rt_thread_ready_table[thread->number] |= thread->high_mask; rt_thread_ready_priority_group |= thread->number_mask; /* enable interrupt */ rt_hw_interrupt_enable(temp);}void rt_schedule_remove_thread(struct rt_thread* thread){ register rt_base_t temp; RT_ASSERT(thread != RT_NULL); /* disable interrupt */ temp = rt_hw_interrupt_disable();#ifdef SCHEDULER_DEBUG rt_kprintf("remove thread, the priority: %d 0x%x %d\n", thread->number, thread->number_mask, thread->high_mask);#endif /* remove thread from ready list */ rt_list_remove(&(thread->tlist)); if (rt_list_isempty(&(rt_thread_priority_table[thread->current_priority]))) { rt_thread_ready_table[thread->number] &= ~thread->high_mask; if (rt_thread_ready_table[thread->number] == 0) { rt_thread_ready_priority_group &= ~thread->number_mask; } } /* enable interrupt */ rt_hw_interrupt_enable(temp);}/** * @brief lock thread scheduler * * This function will lock thread scheduler. */void rt_enter_critical(){ register rt_base_t level; /* disable interrupt */ level = rt_hw_interrupt_disable(); if (rt_scheduler_lock_nest < 255u) rt_scheduler_lock_nest++; /* enable interrupt */ rt_hw_interrupt_enable(level);}/** * @brief unlock thread scheduler * * This function will unlock thread scheduler. */void rt_exit_critical(){ register rt_base_t level; /* disable interrupt */ level = rt_hw_interrupt_disable(); rt_scheduler_lock_nest --; if (rt_scheduler_lock_nest <= 0) { rt_scheduler_lock_nest = 0; rt_schedule(); } else { /* enable interrupt */ rt_hw_interrupt_enable(level); }}/*@}*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -