#include #include 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 | */