Thread.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. #pragma once
  2. #include <AK/AKString.h>
  3. #include <AK/Function.h>
  4. #include <AK/InlineLinkedList.h>
  5. #include <AK/OwnPtr.h>
  6. #include <AK/RefPtr.h>
  7. #include <AK/Vector.h>
  8. #include <Kernel/Arch/i386/CPU.h>
  9. #include <Kernel/KResult.h>
  10. #include <Kernel/UnixTypes.h>
  11. #include <Kernel/VM/Region.h>
  12. #include <LibC/fd_set.h>
  13. class Alarm;
  14. class FileDescription;
  15. class Process;
  16. class Region;
  17. class Thread;
  18. enum class ShouldUnblockThread {
  19. No = 0,
  20. Yes
  21. };
  22. struct SignalActionData {
  23. VirtualAddress handler_or_sigaction;
  24. u32 mask { 0 };
  25. int flags { 0 };
  26. };
  27. extern InlineLinkedList<Thread>* g_runnable_threads;
  28. extern InlineLinkedList<Thread>* g_nonrunnable_threads;
  29. class Thread : public InlineLinkedListNode<Thread> {
  30. friend class Process;
  31. friend class Scheduler;
  32. public:
  33. explicit Thread(Process&);
  34. ~Thread();
  35. static void initialize();
  36. static void finalize_dying_threads();
  37. static Vector<Thread*> all_threads();
  38. static bool is_thread(void*);
  39. int tid() const { return m_tid; }
  40. int pid() const;
  41. Process& process() { return m_process; }
  42. const Process& process() const { return m_process; }
  43. void finalize();
  44. enum State : u8 {
  45. Invalid = 0,
  46. Runnable,
  47. Running,
  48. Skip1SchedulerPass,
  49. Skip0SchedulerPasses,
  50. Dying,
  51. Dead,
  52. Stopped,
  53. Blocked,
  54. };
  55. class Blocker {
  56. public:
  57. virtual ~Blocker() {}
  58. virtual bool should_unblock(Thread&, time_t now_s, long us) = 0;
  59. virtual const char* state_string() const = 0;
  60. };
  61. class FileDescriptionBlocker : public Blocker {
  62. public:
  63. FileDescriptionBlocker(const RefPtr<FileDescription>& description);
  64. RefPtr<FileDescription> blocked_description() const;
  65. private:
  66. RefPtr<FileDescription> m_blocked_description;
  67. };
  68. class AcceptBlocker : public FileDescriptionBlocker {
  69. public:
  70. AcceptBlocker(const RefPtr<FileDescription>& description);
  71. virtual bool should_unblock(Thread&, time_t, long) override;
  72. virtual const char* state_string() const override { return "Accepting"; }
  73. };
  74. class ReceiveBlocker : public FileDescriptionBlocker {
  75. public:
  76. ReceiveBlocker(const RefPtr<FileDescription>& description);
  77. virtual bool should_unblock(Thread&, time_t, long) override;
  78. virtual const char* state_string() const override { return "Receiving"; }
  79. };
  80. class ConnectBlocker : public FileDescriptionBlocker {
  81. public:
  82. ConnectBlocker(const RefPtr<FileDescription>& description);
  83. virtual bool should_unblock(Thread&, time_t, long) override;
  84. virtual const char* state_string() const override { return "Connecting"; }
  85. };
  86. class WriteBlocker : public FileDescriptionBlocker {
  87. public:
  88. WriteBlocker(const RefPtr<FileDescription>& description);
  89. virtual bool should_unblock(Thread&, time_t, long) override;
  90. virtual const char* state_string() const override { return "Writing"; }
  91. };
  92. class ReadBlocker : public FileDescriptionBlocker {
  93. public:
  94. ReadBlocker(const RefPtr<FileDescription>& description);
  95. virtual bool should_unblock(Thread&, time_t, long) override;
  96. virtual const char* state_string() const override { return "Reading"; }
  97. };
  98. class ConditionBlocker : public Blocker {
  99. public:
  100. ConditionBlocker(const char* state_string, Function<bool()> &condition);
  101. virtual bool should_unblock(Thread&, time_t, long) override;
  102. virtual const char* state_string() const override { return m_state_string; }
  103. private:
  104. Function<bool()> m_block_until_condition;
  105. const char* m_state_string;
  106. };
  107. class SleepBlocker : public Blocker {
  108. public:
  109. SleepBlocker(u64 wakeup_time);
  110. virtual bool should_unblock(Thread&, time_t, long) override;
  111. virtual const char* state_string() const override { return "Sleeping"; }
  112. private:
  113. u64 m_wakeup_time { 0 };
  114. };
  115. class SelectBlocker : public Blocker {
  116. public:
  117. typedef Vector<int, FD_SETSIZE> FDVector;
  118. SelectBlocker(const timeval& tv, bool select_has_timeout, const FDVector& read_fds, const FDVector& write_fds, const FDVector& except_fds);
  119. virtual bool should_unblock(Thread&, time_t, long) override;
  120. virtual const char* state_string() const override { return "Selecting"; }
  121. private:
  122. timeval m_select_timeout;
  123. bool m_select_has_timeout { false };
  124. const FDVector& m_select_read_fds;
  125. const FDVector& m_select_write_fds;
  126. const FDVector& m_select_exceptional_fds;
  127. };
  128. class WaitBlocker : public Blocker {
  129. public:
  130. WaitBlocker(int wait_options, pid_t& waitee_pid);
  131. virtual bool should_unblock(Thread&, time_t, long) override;
  132. virtual const char* state_string() const override { return "Waiting"; }
  133. private:
  134. int m_wait_options { 0 };
  135. pid_t& m_waitee_pid;
  136. };
  137. class SemiPermanentBlocker : public Blocker {
  138. public:
  139. enum class Reason {
  140. Lurking,
  141. Signal,
  142. };
  143. SemiPermanentBlocker(Reason reason);
  144. virtual bool should_unblock(Thread&, time_t, long) override;
  145. virtual const char* state_string() const override
  146. {
  147. switch (m_reason) {
  148. case Reason::Lurking:
  149. return "Lurking";
  150. case Reason::Signal:
  151. return "Signal";
  152. }
  153. ASSERT_NOT_REACHED();
  154. }
  155. private:
  156. Reason m_reason;
  157. };
  158. void did_schedule() { ++m_times_scheduled; }
  159. u32 times_scheduled() const { return m_times_scheduled; }
  160. bool is_stopped() const { return m_state == Stopped; }
  161. bool is_blocked() const
  162. {
  163. return m_state == Blocked;
  164. }
  165. bool in_kernel() const { return (m_tss.cs & 0x03) == 0; }
  166. u32 frame_ptr() const { return m_tss.ebp; }
  167. u32 stack_ptr() const { return m_tss.esp; }
  168. u16 selector() const { return m_far_ptr.selector; }
  169. TSS32& tss() { return m_tss; }
  170. State state() const { return m_state; }
  171. const char* state_string() const;
  172. u32 ticks() const { return m_ticks; }
  173. u64 sleep(u32 ticks);
  174. void block(Blocker& blocker);
  175. void unblock();
  176. void block_until(const char* state_string, Function<bool()>&&);
  177. KResult wait_for_connect(FileDescription&);
  178. const FarPtr& far_ptr() const { return m_far_ptr; }
  179. bool tick();
  180. void set_ticks_left(u32 t) { m_ticks_left = t; }
  181. u32 ticks_left() const { return m_ticks_left; }
  182. u32 kernel_stack_base() const { return m_kernel_stack_base; }
  183. u32 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; }
  184. void set_selector(u16 s) { m_far_ptr.selector = s; }
  185. void set_state(State);
  186. void send_signal(u8 signal, Process* sender);
  187. void consider_unblock(time_t now_sec, long now_usec);
  188. ShouldUnblockThread dispatch_one_pending_signal();
  189. ShouldUnblockThread dispatch_signal(u8 signal);
  190. bool has_unmasked_pending_signals() const;
  191. void terminate_due_to_signal(u8 signal);
  192. bool should_ignore_signal(u8 signal) const;
  193. FPUState& fpu_state() { return *m_fpu_state; }
  194. bool has_used_fpu() const { return m_has_used_fpu; }
  195. void set_has_used_fpu(bool b) { m_has_used_fpu = b; }
  196. void set_default_signal_dispositions();
  197. void push_value_on_stack(u32);
  198. void make_userspace_stack_for_main_thread(Vector<String> arguments, Vector<String> environment);
  199. void make_userspace_stack_for_secondary_thread(void* argument);
  200. Thread* clone(Process&);
  201. // For InlineLinkedList
  202. Thread* m_prev { nullptr };
  203. Thread* m_next { nullptr };
  204. InlineLinkedList<Thread>* thread_list() { return m_thread_list; }
  205. void set_thread_list(InlineLinkedList<Thread>*);
  206. template<typename Callback>
  207. static void for_each_in_state(State, Callback);
  208. template<typename Callback>
  209. static void for_each_living(Callback);
  210. template<typename Callback>
  211. static void for_each_runnable(Callback);
  212. template<typename Callback>
  213. static void for_each_nonrunnable(Callback);
  214. template<typename Callback>
  215. static void for_each(Callback);
  216. static bool is_runnable_state(Thread::State state)
  217. {
  218. return state == Thread::State::Running || state == Thread::State::Runnable;
  219. }
  220. static InlineLinkedList<Thread>* thread_list_for_state(Thread::State state)
  221. {
  222. if (is_runnable_state(state))
  223. return g_runnable_threads;
  224. return g_nonrunnable_threads;
  225. }
  226. private:
  227. Process& m_process;
  228. int m_tid { -1 };
  229. TSS32 m_tss;
  230. OwnPtr<TSS32> m_tss_to_resume_kernel;
  231. FarPtr m_far_ptr;
  232. u32 m_ticks { 0 };
  233. u32 m_ticks_left { 0 };
  234. u32 m_times_scheduled { 0 };
  235. u32 m_pending_signals { 0 };
  236. u32 m_signal_mask { 0 };
  237. u32 m_kernel_stack_base { 0 };
  238. RefPtr<Region> m_kernel_stack_region;
  239. RefPtr<Region> m_kernel_stack_for_signal_handler_region;
  240. SignalActionData m_signal_action_data[32];
  241. Region* m_signal_stack_user_region { nullptr };
  242. OwnPtr<Blocker> m_blocker;
  243. FPUState* m_fpu_state { nullptr };
  244. InlineLinkedList<Thread>* m_thread_list { nullptr };
  245. State m_state { Invalid };
  246. bool m_has_used_fpu { false };
  247. bool m_was_interrupted_while_blocked { false };
  248. void block_helper();
  249. };
  250. HashTable<Thread*>& thread_table();
  251. template<typename Callback>
  252. inline void Thread::for_each_in_state(State state, Callback callback)
  253. {
  254. ASSERT_INTERRUPTS_DISABLED();
  255. for (auto* thread = thread_list_for_state(state)->head(); thread;) {
  256. auto* next_thread = thread->next();
  257. if (thread->state() == state)
  258. callback(*thread);
  259. thread = next_thread;
  260. }
  261. }
  262. template<typename Callback>
  263. inline void Thread::for_each_living(Callback callback)
  264. {
  265. ASSERT_INTERRUPTS_DISABLED();
  266. for (auto* thread = g_runnable_threads->head(); thread;) {
  267. auto* next_thread = thread->next();
  268. if (thread->state() != Thread::State::Dead && thread->state() != Thread::State::Dying)
  269. callback(*thread);
  270. thread = next_thread;
  271. }
  272. for (auto* thread = g_nonrunnable_threads->head(); thread;) {
  273. auto* next_thread = thread->next();
  274. if (thread->state() != Thread::State::Dead && thread->state() != Thread::State::Dying)
  275. callback(*thread);
  276. thread = next_thread;
  277. }
  278. }
  279. template<typename Callback>
  280. inline void Thread::for_each(Callback callback)
  281. {
  282. ASSERT_INTERRUPTS_DISABLED();
  283. for_each_runnable(callback);
  284. for_each_nonrunnable(callback);
  285. }
  286. template<typename Callback>
  287. inline void Thread::for_each_runnable(Callback callback)
  288. {
  289. ASSERT_INTERRUPTS_DISABLED();
  290. for (auto* thread = g_runnable_threads->head(); thread;) {
  291. auto* next_thread = thread->next();
  292. if (callback(*thread) == IterationDecision::Break)
  293. return;
  294. thread = next_thread;
  295. }
  296. }
  297. template<typename Callback>
  298. inline void Thread::for_each_nonrunnable(Callback callback)
  299. {
  300. ASSERT_INTERRUPTS_DISABLED();
  301. for (auto* thread = g_nonrunnable_threads->head(); thread;) {
  302. auto* next_thread = thread->next();
  303. if (callback(*thread) == IterationDecision::Break)
  304. return;
  305. thread = next_thread;
  306. }
  307. }