thread.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #ifndef __THREAD_THREAD_H
  2. #define __THREAD_THREAD_H
  3. #include "../lib/stdint.h"
  4. #include "../lib/kernel/list.h"
  5. #include "../kernel/memory.h"
  6. // 通用函数类型,它将在很多线程函数中作为参数类型
  7. typedef void thread_func(void *);
  8. typedef int16_t pid_t;
  9. // 线程的状态
  10. enum task_status
  11. {
  12. TASK_RUNNING,
  13. TASK_READY,
  14. TASK_BLOCKED,
  15. TASK_WAITING,
  16. TASK_HANGING,
  17. TASK_DIED
  18. };
  19. /******************** 中断栈 intr_stack **********************************
  20. * 些结构用于中断发生时保护程序(线程或进程)的上下文环境:
  21. * 进程或线程被外部中断或软中断打断时,需要保护程序(线程或进程)的上下文寄存器,
  22. * kernel.S 中的 intr_exit 出栈操作是些结构的逆操作。
  23. * 此栈在线程自己的内核栈中位置固定,所在页的最顶端。
  24. ***********************************************************************/
  25. struct intr_stack
  26. {
  27. uint32_t vec_no; // kernel.S 宏VECTOR中push %1压入的中断号
  28. uint32_t edi;
  29. uint32_t esi;
  30. uint32_t ebp;
  31. uint32_t esp_dummy; // 虽然pushad会把esp压入,但esp是不断变化的,所以会被popad忽略
  32. uint32_t ebx;
  33. uint32_t edx;
  34. uint32_t ecx;
  35. uint32_t eax;
  36. uint32_t gs;
  37. uint32_t fs;
  38. uint32_t es;
  39. uint32_t ds;
  40. // 以下由cpu从低特权级进入高特权级时压入
  41. uint32_t err_code; // err_code会被压入在eip之后
  42. void (*eip)(void);
  43. uint32_t cs;
  44. uint32_t eflags;
  45. void *esp;
  46. uint32_t ss;
  47. };
  48. /********************* 线程栈thread_stack ********************************
  49. * 线程自己的栈,用于存储线程中待执行的函数
  50. * 此结构在线程自己的内核栈中位置不固定
  51. * 仅用在 switch_to 时保存线程环境
  52. * 实际位置取决于实际运行情况
  53. ***********************************************************************/
  54. struct thread_stack
  55. {
  56. // All registers on the Intel386 缸e global and thus visible to both a calling and a called function.
  57. // Registers %ebp, %ebx, %edi, %esi, and %esp “ belong” to the calling function.
  58. // In other words, a called function must preserve these registers' values for its caller.
  59. // Remaining registers “ belong” to the called function.
  60. // If a calling function wants to preserve such a register value across a function call,
  61. // it must save the value in its local stack frame.
  62. uint32_t ebp;
  63. uint32_t ebx;
  64. uint32_t edi;
  65. uint32_t esi;
  66. // 线程第一次执行时,eip指向待调用的函数kernel_thread
  67. // 其他时候,指向switch_to的返回地址
  68. void (*eip)(thread_func *func, void *func_arg);
  69. // 以下仅供第一次被调度上cpu时使用
  70. // 参数unused_ret只为占位置充数为返回地址
  71. void(*unused_retaddr);
  72. thread_func *function; // 由kernel_thread所调用的函数名
  73. void *func_arg; // 由kernel_thread所调用的函数所需的参数
  74. };
  75. // 进程或线程的 pcb,程序控制块(process control block)
  76. struct task_struct
  77. {
  78. uint32_t *self_kstack; // 各内核线程都用自己的内核栈
  79. pid_t pid; // 任务pid
  80. enum task_status status; // 线程状态
  81. char name[16]; // 进程或线程的名字
  82. uint8_t priority; // 线程优先级
  83. uint8_t ticks; // 每次在处理器上执行的时间嘀嗒数
  84. uint32_t elapsed_ticks; // 累计计执行的 ticks 数
  85. struct list_elem general_tag; // 用于线程在一般队列中的结点
  86. struct list_elem all_list_tag; // 用于线程队列 thread_all_list 中的结点
  87. uint32_t *pgdir; // 进程自己页表的虚拟地址, 如果是线程则为 NULL
  88. struct virtual_addr userprog_addr; // 用户进程的虚拟地址
  89. uint32_t stack_magic; // 用这串数字做栈的边界标记,用于检测栈的溢出
  90. };
  91. extern struct list thread_ready_list; // 就绪队列
  92. extern struct list thread_all_list; // 所有任务队列
  93. // 获取当前线程的 PCB 指针
  94. struct task_struct *running_thread(void);
  95. // 初始化线程栈 thread_stack
  96. void thread_create(struct task_struct *pthread, thread_func function, void *func_arg);
  97. // 初始化线程基本信息
  98. void init_thread(struct task_struct *pthread, char *name, int prio);
  99. // 创建优先级为 prio 的线程, 线程名为 name, 线程所执行的函数是 function(func_arg)
  100. struct task_struct *thread_start(char *name, int prio, thread_func function, void *func_arg);
  101. // 任务调度
  102. void schedule(void);
  103. // 当前线程将自己阻塞,标志其状态为 status
  104. void thread_block(enum task_status status);
  105. // 解除线程的阻塞状态,标志其状态为 TASK_RUNNING
  106. void thread_unblock(struct task_struct *pthread);
  107. // 初始化线程环境
  108. void thread_init(void);
  109. #endif // __THREAD_THREAD_H