process.hpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. #pragma once
  2. #include <kernel/event/evtqueue.hpp>
  3. #include <kernel/interrupt.h>
  4. #include <kernel/mm.hpp>
  5. #include <kernel/task.h>
  6. #include <types/cplusplus.hpp>
  7. #include <types/hash_map.hpp>
  8. #include <types/list.hpp>
  9. #include <types/stdint.h>
  10. #include <types/types.h>
  11. typedef size_t pid_t;
  12. class process;
  13. struct thread;
  14. struct process_attr {
  15. uint16_t system : 1;
  16. uint16_t zombie : 1 = 0;
  17. };
  18. struct thread_attr {
  19. uint32_t system : 1;
  20. uint32_t ready : 1;
  21. uint32_t wait : 1;
  22. };
  23. struct thread {
  24. private:
  25. inline void alloc_kstack(void)
  26. {
  27. // TODO: alloc low mem
  28. kstack = to_pp(alloc_n_raw_pages(2));
  29. kstack += THREAD_KERNEL_STACK_SIZE;
  30. esp = reinterpret_cast<uint32_t*>(kstack);
  31. }
  32. public:
  33. uint32_t* esp;
  34. pptr_t kstack;
  35. process* owner;
  36. thread_attr attr;
  37. explicit inline thread(process* _owner, bool system)
  38. : owner { _owner }
  39. , attr {
  40. .system = system,
  41. .ready = 1,
  42. .wait = 0,
  43. }
  44. {
  45. alloc_kstack();
  46. }
  47. constexpr thread(thread&& val)
  48. : esp { val.esp }
  49. , kstack { val.kstack }
  50. , owner { val.owner }
  51. , attr { val.attr }
  52. {
  53. val.attr = {};
  54. val.esp = 0;
  55. val.kstack = 0;
  56. val.owner = nullptr;
  57. }
  58. inline thread(const thread& val)
  59. : owner { val.owner }
  60. , attr { val.attr }
  61. {
  62. alloc_kstack();
  63. }
  64. constexpr ~thread()
  65. {
  66. if (kstack)
  67. free_n_raw_pages(to_page(kstack), 2);
  68. }
  69. };
  70. class process {
  71. public:
  72. mutable kernel::mm_list mms;
  73. types::list<thread> thds;
  74. kernel::evtqueue wait_lst;
  75. process_attr attr;
  76. pid_t pid;
  77. pid_t ppid;
  78. public:
  79. process(process&& val);
  80. process(const process&) = delete;
  81. process(const process& proc, const thread& main_thread);
  82. // only used for system initialization
  83. explicit process(pid_t ppid);
  84. explicit process(void (*func_in_kernel_space)(void), pid_t ppid);
  85. ~process();
  86. private:
  87. static inline pid_t max_pid;
  88. static inline pid_t alloc_pid(void)
  89. {
  90. return ++max_pid;
  91. }
  92. };
  93. class proclist final {
  94. public:
  95. using list_type = types::list<process>;
  96. using index_type = types::hash_map<pid_t, types::list<process>::iterator_type, types::linux_hasher<pid_t>>;
  97. using child_index_type = types::hash_map<pid_t, types::list<pid_t>, types::linux_hasher<pid_t>>;
  98. using iterator_type = list_type::iterator_type;
  99. using const_iterator_type = list_type::const_iterator_type;
  100. private:
  101. list_type m_procs;
  102. index_type m_idx;
  103. child_index_type m_child_idx;
  104. public:
  105. template <typename... Args>
  106. constexpr iterator_type emplace(Args&&... args)
  107. {
  108. auto iter = m_procs.emplace_back(types::forward<Args>(args)...);
  109. m_idx.emplace(iter->pid, iter);
  110. auto children = m_child_idx.find(iter->ppid);
  111. if (!children) {
  112. m_child_idx.emplace(iter->ppid, types::list<pid_t> {});
  113. children = m_child_idx.find(iter->ppid);
  114. }
  115. children->value.push_back(iter->pid);
  116. return iter;
  117. }
  118. constexpr void remove(pid_t pid)
  119. {
  120. make_children_orphans(pid);
  121. auto proc_iter = m_idx.find(pid);
  122. auto ppid = proc_iter->value->ppid;
  123. auto& parent_children = m_child_idx.find(ppid)->value;
  124. auto i = parent_children.find(pid);
  125. parent_children.erase(i);
  126. m_procs.erase(proc_iter->value);
  127. m_idx.remove(proc_iter);
  128. }
  129. constexpr process* find(pid_t pid)
  130. {
  131. return &m_idx.find(pid)->value;
  132. }
  133. constexpr bool has_child(pid_t pid)
  134. {
  135. auto children = m_child_idx.find(pid);
  136. return children && !children->value.empty();
  137. }
  138. constexpr void make_children_orphans(pid_t pid)
  139. {
  140. auto children = m_child_idx.find(pid);
  141. if (children) {
  142. auto init_children = m_child_idx.find(1);
  143. for (auto iter = children->value.begin(); iter != children->value.end(); ++iter) {
  144. init_children->value.push_back(*iter);
  145. this->find(*iter)->ppid = 1;
  146. }
  147. m_child_idx.remove(children);
  148. }
  149. }
  150. };
  151. class readyqueue final {
  152. public:
  153. using list_type = types::list<thread*>;
  154. using iterator_type = list_type::iterator_type;
  155. using const_iterator_type = list_type::const_iterator_type;
  156. private:
  157. list_type m_thds;
  158. private:
  159. readyqueue(const readyqueue&) = delete;
  160. readyqueue(readyqueue&&) = delete;
  161. readyqueue& operator=(const readyqueue&) = delete;
  162. readyqueue& operator=(readyqueue&&) = delete;
  163. ~readyqueue() = delete;
  164. public:
  165. constexpr explicit readyqueue(void) = default;
  166. constexpr void push(thread* thd)
  167. {
  168. m_thds.push_back(thd);
  169. }
  170. constexpr thread* pop(void)
  171. {
  172. auto iter = m_thds.begin();
  173. while (!((*iter)->attr.ready))
  174. iter = m_thds.erase(iter);
  175. auto* ptr = *iter;
  176. m_thds.erase(iter);
  177. return ptr;
  178. }
  179. constexpr thread* query(void)
  180. {
  181. auto* thd = this->pop();
  182. this->push(thd);
  183. return thd;
  184. }
  185. constexpr void remove_all(thread* thd)
  186. {
  187. auto iter = m_thds.find(thd);
  188. while (iter != m_thds.end()) {
  189. m_thds.erase(iter);
  190. iter = m_thds.find(thd);
  191. }
  192. }
  193. };
  194. inline process* volatile current_process;
  195. inline thread* volatile current_thread;
  196. inline proclist* procs;
  197. inline readyqueue* readythds;
  198. extern "C" void NORETURN init_scheduler();
  199. void schedule(void);
  200. constexpr uint32_t push_stack(uint32_t** stack, uint32_t val)
  201. {
  202. --*stack;
  203. **stack = val;
  204. return val;
  205. }
  206. void k_new_thread(void (*func)(void*), void* data);