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
20MOS_ENUM_FLAGS(FDFlag, FDFlags);
21
22/**
23 * @defgroup tasks Process and thread management
24 * @{
25 */
26
27typedef enum
28{
29 THREAD_MODE_KERNEL,
30 THREAD_MODE_USER,
31} thread_mode;
32
33struct Thread;
34
35typedef 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
41struct fd_type
42{
43 IO *io;
44 FDFlags flags;
45};
46
47inline 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
52struct 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
106typedef 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
113struct 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