process.hpp 5.6 KB

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