11#include <abi-bits/wait.h>
47 default:
return "unknown";
57 default:
return "unknown";
63 static std::atomic<pid_t> next = 1;
73 this->
name = name_.
empty() ?
"<unknown>" : name_;
78 pr_demph(process,
"special process %pp created", (
void *)
this);
80 else if (
parent ==
nullptr)
82 mos_panic(
"process %pp has no parent", (
void *)
this);
103 pr_emerg(
"process %p destroyed", (
void *)
this);
114 pr_dinfo2(process,
"destroying process %pp", process);
133 process->
mm =
nullptr;
142 pr_dinfo2(process,
"creating process %pp", proc);
154 proc->main_thread = thread.get();
183 mos_warn(
"process %pp has too many open files", process);
246 pr_dinfo2(process,
"woken up by signal");
251 goto find_dead_child;
256 if (!target_proc_opt)
258 pr_warn(
"process %d does not exist", pid);
262 const auto target_proc = *target_proc_opt;
267 if (target_proc->exited)
276 pid = target_proc->pid;
278 *exit_code = target_proc->exit_status;
287 pr_dinfo2(process,
"process %pp exited with code %d, signal %d", process, exit_code, signal);
290 mos_panic(
"init process terminated with code %d, signal %d", exit_code, signal);
292 for (
const auto &thread : process->thread_list)
297 pr_dinfo2(process,
"cleanup thread %pt", thread);
308 pr_dinfo2(signal,
"sending SIGKILL to thread %pt", thread);
313 pr_dinfo2(process,
"thread %pt terminated", thread);
321 process->main_thread = thread;
322 pr_dinfo2(process,
"thread %pt is current thread, making it main thread", thread);
327 size_t files_total = 0;
328 size_t files_closed = 0;
331 fd_type file = process->files[i];
332 process->files[i] =
nullfd;
345 child->parent = process->parent;
352 pr_dinfo2(process,
"closed %zu/%zu files owned by %pp", files_closed, files_total, process);
353 process->exited =
true;
354 process->exit_status = W_EXITCODE(exit_code, signal);
360 pr_dinfo2(process,
"waking up parent %pp", process->parent);
362 waitlist_wake(&process->parent->signal_info.sigchild_waitlist, INT_MAX);
370 pr_info(
"process %pp:", process);
377 pr_info2(
" %3zd: %pvm, %s, %s", i, (
void *) map, typestr, forkmode);
380 pr_info(
"total: %zd memory regions", i);
385 pr_dinfo2(signal,
"registering signal handler for process %pp, signal %d", process, sig);
397#define do_print(fmt, name, item) sysfs_printf(f, "%-10s: " fmt "\n", name, item);
424#define stat_line(fmt) " %9s: " fmt "\n"
427 (
void *) &vmap->vmflags,
428 vmap->vmflags &
VM_USER ?
"user" :
"kernel",
429 vmap->vmflags &
VM_GLOBAL ?
" global" :
""
#define MOS_ASSERT_X(cond, msg,...)
#define MOS_UNREACHABLE()
#define mos_warn(fmt,...)
#define MOS_PROCESS_MAX_OPEN_FILES
#define MOS_PATH_MAX_LENGTH
constexpr bool empty() const
dentry_t * dentry_ref_up_to(dentry_t *dentry, dentry_t *root)
Increment the reference count of a dentry up to a given dentry.
void dentry_unref(dentry_t *dentry)
Decrement the reference count of a dentry.
long signal_send_to_process(Process *target, signal_t signal)
Send a signal to a process, an arbitrary thread will be chosen to receive the signal.
bool signal_has_pending(void)
Return true if there's a pending signal.
long signal_send_to_thread(Thread *target, signal_t signal)
Send a signal to a thread.
MOSAPI void linked_list_init(list_node_t *head_node)
Initialise a circular double linked list.
MOSAPI void list_node_append(list_node_t *head, list_node_t *item)
#define list_foreach(t, v, h)
Iterate over a list.
#define list_node(element)
Get the ‘list_node’ of a list element. This is exactly the reverse of ‘list_entry’ above.
MOSAPI bool list_is_empty(const list_node_t *head)
#define list_remove(element)
void mm_destroy_context(MMContext *table)
Destroy a user-mode platform-dependent page table.
MMContext * mm_create_context(void)
Create a user-mode platform-dependent page table.
void vmap_destroy(vmap_t *vmap)
Destroy a vmap object, and unmmap the region.
#define PROCESS_MAGIC_PROC
__nodiscard bool io_valid(const io_t *io)
io_t * io_unref(io_t *io)
void io_get_name(const io_t *io, char *buf, size_t size)
basic_string_view< char > string_view
#define mos_panic(fmt,...)
#define pr_info2(fmt,...)
#define pr_emerg(fmt,...)
#define pr_demph(feat, fmt,...)
#define pr_dinfo2(feat, fmt,...)
pid_t process_wait_for_pid(pid_t pid, u32 *exit_code, u32 flags)
void process_exit(Process *&&process, u8 exit_code, signal_t signal)
fd_t process_attach_ref_fd(Process *process, io_t *file, fd_flags_t flags)
static sysfs_item_t process_sysfs_items[]
#define do_print(fmt, name, item)
Process * process_new(Process *parent, mos::string_view name, const stdio_t *ios)
const char * get_vmap_type_str(vmap_type_t type)
static bool process_sysfs_thread_stat(sysfs_file_t *f)
void process_dump_mmaps(const Process *process)
void process_destroy(Process *process)
static bool process_sysfs_process_stat(sysfs_file_t *f)
static pid_t new_process_id(void)
bool process_register_signal_handler(Process *process, signal_t sig, const sigaction_t *sigaction)
static bool process_sysfs_vmap_stat(sysfs_file_t *f)
std::optional< Process * > process_get(pid_t pid)
bool process_detach_fd(Process *process, fd_t fd)
io_t * process_get_fd(Process *process, fd_t fd)
const char * get_vmap_content_str(vmap_content_t content)
should_inline bool process_is_valid(const Process *process)
mos::HashMap< pid_t, Process * > ProcessTable
__nodiscard bool reschedule_for_waitlist(waitlist_t *waitlist)
#define spinlock_acquire(lock)
#define spinlock_release(lock)
spinlock_t mm_lock
protects [pgd] and the [mmaps] list (the list itself, not the vmap_t objects)
static Process * New(Process *parent, mos::string_view name)
process_signal_info_t signal_info
signal handling info
dentry_t * working_directory
Process(Private, Process *parent, mos::string_view name)
list_head children
list of children processes
fd_type files[MOS_PROCESS_MAX_OPEN_FILES]
spinlock_t state_lock
protects the thread state
sigaction_t handlers[SIGNAL_MAX_N]
signal handlers
A wrapper type for the standard I/O streams.
ssize_t sysfs_printf(sysfs_file_t *file, const char *fmt,...)
#define SYSFS_RO_ITEM(_name, _show_fn)
#define SYSFS_AUTOREGISTER(sysfs_name, sysfs_items)
void thread_destroy(Thread *thread)
mos::HashMap< tid_t, Thread * > thread_table
bool thread_wait_for_tid(tid_t tid)
PtrResult< Thread > thread_new(Process *owner, thread_mode mode, mos::string_view name, size_t stack_size, void *stack)
void thread_exit_locked(Thread *&&t)
void waitlist_init(waitlist_t *list)
size_t waitlist_wake(waitlist_t *list, size_t max_wakeups)
void waitlist_remove_me(waitlist_t *waitlist)