xref: /DragonOS/kernel/src/process/process.h (revision 3d729e2069e01ee07525ff83167566dac5322a40)
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 // 设置初始进程的PCB
26 #define INITIAL_PROC(proc)                                                                                             \
27     {                                                                                                                  \
28         .state = PROC_UNINTERRUPTIBLE, .flags = PF_KTHREAD, .preempt_count = 0, .signal = 0, .cpu_id = 0,              \
29         .mm = &initial_mm, .thread = &initial_thread, .addr_limit = 0xffffffffffffffff, .pid = 0, .priority = 2,       \
30         .virtual_runtime = 0, .fds = {0}, .next_pcb = &proc, .prev_pcb = &proc, .parent_pcb = &proc, .exit_code = 0,    \
31         .wait_child_proc_exit = 0, .worker_private = NULL, .policy = SCHED_NORMAL                                      \
32     }
33 
34 /**
35  * @brief 任务状态段结构体
36  *
37  */
38 
39 // 设置初始进程的tss
40 #define INITIAL_TSS                                                                                                    \
41     {                                                                                                                  \
42         .reserved0 = 0, .rsp0 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)),                              \
43         .rsp1 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)),                                              \
44         .rsp2 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), .reserved1 = 0, .ist1 = 0xffff800000007c00,  \
45         .ist2 = 0xffff800000007c00, .ist3 = 0xffff800000007c00, .ist4 = 0xffff800000007c00,                            \
46         .ist5 = 0xffff800000007c00, .ist6 = 0xffff800000007c00, .ist7 = 0xffff800000007c00, .reserved2 = 0,            \
47         .reserved3 = 0, .io_map_base_addr = 0                                                                          \
48     }
49 
50 #define GET_CURRENT_PCB                                                                                                \
51     "movq %rsp, %rbx \n\t"                                                                                             \
52     "andq $-32768, %rbx\n\t"
53 
54 /**
55  * @brief 切换进程上下文
56  * 先把rbp和rax保存到栈中,然后将rsp和rip保存到prev的thread结构体中
57  * 然后调用__switch_to切换栈,配置其他信息,最后恢复下一个进程的rax rbp。
58  */
59 
60 #define switch_proc(prev, next)                                                                                        \
61     do                                                                                                                 \
62     {                                                                                                                  \
63         __asm__ __volatile__("pushq	%%rbp	\n\t"                                                                        \
64                              "pushq	%%rax	\n\t"                                                                        \
65                              "movq	%%rsp,	%0	\n\t"                                                                     \
66                              "movq	%2,	%%rsp	\n\t"                                                                     \
67                              "leaq	switch_proc_ret_addr(%%rip),	%%rax	\n\t"                                            \
68                              "movq	%%rax,	%1	\n\t"                                                                     \
69                              "pushq	%3		\n\t"                                                                          \
70                              "jmp	__switch_to	\n\t"                                                                    \
71                              "switch_proc_ret_addr:	\n\t"                                                              \
72                              "popq	%%rax	\n\t"                                                                         \
73                              "popq	%%rbp	\n\t"                                                                         \
74                              : "=m"(prev->thread->rsp), "=m"(prev->thread->rip)                                        \
75                              : "m"(next->thread->rsp), "m"(next->thread->rip), "D"(prev), "S"(next)                    \
76                              : "memory");                                                                              \
77     } while (0)
78 
79 /**
80  * @brief 初始化系统的第一个进程
81  *
82  */
83 void process_init();
84 
85 /**
86  * @brief fork当前进程
87  *
88  * @param regs 新的寄存器值
89  * @param clone_flags 克隆标志
90  * @param stack_start 堆栈开始地址
91  * @param stack_size 堆栈大小
92  * @return unsigned long
93  */
94 unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned long stack_start,
95                       unsigned long stack_size);
96 
97 /**
98  * @brief 根据pid获取进程的pcb。存在对应的pcb时,返回对应的pcb的指针,否则返回NULL
99  *
100  * @param pid
101  * @return struct process_control_block*
102  */
103 struct process_control_block *process_find_pcb_by_pid(pid_t pid);
104 
105 /**
106  * @brief 将进程加入到调度器的就绪队列中
107  *
108  * @param pcb 进程的pcb
109  */
110 int process_wakeup(struct process_control_block *pcb);
111 
112 /**
113  * @brief 将进程加入到调度器的就绪队列中,并标志当前进程需要被调度
114  *
115  * @param pcb 进程的pcb
116  */
117 int process_wakeup_immediately(struct process_control_block *pcb);
118 
119 /**
120  * @brief 使当前进程去执行新的代码
121  *
122  * @param regs 当前进程的寄存器
123  * @param path 可执行程序的路径
124  * @param argv 参数列表
125  * @param envp 环境变量
126  * @return ul 错误码
127  */
128 ul do_execve(struct pt_regs *regs, char *path, char *argv[], char *envp[]);
129 
130 /**
131  * @brief 释放进程的页表
132  *
133  * @param pcb 要被释放页表的进程
134  * @return uint64_t
135  */
136 uint64_t process_exit_mm(struct process_control_block *pcb);
137 
138 /**
139  * @brief 进程退出时执行的函数
140  *
141  * @param code 返回码
142  * @return ul
143  */
144 ul process_do_exit(ul code);
145 
146 /**
147  * @brief 当子进程退出后向父进程发送通知
148  *
149  */
150 void process_exit_notify();
151 
152 /**
153  * @brief 初始化内核进程
154  *
155  * @param fn 目标程序的地址
156  * @param arg 向目标程序传入的参数
157  * @param flags
158  * @return int
159  */
160 
161 pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
162 
163 int process_fd_alloc(struct vfs_file_t *file);
164 
165 int process_release_pcb(struct process_control_block *pcb);
166 
167 /**
168  * @brief 切换页表
169  * @param prev 前一个进程的pcb
170  * @param next 下一个进程的pcb
171  *
172  */
173 #define process_switch_mm(next_pcb)                                                                                    \
174     do                                                                                                                 \
175     {                                                                                                                  \
176         asm volatile("movq %0, %%cr3	\n\t" ::"r"(next_pcb->mm->pgd) : "memory");                                    \
177     } while (0)
178 // flush_tlb();
179 
180 // 获取当前cpu id
181 #define proc_current_cpu_id (current_pcb->cpu_id)
182 
183 extern unsigned long head_stack_start; // 导出内核层栈基地址(定义在head.S
184 extern ul _stack_start;
185 extern void ret_from_intr(void); // 导出从中断返回的函数(定义在entry.S
186 
187 extern struct tss_struct initial_tss[MAX_CPU_NUM];
188 extern struct mm_struct initial_mm;
189 extern struct thread_struct initial_thread;
190 extern union proc_union initial_proc_union;
191 extern struct process_control_block *initial_proc[MAX_CPU_NUM];
192 
193 /**
194  * @brief 给pcb设置名字
195  *
196  * @param pcb 需要设置名字的pcb
197  * @param pcb_name 保存名字的char数组
198  */
199 void process_set_pcb_name(struct process_control_block *pcb, const char *pcb_name);
200