11#include <abi-bits/wait.h>
51 static pid_t next = 1;
52 return (
pid_t){ next++ };
75 pr_demph(process,
"special process %pp created", (
void *) proc);
79 pr_emerg(
"process %pp has no parent", (
void *) proc);
98 pr_emerg(
"failed to create page table for process %pp", (
void *) proc);
115 pr_dinfo2(process,
"destroying process %pp", (
void *) process);
124 kfree(process->
name);
148 pr_dinfo2(process,
"creating process %pp", (
void *) proc);
158 MOS_ASSERT_X(old_proc ==
NULL,
"process already exists, go and buy yourself a lottery :)");
182 mos_warn(
"process %pp has too many open files", (
void *) process);
245 pr_dinfo2(process,
"woken up by signal");
250 goto find_dead_child;
255 if (target_proc ==
NULL)
257 pr_warn(
"process %d does not exist", pid);
273 pid = target_proc->
pid;
284 pr_dinfo2(process,
"process %pp exited with code %d, signal %d", (
void *) process, exit_code, signal);
287 mos_panic(
"init process terminated with code %d, signal %d", exit_code, signal);
294 pr_dinfo2(process,
"cleanup thread %pt", (
void *) thread);
305 pr_dinfo2(signal,
"sending SIGKILL to thread %pt", (
void *) thread);
310 pr_dinfo2(process,
"thread %pt terminated", (
void *) thread);
319 pr_dinfo2(process,
"thread %pt is current thread, making it main thread", (
void *) thread);
324 size_t files_total = 0;
325 size_t files_closed = 0;
342 child->parent = process->
parent;
349 pr_dinfo2(process,
"closed %zu/%zu files owned by %pp", files_closed, files_total, (
void *) process);
351 process->
exit_status = W_EXITCODE(exit_code, signal);
367 pr_info(
"process %pp:", (
void *) process);
374 pr_info2(
" %3zd: %pvm, %s, %s", i, (
void *) map, typestr, forkmode);
377 pr_info(
"total: %zd memory regions", i);
382 pr_dinfo2(signal,
"registering signal handler for process %pp, signal %d", (
void *) process, sig);
394#define do_print(fmt, name, item) sysfs_printf(f, "%-10s: " fmt "\n", name, item);
405 do_print(
"%pt",
"thread", (
void *) thread);
421#define stat_line(fmt) " %9s: " fmt "\n"
424 (
void *) &vmap->vmflags,
425 vmap->vmflags &
VM_USER ?
"user" :
"kernel",
426 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
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_t *target, signal_t signal)
Send a signal to a process, an arbitrary thread will be chosen to receive the signal.
long signal_send_to_thread(thread_t *target, signal_t signal)
Send a signal to a thread.
bool signal_has_pending(void)
Return true if there's a pending signal.
MOSAPI void * hashmap_get(hashmap_t *map, uintn key)
MOSAPI void * hashmap_put(hashmap_t *map, uintn key, void *value)
MOSAPI void * hashmap_remove(hashmap_t *map, uintn key)
MOSAPI char * strdup(const char *src)
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(mm_context_t *table)
Destroy a user-mode platform-dependent page table.
mm_context_t * 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.
__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)
#define mos_panic(fmt,...)
#define pr_info2(fmt,...)
#define pr_emerg(fmt,...)
#define pr_demph(feat, fmt,...)
#define pr_dinfo2(feat, fmt,...)
fd_t process_attach_ref_fd(process_t *process, io_t *file, fd_flags_t flags)
static const char * vmap_content_str[]
pid_t process_wait_for_pid(pid_t pid, u32 *exit_code, u32 flags)
static sysfs_item_t process_sysfs_items[]
bool process_register_signal_handler(process_t *process, signal_t sig, const sigaction_t *sigaction)
#define do_print(fmt, name, item)
void process_destroy(process_t *process)
void process_dump_mmaps(const process_t *process)
process_t * process_get(pid_t pid)
void process_exit(process_t *process, u8 exit_code, signal_t signal)
static bool process_sysfs_thread_stat(sysfs_file_t *f)
io_t * process_get_fd(process_t *process, fd_t fd)
const char * vmap_type_str[]
static bool process_sysfs_process_stat(sysfs_file_t *f)
static pid_t new_process_id(void)
process_t * process_allocate(process_t *parent, const char *name)
static bool process_sysfs_vmap_stat(sysfs_file_t *f)
process_t * process_new(process_t *parent, const char *name, const stdio_t *ios)
bool process_detach_fd(process_t *process, fd_t fd)
should_inline bool process_is_valid(const process_t *process)
#define PROCESS_MAGIC_PROC
__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)
sigaction_t handlers[SIGNAL_MAX_N]
signal handlers
waitlist_t sigchild_waitlist
the parent is waiting for a child to exit, if not empty
bool exited
true if the process has exited
process_signal_info_t signal_info
signal handling info
dentry_t * working_directory
list_head children
list of children processes
fd_type files[MOS_PROCESS_MAX_OPEN_FILES]
u32 exit_status
exit status
A wrapper type for the standard I/O streams.
spinlock_t state_lock
protects the thread state
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_t *thread)
bool thread_wait_for_tid(tid_t tid)
void thread_exit_locked(thread_t *t)
thread_t * thread_new(process_t *owner, thread_mode mode, const char *name, size_t stack_size, void *stack)
size_t waitlist_wake(waitlist_t *list, size_t max_wakeups)
__BEGIN_DECLS void waitlist_init(waitlist_t *list)
void waitlist_remove_me(waitlist_t *waitlist)