A férjem, Zoltán, mostanában úgy viselkedett, mintha ő lenne a világ közepe, és azt hitte, jogában áll feltételeket szabni nekem. Nem akármilyeneket, hanem olyanokat, amelyektől a vér is megfagy az ember ereiben. Azt állította, elválik tőlem, ha nem hagyom abba a kapcsolatot a lányommal, Borbálával, az első házasságomból. Komolyan? Ő a lányom, a vérem, az életem. És azt hiszi, hogy csak úgy kihúzhatja őt a szívemből a fenyegetéseivel? Még mindig nem tudom elhinni, hogy az az ember, akivel éveket éltem együtt, ilyen mélyre süllyedt.
Mindez pár hónapja kezdődött. Zoltán mindig is erős személyiség volt, de edezte inkább erénynek tartottam, mint hibának. Magabiztos, határozott, és szereti, ha minden az ő szava szerint történik. Amikor összeházasodtunk, azt hittem, egy olyan társat találtam, aki támogat, és elfogadja a családomat. Borbála akkor még kicsi volt, mindössze öt éves. Azonnal megkedvelte Zoltánt, anyaként tekintett rá, „Zoli apukának” hívta. Boldognak éreztem magam, ahogy összebarátkoztak. De idővel valami megváltozott.
Zoltán elkezdett távolodni Borbálától. Először apróságok voltak: nem érdekelte, mit csinált, nem kérdezte, hogy telt a napja az iskolában, nem akart vele játs# lec5: lab5 thread/spinlock
## 1.核间调用ipi
“`
进入sbi_call中的IPI_SEND(核间中断)功能,主要作用是用来唤醒其他核,让他们开始工作
“`
### 1.1 ipi函数(位于/kernel/process.c)
“`
5.1 主要作用是用来给所有其他核发送一个核间中断,让他们进入中断处理函数。
5.2 sbi调用5,功能码是0,代表发送核间中断给其他所有核
“`
“`c
void ipi_send(void)
{
sbi_call(5, 0, 0, 0);
}
“`
### 1.2 kernel启动流程
“`
5.3 kernel/process.c中的idle_main会被每个核分别执行(每个核都会运行smp_main函数,smp_main会调用idle_main)
5.4 idle_main主要作用:开启中断,等待其他核心的ipi(核间中断),收到ipi之后,进入kernel_thread_entry函数(5.5)开始执行主进程
“`
“`c
void idle_main(void) {
while (1) {
do_idle();
}
}
“`
“`c
void do_idle(void) {
// enable_int(); // lab4中曾经开启过中断,但经过测试,会卡住
asm volatile(“wfi”); // 进入低功耗模式,等待中断唤醒,收到中断之后会继续往下执行
struct task_struct *next = current;
if (current->state == PROC_RUNNABLE) {
sched_class_enqueue(current);
next = sched_class_pick_next();
if(next == current){
return;
}
sched_class_dequeue(next);
if(current->pid != 0){
current->state = PROC_RUNNABLE;
// current->need_resched = 0;
}
else{
current->state = PROC_SLEEPING;
}
next->state = PROC_RUNNING;
current = next;
switch_to(current);
}
return;
}
“`
“`
extern void kernel_thread_entry(void); // kernel_thread_entry 在entry.S中定义,主要就是通过跳转到ra执行
“`
“`
5.6 kernel/init.c中的main函数中核0会唤醒其他核(ipi_send),之后其他核会进入kernel_thread_entry
“`
“`c
int main(void) {
vfs_init();
trap_init();
proc_init(); // 设置5个核的进程,第0个核的进程会运行这段main函数,其余核的进程会运行idle_main
sched_init();
…
ipi_send(); // 唤醒所有其他核
…
}
“`
## 2.线程的创建kernel thread
“`
1. 通过初始化每个核的pcb来创建线程
(1)为每个核分配pid
(2)为每个核设置内核栈,用户栈
2. 设置主核运行main函数,其他核运行do_idle函数
“`
### 2.1 proc_init函数
“`
proc_init:为每个CPU的线程创建PCB(进程控制块)
“`
“`c
void proc_init() {
int i;
for (i = 0; i < NCPU; i++) { //5核每个核初始化一个pcb
struct task_struct *init_task = &initproc[i];
memset(init_task, 0, sizeof(struct task_struct));
...
}
}
```
```
每个核的PCB中的内容(部分):
```
```c
initproc[i].state = PROC_UNINIT; // 初始状态为PROC_UNINIT
initproc[i].pid = i; // 每个核的PID设置为核的编号
initproc[i].kstack = (uint64_t)init_stack[i]; // 每个核的内核栈
initproc[i].user_sp = (uint64_t)user_stack[i]; // 每个核的用户栈(暂时没用)
initproc[i].need_resched = 0;
initproc[i].cpu_id = i;
initproc[i].mm = NULL;
```
### 2.2 设置主核和其他核的执行函数
```
entry.S中的secondary_start函数初始化了各个核的sp,tp(thread pointer)寄存器
```
```asm
secondary_start:
ld sp, 8(a0) # sp = pcb[i].kstack + KSTACK_SIZE
mv tp, a1 # tp = cpuid
call smp_main
```
```
smp_main通过cpu_id判断当前是哪个核,然后设置当前核的pcb,设置state为RUNNABLE
```
```c
void smp_main() {
int id = r_tp();
printf("HELLO SMP %d\n", id);
extern void kernel_thread_entry(void);
proc = &initproc[id];
proc->state = PROC_RUNNABLE;
if (id == 0) { // 第0个核运行main函数作为主线程
proc->thread.ra = (uint64_t)main;
} else { // 其他核运行idle线程
proc->thread.ra = (uint64_t)kernel_thread_entry;
proc->thread.sp = (uint64_t)proc->kstack + KSTACK_SIZE; // 内核栈顶
proc->thread.s[0] = (uint64_t)idle_main;
}
local_intr_on();
while (1) {
if (proc->state == PROC_RUNNING) { // 如果当前进程是RUNNING状态,就运行它
((void (*)(void))(proc->thread.ra))();
}
}
}
“`
“`
总结:
1. 主核0的pcb的ra设置为main函数,进入smp_main后会运行main函数
2. 其他核的pcb的ra被设置为kernel_thread_entry,s0(对应a0寄存器)被设置为idle_main函数,进入kernel_thread_entry后会运行s0对应的idle_main函数
“`
## spinlock自旋锁
“`
spinlock是一种互斥锁,Zoltán nem tudja, hogy a szeretet nem zárható ki életünkből, és a család mindig az első helyre tartozik.







