| 1 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 2 | |
| 3 | #pragma once |
| 4 | |
| 5 | #include "mos/filesystem/vfs_types.hpp" |
| 6 | #include "mos/platform/platform.hpp" |
| 7 | #include "mos/syslog/syslog.hpp" |
| 8 | #include "mos/tasks/wait.hpp" |
| 9 | |
| 10 | #include <abi-bits/signal.h> |
| 11 | #include <mos/allocator.hpp> |
| 12 | #include <mos/lib/structures/list.hpp> |
| 13 | #include <mos/lib/structures/stack.hpp> |
| 14 | #include <mos/list.hpp> |
| 15 | #include <mos/shared_ptr.hpp> |
| 16 | #include <mos/string.hpp> |
| 17 | #include <mos/tasks/signal_types.h> |
| 18 | #include <mos/type_utils.hpp> |
| 19 | |
| 20 | MOS_ENUM_FLAGS(FDFlag, FDFlags); |
| 21 | |
| 22 | /** |
| 23 | * @defgroup tasks Process and thread management |
| 24 | * @{ |
| 25 | */ |
| 26 | |
| 27 | typedef enum |
| 28 | { |
| 29 | THREAD_MODE_KERNEL, |
| 30 | THREAD_MODE_USER, |
| 31 | } thread_mode; |
| 32 | |
| 33 | struct Thread; |
| 34 | |
| 35 | typedef struct |
| 36 | { |
| 37 | sigaction_t handlers[SIGNAL_MAX_N]; ///< signal handlers |
| 38 | waitlist_t sigchild_waitlist; ///< the parent is waiting for a child to exit, if not empty |
| 39 | } process_signal_info_t; |
| 40 | |
| 41 | struct fd_type |
| 42 | { |
| 43 | IO *io; |
| 44 | FDFlags flags; |
| 45 | }; |
| 46 | |
| 47 | inline const fd_type nullfd{ .io: nullptr, .flags: FD_FLAGS_NONE }; |
| 48 | |
| 49 | #define PROCESS_MAGIC_PROC MOS_FOURCC('P', 'R', 'O', 'C') |
| 50 | #define THREAD_MAGIC_THRD MOS_FOURCC('T', 'H', 'R', 'D') |
| 51 | |
| 52 | struct Process : mos::NamedType<"Process" > |
| 53 | { |
| 54 | PrivateTag; |
| 55 | |
| 56 | public: |
| 57 | explicit Process(Private, Process *parent, mos::string_view name); |
| 58 | ~Process(); |
| 59 | |
| 60 | const u32 magic = PROCESS_MAGIC_PROC; |
| 61 | pid_t pid; |
| 62 | mos::string name; |
| 63 | Process *parent; |
| 64 | list_head children; ///< list of children processes |
| 65 | as_linked_list; ///< node in the parent's children list |
| 66 | |
| 67 | bool exited; ///< true if the process has exited |
| 68 | u32 exit_status; ///< exit status |
| 69 | |
| 70 | fd_type files[MOS_PROCESS_MAX_OPEN_FILES]; |
| 71 | |
| 72 | Thread *main_thread; |
| 73 | mos::list<Thread *> thread_list; |
| 74 | |
| 75 | MMContext *mm; |
| 76 | dentry_t *working_directory; |
| 77 | |
| 78 | platform_process_options_t platform_options; ///< platform per-process flags |
| 79 | |
| 80 | process_signal_info_t signal_info; ///< signal handling info |
| 81 | |
| 82 | public: |
| 83 | static inline bool IsValid(const Process *process) |
| 84 | { |
| 85 | if (const auto ptr = process) |
| 86 | return ptr->magic == PROCESS_MAGIC_PROC; |
| 87 | else |
| 88 | return false; |
| 89 | } |
| 90 | |
| 91 | public: |
| 92 | static inline Process *New(Process *parent, mos::string_view name) |
| 93 | { |
| 94 | return mos::create<Process>(args: Private(), args&: parent, args&: name); |
| 95 | } |
| 96 | |
| 97 | friend mos::SyslogStreamWriter operator<<(mos::SyslogStreamWriter stream, const Process *process) |
| 98 | { |
| 99 | if (!Process::IsValid(process)) |
| 100 | return stream << "[invalid]" ; |
| 101 | |
| 102 | return stream << fmt("[p{}:{}]" , process->pid, process->name.value_or("<no name>" )); |
| 103 | } |
| 104 | }; |
| 105 | |
| 106 | typedef struct |
| 107 | { |
| 108 | spinlock_t lock; |
| 109 | list_head pending; ///< list of pending signals |
| 110 | sigset_t mask; ///< pending signals mask |
| 111 | } thread_signal_info_t; |
| 112 | |
| 113 | struct Thread : mos::NamedType<"Thread" > |
| 114 | { |
| 115 | u32 magic; |
| 116 | tid_t tid; |
| 117 | mos::string name; |
| 118 | Process *owner; |
| 119 | as_linked_list; ///< node in the process's thread list |
| 120 | thread_mode mode; ///< user-mode thread or kernel-mode |
| 121 | spinlock_t state_lock; ///< protects the thread state |
| 122 | thread_state_t state; ///< thread state |
| 123 | downwards_stack_t u_stack; ///< user-mode stack |
| 124 | downwards_stack_t k_stack; ///< kernel-mode stack |
| 125 | |
| 126 | platform_thread_options_t platform_options; ///< platform-specific thread options |
| 127 | |
| 128 | waitlist_t waiters; ///< list of threads waiting for this thread to exit |
| 129 | |
| 130 | thread_signal_info_t signal_info; |
| 131 | |
| 132 | ~Thread(); |
| 133 | |
| 134 | static bool IsValid(const Thread *thread) |
| 135 | { |
| 136 | if (auto ptr = thread; ptr) |
| 137 | return ptr->magic == THREAD_MAGIC_THRD; |
| 138 | else |
| 139 | return false; |
| 140 | } |
| 141 | |
| 142 | friend mos::SyslogStreamWriter operator<<(mos::SyslogStreamWriter stream, const Thread *thread) |
| 143 | { |
| 144 | if (!Thread::IsValid(thread)) |
| 145 | return stream << "[invalid]" ; |
| 146 | |
| 147 | return stream << fmt("[t{}:{}]" , thread->tid, thread->name.value_or("<no name>" )); |
| 148 | } |
| 149 | }; |
| 150 | |
| 151 | /** @} */ |
| 152 | |