thread.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. #include "thread.h"
  2. #include "../lib/string.h"
  3. #include "../kernel/memory.h"
  4. #define PG_SIZE 4096
  5. // 由 kernel_thread 去执行 function(func_arg)
  6. static void kernel_thread(thread_func *function, void *func_arg)
  7. {
  8. function(func_arg);
  9. }
  10. // 初始化线程栈 thread_stack
  11. void thread_create(struct task_struct *pthread, thread_func function, void *func_arg)
  12. {
  13. // 先预留中断栈空间
  14. pthread->self_kstack -= sizeof(struct intr_stack);
  15. // 再预留线程栈空间,线程栈位于中断栈顶
  16. pthread->self_kstack -= sizeof(struct thread_stack);
  17. struct thread_stack *kthread_stack = (struct thread_stack *)pthread->self_kstack;
  18. kthread_stack->eip = kernel_thread;
  19. kthread_stack->function = function;
  20. kthread_stack->func_arg = func_arg;
  21. kthread_stack->ebp = kthread_stack->ebx = kthread_stack->edi = kthread_stack->esi = 0;
  22. }
  23. // 初始化线程基本信息
  24. void init_thread(struct task_struct *pthread, char *name, int prio)
  25. {
  26. _memset(pthread, 0, sizeof(*pthread));
  27. _strcpy(pthread->name, name);
  28. pthread->status = TASK_RUNNING;
  29. pthread->priority = prio;
  30. // self_kstack是线程自己在内核态下使用的栈顶地址
  31. pthread->self_kstack = (uint32_t *)((uintptr_t)pthread + PG_SIZE);
  32. pthread->stack_magic = 0x19940625; // 自定义的魔数
  33. }
  34. // 创建优先级为 prio 的线程, 线程名为 name, 线程所执行的函数是 function(func_arg)
  35. struct task_struct *thread_start(char *name, int prio, thread_func function, void *func_arg)
  36. {
  37. // pcb 线程控制块
  38. struct task_struct *thread = get_kernel_pages(1); // 申请一页内存(内核空间)做为PCB
  39. init_thread(thread, name, prio); // 初始化线程基本信息
  40. thread_create(thread, function, func_arg); // 初始化线程栈 thread_stack
  41. // ret 指令的作用是弹出栈顶的数据到 eip 寄存器,然后跳转到 eip 寄存器的地址执行
  42. // 此时栈顶数据是kthread_stack->eip 的值 kernel_thread。
  43. // 因此,在执行 ret 后,会跳转到 kernel_thread 函数执行。
  44. asm volatile("movl %0, %%esp; pop %%ebp; pop %%ebx; pop %%edi; pop %%esi; ret" : : "g"(thread->self_kstack) : "memory");
  45. return thread;
  46. }