1 /** 2 * @file process.h 3 * @author longjin 4 * @brief 进程 5 * @date 2022-01-29 6 * 7 * @copyright Copyright (c) 2022 8 * 9 */ 10 11 #pragma once 12 #include "ptrace.h" 13 #include <common/cpu.h> 14 #include <common/errno.h> 15 #include <common/glib.h> 16 #include <common/wait_queue.h> 17 #include <filesystem/vfs/VFS.h> 18 #include <mm/mm-types.h> 19 #include <syscall/syscall.h> 20 21 #include <asm/current.h> 22 23 #include "proc-types.h" 24 25 extern void process_exit_thread(struct process_control_block *pcb); 26 extern int process_exit_files(struct process_control_block *pcb); 27 28 /** 29 * @brief 任务状态段结构体 30 * 31 */ 32 33 // 设置初始进程的tss 34 #define INITIAL_TSS \ 35 { \ 36 .reserved0 = 0, .rsp0 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), \ 37 .rsp1 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), \ 38 .rsp2 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), .reserved1 = 0, .ist1 = 0xffff800000007c00, \ 39 .ist2 = 0xffff800000007c00, .ist3 = 0xffff800000007c00, .ist4 = 0xffff800000007c00, \ 40 .ist5 = 0xffff800000007c00, .ist6 = 0xffff800000007c00, .ist7 = 0xffff800000007c00, .reserved2 = 0, \ 41 .reserved3 = 0, .io_map_base_addr = 0 \ 42 } 43 44 #define GET_CURRENT_PCB \ 45 "movq %rsp, %rbx \n\t" \ 46 "andq $-32768, %rbx\n\t" 47 48 /** 49 * @brief 切换进程上下文 50 * 先把rbp和rax保存到栈中,然后将rsp和rip保存到prev的thread结构体中 51 * 然后调用__switch_to切换栈,配置其他信息,最后恢复下一个进程的rax rbp。 52 */ 53 54 #define switch_to(prev, next) \ 55 do \ 56 { \ 57 __asm__ __volatile__("pushq %%rbp \n\t" \ 58 "pushq %%rax \n\t" \ 59 "movq %%rsp, %0 \n\t" \ 60 "movq %2, %%rsp \n\t" \ 61 "leaq 2f(%%rip), %%rax \n\t" \ 62 "movq %%rax, %1 \n\t" \ 63 "pushq %3 \n\t" \ 64 "jmp __switch_to \n\t" \ 65 "2: \n\t" \ 66 "popq %%rax \n\t" \ 67 "popq %%rbp \n\t" \ 68 : "=m"(prev->thread->rsp), "=m"(prev->thread->rip) \ 69 : "m"(next->thread->rsp), "m"(next->thread->rip), "D"(prev), "S"(next) \ 70 : "memory", "rax"); \ 71 } while (0) 72 73 /** 74 * @brief 初始化系统的第一个进程 75 * 76 */ 77 void process_init(); 78 79 /** 80 * @brief fork当前进程 81 * 82 * @param regs 新的寄存器值 83 * @param clone_flags 克隆标志 84 * @param stack_start 堆栈开始地址 85 * @param stack_size 堆栈大小 86 * @return unsigned long 87 */ 88 unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned long stack_start, 89 unsigned long stack_size); 90 91 /** 92 * @brief 根据pid获取进程的pcb。存在对应的pcb时,返回对应的pcb的指针,否则返回NULL 93 * 当进程管理模块拥有pcblist_lock之后,调用本函数之前,应当对其加锁 94 * @param pid 95 * @return struct process_control_block* 96 */ 97 struct process_control_block *process_find_pcb_by_pid(pid_t pid); 98 99 /** 100 * @brief 将进程加入到调度器的就绪队列中 101 * 102 * @param pcb 进程的pcb 103 * 104 * @return 如果进程被成功唤醒,则返回1,如果进程正在运行,则返回0.如果pcb为NULL,则返回-EINVAL 105 */ 106 int process_wakeup(struct process_control_block *pcb); 107 108 /** 109 * @brief 将进程加入到调度器的就绪队列中,并标志当前进程需要被调度 110 * 111 * @param pcb 进程的pcb 112 */ 113 int process_wakeup_immediately(struct process_control_block *pcb); 114 115 /** 116 * @brief 释放进程的页表 117 * 118 * @param pcb 要被释放页表的进程 119 * @return uint64_t 120 */ 121 uint64_t process_exit_mm(struct process_control_block *pcb); 122 123 /** 124 * @brief 进程退出时执行的函数 125 * 126 * @param code 返回码 127 * @return ul 128 */ 129 ul process_do_exit(ul code); 130 131 /** 132 * @brief 当子进程退出后向父进程发送通知 133 * 134 */ 135 void process_exit_notify(); 136 137 /** 138 * @brief 初始化内核进程 139 * 140 * @param fn 目标程序的地址 141 * @param arg 向目标程序传入的参数 142 * @param flags 143 * @return int 144 */ 145 146 pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); 147 148 int process_fd_alloc(struct vfs_file_t *file); 149 150 int process_release_pcb(struct process_control_block *pcb); 151 152 /** 153 * @brief 切换页表 154 * @param prev 前一个进程的pcb 155 * @param next 下一个进程的pcb 156 * 157 */ 158 #define process_switch_mm(next_pcb) \ 159 do \ 160 { \ 161 asm volatile("movq %0, %%cr3 \n\t" ::"r"(next_pcb->mm->pgd) \ 162 : "memory"); \ 163 } while (0) 164 // flush_tlb(); 165 166 // 获取当前cpu id 167 #define proc_current_cpu_id (current_pcb->cpu_id) 168 169 extern unsigned long head_stack_start; // 导出内核层栈基地址(定义在head.S) 170 extern ul _stack_start; 171 extern void ret_from_intr(void); // 导出从中断返回的函数(定义在entry.S) 172 173 extern struct tss_struct initial_tss[MAX_CPU_NUM]; 174 extern struct mm_struct initial_mm; 175 extern struct thread_struct initial_thread; 176 extern union proc_union initial_proc_union; 177 extern struct process_control_block *initial_proc[MAX_CPU_NUM]; 178 179 /** 180 * @brief 给pcb设置名字 181 * 182 * @param pcb 需要设置名字的pcb 183 * @param pcb_name 保存名字的char数组 184 */ 185 void process_set_pcb_name(struct process_control_block *pcb, const char *pcb_name); 186 187 /** 188 * @brief 判断进程是否已经停止 189 * 190 * hint: 本函数在rust中实现,请参考rust版本的注释 191 * 192 * @param pcb 目标pcb 193 * @return true 194 * @return false 195 */ 196 extern bool process_is_stopped(struct process_control_block *pcb); 197 198 /** 199 * @brief 尝试唤醒指定的进程。 200 * 本函数的行为:If (@_state & @pcb->state) @pcb->state = TASK_RUNNING. 201 * 202 * hint: 本函数在rust中实现,请参考rust版本的注释 203 */ 204 extern int process_try_to_wake_up(struct process_control_block *_pcb, uint64_t _state, int32_t _wake_flags); 205 206 /** @brief 当进程,满足 (@state & @pcb->state)时,唤醒进程,并设置: @pcb->state = TASK_RUNNING. 207 * 208 * hint: 本函数在rust中实现,请参考rust版本的注释 209 * @return true 唤醒成功 210 * @return false 唤醒失败 211 */ 212 extern int process_wake_up_state(struct process_control_block *pcb, uint64_t state); 213 void __switch_to(struct process_control_block *prev, struct process_control_block *next); 214