finish exec4.7-9

This commit is contained in:
KAAAsS 2021-05-18 00:39:56 +08:00
parent 4e78127811
commit 64e90d6037
Signed by: KAAAsS
GPG Key ID: D56625F3E671882F
6 changed files with 115 additions and 6 deletions

View File

@ -13,4 +13,4 @@ define add-symbol-file-auto
end
add-symbol-file-auto ./build/kernel.img
add-symbol-file-auto ./user/build/ramdisk/testpf.bin
add-symbol-file-auto ./user/build/ramdisk/yield_single.bin

View File

@ -80,6 +80,11 @@ void handle_entry_c(int type, u64 esr, u64 address)
case ESR_EL1_EC_DABT_CEL:
do_page_fault(esr, address);
break;
case ESR_EL1_EC_IABT_LEL:
// 线程退出
if (address == 0x0) {
sys_exit(0);
}
default:
kdebug("Unsupported Exception ESR %lx\n", esr);
break;

View File

@ -51,9 +51,36 @@ struct thread idle_threads[PLAT_CPU_NUM];
*/
int rr_sched_enqueue(struct thread *thread)
{
s32 dest_core;
if (thread == NULL || thread->thread_ctx == NULL) {
return -1;
}
// 空闲线程
if (thread->thread_ctx->type == TYPE_IDLE) {
return 0;
}
// 已经进入就绪队列
if (thread->thread_ctx->state == TS_READY) {
return -1;
}
// 选择目标核心
dest_core = thread->thread_ctx->affinity;
if (dest_core == NO_AFF) {
dest_core = smp_get_cpu_id();
}
// 入队尾
list_append(&thread->ready_queue_node, &rr_ready_queue[dest_core]);
thread->thread_ctx->state = TS_READY;
thread->thread_ctx->cpuid = dest_core;
return 0;
}
/*
* Lab4
* Sched_dequeue
@ -62,9 +89,27 @@ int rr_sched_enqueue(struct thread *thread)
*/
int rr_sched_dequeue(struct thread *thread)
{
if (thread == NULL || thread->thread_ctx == NULL) {
return -1;
}
// 空闲线程
if (thread->thread_ctx->type == TYPE_IDLE) {
return -1;
}
// 状态判断
if (thread->thread_ctx->state != TS_READY) {
return -1;
}
// 出队
list_del(&thread->ready_queue_node);
thread->thread_ctx->state = TS_INTER;
return 0;
}
/*
* Lab4
* The helper function
@ -78,9 +123,27 @@ int rr_sched_dequeue(struct thread *thread)
*/
struct thread *rr_sched_choose_thread(void)
{
struct thread *result;
struct list_head *queue = &rr_ready_queue[smp_get_cpu_id()];
// 队列空
if (list_empty(queue)) {
return &idle_threads[smp_get_cpu_id()];
}
// 选择队首,注意准备队列指针并不是 thread 的开头
result = (struct thread *) (queue->next - 1);
// 出队
if (rr_sched_dequeue(result) != 0) {
return NULL;
}
kdebug("[RR] Cpu #%d Select thread %lx, sp = %lx\n",
smp_get_cpu_id(), result->thread_ctx, result->thread_ctx->ec.reg[SP_EL0]);
return result;
}
static inline void rr_sched_refill_budget(struct thread *target, u32 budget)
{
}
@ -99,9 +162,27 @@ static inline void rr_sched_refill_budget(struct thread *target, u32 budget)
*/
int rr_sched(void)
{
struct thread *dest_thread;
// 若当前有运行进程,放入队列
if (current_thread != NULL && current_thread->thread_ctx != NULL
&& current_thread->thread_ctx->type != TYPE_IDLE) {
rr_sched_enqueue(current_thread);
kdebug("[RR] Cpu #%d yield thread %lx to queue\n", smp_get_cpu_id(), current_thread->thread_ctx);
}
// 选择新线程
dest_thread = rr_sched_choose_thread();
if (dest_thread == NULL) {
return -1;
}
// 准备调度
switch_to_thread(dest_thread);
return 0;
}
/*
* Initialize the per thread queue and idle thread.
*/

View File

@ -140,6 +140,8 @@ u64 switch_context(void)
*/
void sys_yield(void)
{
sched();
eret_to_thread(switch_context());
}
int sched_init(struct sched_ops *sched_ops)

View File

@ -45,7 +45,7 @@ u32 sys_getc(void)
*/
u32 sys_get_cpu_id(void)
{
return -1;
return smp_get_cpu_id();
}
#pragma clang diagnostic push
@ -57,6 +57,11 @@ u32 sys_get_cpu_id(void)
*/
const void *syscall_table[NR_SYSCALL] = {
[0 ... NR_SYSCALL - 1] = sys_debug,
[SYS_putc] = sys_putc,
[SYS_exit] = sys_exit,
[SYS_create_pmo] = sys_create_pmo,
[SYS_map_pmo] = sys_map_pmo,
[SYS_handle_brk] = sys_handle_brk,
/* lab3 syscalls finished */
[SYS_getc] = sys_getc,

View File

@ -145,6 +145,10 @@ ELF Section、Segment 两个概念。
其实连对齐都不用,直接就干上去也行,反正之前页表的时候已经处理了没对齐的情况。
一定注意对齐!竟然在后面实验翻车了,段开头是有可能非 4k 对齐的,复制要加上偏移。
alloc_section = (char *) phys_to_virt(pmo->start) + (p_vaddr & (PAGE_SIZE - 1));
**** 初始化线程上下文
照着文字写就行,初始化 TCB
@ -195,3 +199,15 @@ boot 阶段的栈是独立的。函数也没调用几个,我猜测可能是 el
*** 练习6
原因是 unlock_kernel 后才进行从栈恢复,而且函数退出时内核栈还是空的,所以 unlock 的时候无所谓。
*** 练习7
虽然没提,但是其实状态设置、控制很重要。以及 BUG 异步输出基本和乱码一样,希望加个打印锁……
还有一个重点就是 ready_queue 不是结构体开头,所以不可以直接转成 thread *。
sys_yield 要注意必须手动调用切换上下文,不然不会有效果。因为默认的 exception_return 不考虑 current_thread。
*** 练习8
否则将无法再次在该核上进行调度。