Thread.h 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. #pragma once
  2. #include <AK/AKString.h>
  3. #include <AK/InlineLinkedList.h>
  4. #include <AK/OwnPtr.h>
  5. #include <AK/RetainPtr.h>
  6. #include <AK/Vector.h>
  7. #include <Kernel/Arch/i386/CPU.h>
  8. #include <Kernel/KResult.h>
  9. #include <Kernel/UnixTypes.h>
  10. #include <Kernel/VM/Region.h>
  11. #include <Kernel/VirtualAddress.h>
  12. class Alarm;
  13. class FileDescription;
  14. class Process;
  15. class Region;
  16. class Thread;
  17. enum class ShouldUnblockThread {
  18. No = 0,
  19. Yes
  20. };
  21. struct SignalActionData {
  22. VirtualAddress handler_or_sigaction;
  23. dword mask { 0 };
  24. int flags { 0 };
  25. };
  26. extern InlineLinkedList<Thread>* g_runnable_threads;
  27. extern InlineLinkedList<Thread>* g_nonrunnable_threads;
  28. class Thread : public InlineLinkedListNode<Thread> {
  29. friend class Process;
  30. friend class Scheduler;
  31. public:
  32. explicit Thread(Process&);
  33. ~Thread();
  34. static void initialize();
  35. static void finalize_dying_threads();
  36. static Vector<Thread*> all_threads();
  37. static bool is_thread(void*);
  38. int tid() const { return m_tid; }
  39. int pid() const;
  40. Process& process() { return m_process; }
  41. const Process& process() const { return m_process; }
  42. void finalize();
  43. enum State : byte {
  44. Invalid = 0,
  45. Runnable,
  46. Running,
  47. Skip1SchedulerPass,
  48. Skip0SchedulerPasses,
  49. Dying,
  50. Dead,
  51. Stopped,
  52. BlockedLurking,
  53. BlockedSleep,
  54. BlockedWait,
  55. BlockedRead,
  56. BlockedWrite,
  57. BlockedSignal,
  58. BlockedSelect,
  59. BlockedConnect,
  60. BlockedReceive,
  61. BlockedSnoozing,
  62. };
  63. void did_schedule() { ++m_times_scheduled; }
  64. dword times_scheduled() const { return m_times_scheduled; }
  65. bool is_stopped() const { return m_state == Stopped; }
  66. bool is_blocked() const
  67. {
  68. return m_state == BlockedSleep || m_state == BlockedWait || m_state == BlockedRead || m_state == BlockedWrite || m_state == BlockedSignal || m_state == BlockedSelect;
  69. }
  70. bool in_kernel() const { return (m_tss.cs & 0x03) == 0; }
  71. dword frame_ptr() const { return m_tss.ebp; }
  72. dword stack_ptr() const { return m_tss.esp; }
  73. word selector() const { return m_far_ptr.selector; }
  74. TSS32& tss() { return m_tss; }
  75. State state() const { return m_state; }
  76. dword ticks() const { return m_ticks; }
  77. pid_t waitee_pid() const { return m_waitee_pid; }
  78. void sleep(dword ticks);
  79. void block(Thread::State);
  80. void block(Thread::State, FileDescription&);
  81. void unblock();
  82. void set_wakeup_time(qword t) { m_wakeup_time = t; }
  83. qword wakeup_time() const { return m_wakeup_time; }
  84. void snooze_until(Alarm&);
  85. KResult wait_for_connect(FileDescription&);
  86. const FarPtr& far_ptr() const { return m_far_ptr; }
  87. bool tick();
  88. void set_ticks_left(dword t) { m_ticks_left = t; }
  89. dword ticks_left() const { return m_ticks_left; }
  90. dword kernel_stack_base() const { return m_kernel_stack_base; }
  91. dword kernel_stack_for_signal_handler_base() const { return m_kernel_stack_for_signal_handler_region ? m_kernel_stack_for_signal_handler_region->vaddr().get() : 0; }
  92. void set_selector(word s) { m_far_ptr.selector = s; }
  93. void set_state(State);
  94. void send_signal(byte signal, Process* sender);
  95. ShouldUnblockThread dispatch_one_pending_signal();
  96. ShouldUnblockThread dispatch_signal(byte signal);
  97. bool has_unmasked_pending_signals() const;
  98. void terminate_due_to_signal(byte signal);
  99. FPUState& fpu_state() { return *m_fpu_state; }
  100. bool has_used_fpu() const { return m_has_used_fpu; }
  101. void set_has_used_fpu(bool b) { m_has_used_fpu = b; }
  102. void set_default_signal_dispositions();
  103. void push_value_on_stack(dword);
  104. void make_userspace_stack_for_main_thread(Vector<String> arguments, Vector<String> environment);
  105. void make_userspace_stack_for_secondary_thread(void* argument);
  106. Thread* clone(Process&);
  107. // For InlineLinkedList
  108. Thread* m_prev { nullptr };
  109. Thread* m_next { nullptr };
  110. InlineLinkedList<Thread>* thread_list() { return m_thread_list; }
  111. void set_thread_list(InlineLinkedList<Thread>*);
  112. template<typename Callback>
  113. static void for_each_in_state(State, Callback);
  114. template<typename Callback>
  115. static void for_each_living(Callback);
  116. template<typename Callback>
  117. static void for_each_runnable(Callback);
  118. template<typename Callback>
  119. static void for_each_nonrunnable(Callback);
  120. template<typename Callback>
  121. static void for_each(Callback);
  122. static bool is_runnable_state(Thread::State state)
  123. {
  124. return state == Thread::State::Running || state == Thread::State::Runnable;
  125. }
  126. static InlineLinkedList<Thread>* thread_list_for_state(Thread::State state)
  127. {
  128. if (is_runnable_state(state))
  129. return g_runnable_threads;
  130. return g_nonrunnable_threads;
  131. }
  132. private:
  133. Process& m_process;
  134. int m_tid { -1 };
  135. TSS32 m_tss;
  136. OwnPtr<TSS32> m_tss_to_resume_kernel;
  137. FarPtr m_far_ptr;
  138. dword m_ticks { 0 };
  139. dword m_ticks_left { 0 };
  140. qword m_wakeup_time { 0 };
  141. dword m_times_scheduled { 0 };
  142. dword m_pending_signals { 0 };
  143. dword m_signal_mask { 0 };
  144. dword m_kernel_stack_base { 0 };
  145. RetainPtr<Region> m_kernel_stack_region;
  146. RetainPtr<Region> m_kernel_stack_for_signal_handler_region;
  147. pid_t m_waitee_pid { -1 };
  148. RetainPtr<FileDescription> m_blocked_description;
  149. timeval m_select_timeout;
  150. SignalActionData m_signal_action_data[32];
  151. Region* m_signal_stack_user_region { nullptr };
  152. Alarm* m_snoozing_alarm { nullptr };
  153. Vector<int> m_select_read_fds;
  154. Vector<int> m_select_write_fds;
  155. Vector<int> m_select_exceptional_fds;
  156. FPUState* m_fpu_state { nullptr };
  157. InlineLinkedList<Thread>* m_thread_list { nullptr };
  158. State m_state { Invalid };
  159. bool m_select_has_timeout { false };
  160. bool m_has_used_fpu { false };
  161. bool m_was_interrupted_while_blocked { false };
  162. };
  163. HashTable<Thread*>& thread_table();
  164. const char* to_string(Thread::State);
  165. template<typename Callback>
  166. inline void Thread::for_each_in_state(State state, Callback callback)
  167. {
  168. ASSERT_INTERRUPTS_DISABLED();
  169. for (auto* thread = thread_list_for_state(state)->head(); thread;) {
  170. auto* next_thread = thread->next();
  171. if (thread->state() == state)
  172. callback(*thread);
  173. thread = next_thread;
  174. }
  175. }
  176. template<typename Callback>
  177. inline void Thread::for_each_living(Callback callback)
  178. {
  179. ASSERT_INTERRUPTS_DISABLED();
  180. for (auto* thread = g_runnable_threads->head(); thread;) {
  181. auto* next_thread = thread->next();
  182. if (thread->state() != Thread::State::Dead && thread->state() != Thread::State::Dying)
  183. callback(*thread);
  184. thread = next_thread;
  185. }
  186. for (auto* thread = g_nonrunnable_threads->head(); thread;) {
  187. auto* next_thread = thread->next();
  188. if (thread->state() != Thread::State::Dead && thread->state() != Thread::State::Dying)
  189. callback(*thread);
  190. thread = next_thread;
  191. }
  192. }
  193. template<typename Callback>
  194. inline void Thread::for_each(Callback callback)
  195. {
  196. ASSERT_INTERRUPTS_DISABLED();
  197. for_each_runnable(callback);
  198. for_each_nonrunnable(callback);
  199. }
  200. template<typename Callback>
  201. inline void Thread::for_each_runnable(Callback callback)
  202. {
  203. ASSERT_INTERRUPTS_DISABLED();
  204. for (auto* thread = g_runnable_threads->head(); thread;) {
  205. auto* next_thread = thread->next();
  206. if (callback(*thread) == IterationDecision::Break)
  207. return;
  208. thread = next_thread;
  209. }
  210. }
  211. template<typename Callback>
  212. inline void Thread::for_each_nonrunnable(Callback callback)
  213. {
  214. ASSERT_INTERRUPTS_DISABLED();
  215. for (auto* thread = g_nonrunnable_threads->head(); thread;) {
  216. auto* next_thread = thread->next();
  217. if (callback(*thread) == IterationDecision::Break)
  218. return;
  219. thread = next_thread;
  220. }
  221. }