171 lines
4.1 KiB
C
171 lines
4.1 KiB
C
/*
|
|
* Copyright (c) 2020 Institute of Parallel And Distributed Systems (IPADS), Shanghai Jiao Tong University (SJTU)
|
|
* OS-Lab-2020 (i.e., ChCore) is licensed under the Mulan PSL v1.
|
|
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
* You may obtain a copy of Mulan PSL v1 at:
|
|
* http://license.coscl.org.cn/MulanPSL
|
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
|
|
* PURPOSE.
|
|
* See the Mulan PSL v1 for more details.
|
|
*/
|
|
|
|
/* Scheduler related functions are implemented here */
|
|
#include <sched/sched.h>
|
|
#include <common/smp.h>
|
|
#include <common/kprint.h>
|
|
#include <common/machine.h>
|
|
#include <common/kmalloc.h>
|
|
#include <common/list.h>
|
|
#include <common/util.h>
|
|
#include <process/thread.h>
|
|
#include <common/macro.h>
|
|
#include <common/errno.h>
|
|
#include <process/thread.h>
|
|
#include <exception/exception.h>
|
|
#include <sched/context.h>
|
|
|
|
struct thread *current_threads[PLAT_CPU_NUM];
|
|
|
|
/* Chosen Scheduling Policies */
|
|
struct sched_ops *cur_sched_ops;
|
|
|
|
char thread_type[][TYPE_STR_LEN] = {
|
|
"IDLE ",
|
|
"ROOT ",
|
|
"USER ",
|
|
"SHADOW",
|
|
"KERNEL",
|
|
"TESTS "
|
|
};
|
|
|
|
char thread_state[][STATE_STR_LEN] = {
|
|
"TS_INIT ",
|
|
"TS_READY ",
|
|
"TS_INTER ",
|
|
"TS_RUNNING ",
|
|
"TS_EXIT ",
|
|
"TS_WAITING ",
|
|
"TS_EXITING "
|
|
};
|
|
|
|
void arch_idle_ctx_init(struct thread_ctx *idle_ctx, void (*func) (void))
|
|
{
|
|
/* Initialize to run the function `idle_thread_routine` */
|
|
int i = 0;
|
|
arch_exec_cont_t *ec = &(idle_ctx->ec);
|
|
|
|
/* X0-X30 all zero */
|
|
for (i = 0; i < REG_NUM; i++)
|
|
ec->reg[i] = 0;
|
|
/* SPSR_EL1 => Exit to EL1 */
|
|
ec->reg[SPSR_EL1] = SPSR_EL1_KERNEL;
|
|
/* ELR_EL1 => Next PC */
|
|
ec->reg[ELR_EL1] = (u64) func;
|
|
}
|
|
|
|
void print_thread(struct thread *thread)
|
|
{
|
|
printk
|
|
("Thread %p\tType: %s\tState: %s\tCPU %d\tAFF %d\tBudget %d\tPrio: %d\t\n",
|
|
thread, thread_type[thread->thread_ctx->type],
|
|
thread_state[thread->thread_ctx->state], thread->thread_ctx->cpuid,
|
|
thread->thread_ctx->affinity, thread->thread_ctx->sc->budget,
|
|
thread->thread_ctx->prio);
|
|
}
|
|
|
|
int sched_is_running(struct thread *target)
|
|
{
|
|
BUG_ON(!target);
|
|
BUG_ON(!target->thread_ctx);
|
|
|
|
if (target->thread_ctx->state == TS_RUNNING)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Switch Thread to the specified one.
|
|
* Set the correct thread state to running and the current_thread
|
|
*/
|
|
int switch_to_thread(struct thread *target)
|
|
{
|
|
BUG_ON(!target);
|
|
BUG_ON(!target->thread_ctx);
|
|
BUG_ON((target->thread_ctx->state == TS_READY));
|
|
|
|
target->thread_ctx->cpuid = smp_get_cpu_id();
|
|
target->thread_ctx->state = TS_RUNNING;
|
|
smp_wmb();
|
|
current_thread = target;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Switch vmspace and arch-related stuff
|
|
* Return the context pointer which should be set to stack pointer register
|
|
*/
|
|
u64 switch_context(void)
|
|
{
|
|
struct thread *target_thread;
|
|
struct thread_ctx *target_ctx;
|
|
|
|
target_thread = current_thread;
|
|
BUG_ON(!target_thread);
|
|
BUG_ON(!target_thread->thread_ctx);
|
|
|
|
target_ctx = target_thread->thread_ctx;
|
|
|
|
/* These 3 types of thread do not have vmspace */
|
|
if (target_thread->thread_ctx->type != TYPE_IDLE &&
|
|
target_thread->thread_ctx->type != TYPE_KERNEL &&
|
|
target_thread->thread_ctx->type != TYPE_TESTS) {
|
|
|
|
BUG_ON(!target_thread->vmspace);
|
|
/*
|
|
* Recording the CPU the thread runs on: for TLB maintenance.
|
|
* switch_context is always required for running a (new) thread.
|
|
* So, we invoke record_running_cpu here.
|
|
*/
|
|
BUG_ON(!target_thread->vmspace);
|
|
switch_thread_vmspace_to(target_thread);
|
|
}
|
|
/*
|
|
* Lab3: Your code here
|
|
* Return the correct value in order to make eret_to_thread work correctly
|
|
* in main.c
|
|
*/
|
|
return (u64) &target_ctx->ec;
|
|
}
|
|
|
|
/* SYSCALL functions */
|
|
|
|
/**
|
|
* Lab4
|
|
* Finish the sys_yield function
|
|
*/
|
|
void sys_yield(void)
|
|
{
|
|
// 重置预算
|
|
current_thread->thread_ctx->sc->budget = 0;
|
|
|
|
// 调度
|
|
sched();
|
|
eret_to_thread(switch_context());
|
|
}
|
|
|
|
void sys_top(void)
|
|
{
|
|
cur_sched_ops->sched_top();
|
|
}
|
|
|
|
int sched_init(struct sched_ops *sched_ops)
|
|
{
|
|
BUG_ON(sched_ops == NULL);
|
|
|
|
cur_sched_ops = sched_ops;
|
|
cur_sched_ops->sched_init();
|
|
return 0;
|
|
}
|