You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

99 lines
2.6 KiB
C

#include <onix/task.h>
#include <onix/printk.h>
extern void task_switch(task_t* next);
task_t* task_a_stack = (task_t*) (PAGE_SIZE * 1); // A线程栈开始的位置
task_t* task_b_stack = (task_t*) (PAGE_SIZE * 2); // B线程栈开始的位置
static void task_create(task_t* task_struct, usize target_handle){
usize stack = (usize)task_struct + PAGE_SIZE; // 得到线程栈的栈底
stack -= sizeof(task_frame_t); // 线程本身的信息留出来空间
task_frame_t* frame = (task_frame_t*) stack; // 上面留出来的空间, 创建frame
frame->edi = 0x11111111;
frame->esi = 0x22222222;
frame->ebx = 0x33333333;
frame->ebp = 0x44444444;
frame->eip = (u8*) target_handle; // ip指向指定的 函数
task_struct->stack = (u8*)stack; // 把减去了 frame大小的栈的栈底, 赋值给 task结构 的首地址, 后面会被 schdule 间接取址
int a = 123;
}
task_t* running_task(){
asm volatile(
"movl %esp, %eax\n" // 当前 栈顶
"andl $0xfffff000, %eax\n" // 得到栈底; 得到当前线程开始的位置, 即task_create中创建的 frame,
// 由于我们每个任务 占用 1个页, 1个页的大小是0x1000, 所以我们每个线程开始的地方
// 刚好是 0x1000的整倍数, 直接把低3位置位0 即可得到每个任务开始的地方也就是保存了task_frame_t和后续栈的地方
);
}
void schdule(){
task_t* current = running_task();
// 这里实验的, 如果当前是任务a 就切换到任务b, 如果是任务b 就切换到任务a
task_t* next;
if (current == task_a_stack) {
next = task_b_stack;
} else {
next = task_a_stack;
}
task_switch(next); // 调用汇编实现的切换函数
}
void thread_a(){
while(true){
printk("A");
schdule();
}
}
void thread_b(){
while(true){
printk("B");
schdule();
}
}
void task_init(){
// test();
}
void test(){
task_create(task_a_stack, thread_a);
task_create(task_b_stack, thread_b);
schdule();
}
/*
线程栈的内存分布
| | | |
| ------ | ------ | ------------ |
| eip | 0x1fff | Function_ptr |
| ebp | | 0x44444444 |
| ebx | | 0x33333333 |
| esi | | 0x22222222 |
| edi | | 0x11111111 |
| 栈底 | 0x1f00 | |
| | | ... |
| | | ... |
| 栈顶 | 0x1100 | |
| | | |
| ... | | |
| 保存栈顶 | 0x1000 | 0x1100 |
*/