* NOTE: not in doxygen due to these info. are special for MP version * @details This function performs the following operations: * - Disables interrupts to enter critical section * - Gets current CPU and thread context * - Checks if called from interrupt context * - Finds highest priority ready thread * - Performs context switch if needed * - Processes pending signals * - Res
| 919 | * - Restores interrupt state |
| 920 | */ |
| 921 | void rt_schedule(void) |
| 922 | { |
| 923 | rt_base_t level; |
| 924 | struct rt_thread *to_thread; |
| 925 | struct rt_thread *current_thread; |
| 926 | struct rt_cpu *pcpu; |
| 927 | int cpu_id; |
| 928 | |
| 929 | /* enter ciritical region of percpu scheduling context */ |
| 930 | level = rt_hw_local_irq_disable(); |
| 931 | |
| 932 | /* get percpu scheduling context */ |
| 933 | cpu_id = rt_hw_cpu_id(); |
| 934 | pcpu = rt_cpu_index(cpu_id); |
| 935 | current_thread = pcpu->current_thread; |
| 936 | |
| 937 | /* whether do switch in interrupt */ |
| 938 | if (rt_atomic_load(&(pcpu->irq_nest))) |
| 939 | { |
| 940 | pcpu->irq_switch_flag = 1; |
| 941 | rt_hw_local_irq_enable(level); |
| 942 | return ; /* -RT_ESCHEDISR */ |
| 943 | } |
| 944 | |
| 945 | /* forbid any recursive entries of schedule() */ |
| 946 | SCHEDULER_ENTER_CRITICAL(current_thread); |
| 947 | |
| 948 | /* prepare current_thread for processing if signals existed */ |
| 949 | SCHED_THREAD_PREPROCESS_SIGNAL(pcpu, current_thread); |
| 950 | |
| 951 | /* whether caller had locked the local scheduler already */ |
| 952 | if (RT_SCHED_CTX(current_thread).critical_lock_nest > 1) |
| 953 | { |
| 954 | SET_CRITICAL_SWITCH_FLAG(pcpu, current_thread); |
| 955 | |
| 956 | SCHEDULER_EXIT_CRITICAL(current_thread); |
| 957 | |
| 958 | /* -RT_ESCHEDLOCKED */ |
| 959 | } |
| 960 | else |
| 961 | { |
| 962 | /* flush critical switch flag since a scheduling is done */ |
| 963 | CLR_CRITICAL_SWITCH_FLAG(pcpu, current_thread); |
| 964 | pcpu->irq_switch_flag = 0; |
| 965 | |
| 966 | /* |
| 967 | * take the context lock before we do the real scheduling works. Context |
| 968 | * lock will be released before returning from this _schedule_locked() |
| 969 | */ |
| 970 | SCHEDULER_CONTEXT_LOCK(pcpu); |
| 971 | |
| 972 | /* pick the highest runnable thread, and pass the control to it */ |
| 973 | to_thread = _prepare_context_switch_locked(cpu_id, pcpu, current_thread); |
| 974 | |
| 975 | if (to_thread) |
| 976 | { |
| 977 | LOG_D("[cpu#%d] switch to priority#%d " |
| 978 | "thread:%.*s(sp:0x%08x), " |
no test coverage detected