Add procfs
This commit is contained in:
@@ -30,6 +30,7 @@ struct vnode *vnode_create(enum vnode_type t, const char *name) {
|
||||
|
||||
void vnode_destroy(struct vnode *vn) {
|
||||
_assert(vnode_cache);
|
||||
_assert(!vn->open_count);
|
||||
slab_free(vnode_cache, vn);
|
||||
}
|
||||
|
||||
|
||||
+28
-28
@@ -146,7 +146,6 @@ static int sysfs_vnode_stat(struct vnode *node, struct stat *st) {
|
||||
|
||||
////
|
||||
|
||||
|
||||
int sysfs_config_getter(void *ctx, char *buf, size_t lim) {
|
||||
sysfs_buf_puts(buf, lim, ctx);
|
||||
sysfs_buf_puts(buf, lim, "\n");
|
||||
@@ -159,6 +158,33 @@ int sysfs_config_int64_getter(void *ctx, char *buf, size_t lim) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sysfs_del_ent(struct vnode *ent) {
|
||||
_assert(ent);
|
||||
_assert(ent->parent);
|
||||
vnode_detach(ent);
|
||||
|
||||
switch (ent->type) {
|
||||
case VN_LNK:
|
||||
break;
|
||||
case VN_REG:
|
||||
_assert(ent->op == &g_sysfs_vnode_ops);
|
||||
_assert(ent->fs_data);
|
||||
kfree(ent->fs_data);
|
||||
break;
|
||||
case VN_DIR:
|
||||
while (ent->first_child) {
|
||||
sysfs_del_ent(ent->first_child);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
panic("Unsupported sysfs node type\n");
|
||||
break;
|
||||
}
|
||||
|
||||
vnode_destroy(ent);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sysfs_add_dir(struct vnode *at, const char *name, struct vnode **res) {
|
||||
struct vnode *tmp;
|
||||
sysfs_ensure_root();
|
||||
@@ -172,7 +198,7 @@ int sysfs_add_dir(struct vnode *at, const char *name, struct vnode **res) {
|
||||
kdebug("Can't find %s in %s, creating\n", name, at->name);
|
||||
tmp = vnode_create(VN_DIR, name);
|
||||
tmp->flags |= VN_MEMORY;
|
||||
tmp->op = &g_sysfs_vnode_ops;
|
||||
//tmp->op = &g_sysfs_vnode_ops;
|
||||
tmp->mode = S_IXUSR | S_IXGRP | S_IXOTH |
|
||||
S_IRUSR | S_IRGRP | S_IROTH;
|
||||
|
||||
@@ -218,28 +244,6 @@ int sysfs_add_config_endpoint(struct vnode *at, const char *name, mode_t mode, s
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO: move this to an appropriate place
|
||||
#define PROC_PROP_PID 1
|
||||
#define PROC_PROP_NAME 2
|
||||
|
||||
static int proc_property_getter(void *ctx, char *buf, size_t lim) {
|
||||
uint64_t prop = (uint64_t) ctx;
|
||||
struct process *proc = thread_self->proc;
|
||||
_assert(proc);
|
||||
|
||||
switch (prop) {
|
||||
case PROC_PROP_PID:
|
||||
sysfs_buf_printf(buf, lim, "%d\n", (int) proc->pid);
|
||||
break;
|
||||
case PROC_PROP_NAME:
|
||||
sysfs_buf_puts(buf, lim, proc->name);
|
||||
sysfs_buf_puts(buf, lim, "\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int system_uptime_getter(void *ctx, char *buf, size_t lim) {
|
||||
char *p = buf;
|
||||
uint64_t t = system_time / 1000000000ULL;
|
||||
@@ -295,10 +299,6 @@ void sysfs_populate(void) {
|
||||
sysfs_add_config_endpoint(dir, "uptime", SYSFS_MODE_DEFAULT, 32, NULL, system_uptime_getter, NULL);
|
||||
sysfs_add_config_endpoint(dir, "modules", SYSFS_MODE_DEFAULT, 512, NULL, mod_list, NULL);
|
||||
|
||||
sysfs_add_dir(NULL, "self", &dir);
|
||||
sysfs_add_config_endpoint(dir, "pid", SYSFS_MODE_DEFAULT, 16, (void *) PROC_PROP_PID, proc_property_getter, NULL);
|
||||
sysfs_add_config_endpoint(dir, "name", SYSFS_MODE_DEFAULT, 128, (void *) PROC_PROP_NAME, proc_property_getter, NULL);
|
||||
|
||||
sysfs_add_config_endpoint(NULL, "mem", SYSFS_MODE_DEFAULT, 512, NULL, system_mem_getter, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,8 @@ int sysfs_config_getter(void *ctx, char *buf, size_t lim);
|
||||
// ctx: a pointer to an (u)int64_t value
|
||||
int sysfs_config_int64_getter(void *ctx, char *buf, size_t lim);
|
||||
|
||||
int sysfs_del_ent(struct vnode *dir);
|
||||
|
||||
int sysfs_add_dir(struct vnode *at, const char *path, struct vnode **result);
|
||||
int sysfs_add_config_endpoint(struct vnode *at, const char *name, mode_t mode, size_t bufsz, void *ctx, cfg_read_func_t read, cfg_write_func_t write);
|
||||
void sysfs_populate(void);
|
||||
|
||||
@@ -87,6 +87,9 @@ struct process {
|
||||
// Signal
|
||||
uint64_t sigq;
|
||||
|
||||
// procfs
|
||||
struct vnode *fs_entry;
|
||||
|
||||
// State
|
||||
char name[256];
|
||||
uint32_t flags;
|
||||
@@ -113,7 +116,8 @@ struct thread *process_first_thread(struct process *proc);
|
||||
#define THR_INIT_STACK_SET (1 << 1)
|
||||
int thread_init(struct thread *thr, uintptr_t entry, void *arg, int flags);
|
||||
void thread_dump(struct thread *thr);
|
||||
//void thread_cleanup(struct thread *thr);
|
||||
|
||||
void proc_add_entry(struct process *proc);
|
||||
|
||||
struct process *process_child(struct process *of, pid_t pid);
|
||||
void process_unchild(struct process *proc);
|
||||
|
||||
@@ -131,6 +131,7 @@ int sys_execve(const char *path, const char **argv, const char **envp) {
|
||||
uintptr_t entry;
|
||||
size_t argc;
|
||||
int res;
|
||||
int was_kernel = 0;
|
||||
|
||||
if ((res = vfs_stat(&proc->ioctx, path, &st)) != 0) {
|
||||
kerror("execve(%s): %s\n", path, kstrerror(res));
|
||||
@@ -205,6 +206,7 @@ int sys_execve(const char *path, const char **argv, const char **envp) {
|
||||
}
|
||||
|
||||
if (proc->space == mm_kernel) {
|
||||
was_kernel = 1;
|
||||
// Have to allocate a new PID for kernel -> userspace transition
|
||||
proc->pid = process_alloc_pid(1); //thread_alloc_pid(1);
|
||||
proc->pgid = proc->pid;
|
||||
@@ -281,6 +283,10 @@ int sys_execve(const char *path, const char **argv, const char **envp) {
|
||||
thr->data.rsp3_base = ustack;
|
||||
thr->data.rsp3_size = 4 * MM_PAGE_SIZE;
|
||||
|
||||
if (was_kernel) {
|
||||
proc_add_entry(proc);
|
||||
}
|
||||
|
||||
// Up to 4095 argc and envc
|
||||
_assert(procv_vecp[0] < 4096);
|
||||
_assert(procv_vecp[2] < 4096);
|
||||
|
||||
+89
-8
@@ -5,6 +5,7 @@
|
||||
#include "sys/binfmt_elf.h"
|
||||
#include "sys/sys_proc.h"
|
||||
#include "sys/mem/phys.h"
|
||||
#include "sys/snprintf.h"
|
||||
#include "user/signum.h"
|
||||
#include "user/errno.h"
|
||||
#include "user/fcntl.h"
|
||||
@@ -13,6 +14,7 @@
|
||||
#include "sys/thread.h"
|
||||
#include "sys/sched.h"
|
||||
#include "sys/debug.h"
|
||||
#include "fs/sysfs.h"
|
||||
#include "fs/ofile.h"
|
||||
#include "sys/heap.h"
|
||||
|
||||
@@ -37,6 +39,60 @@ static pid_t last_kernel_pid = 0;
|
||||
static pid_t last_user_pid = 0;
|
||||
// TODO: MAKE THIS PER-PROCESSOR
|
||||
static uint64_t fxsave_buf[FXSAVE_REGION / 8] __attribute__((aligned(16)));
|
||||
static struct vnode *g_sysfs_proc_dir;
|
||||
|
||||
static int sysfs_proc_name(void *ctx, char *buf, size_t lim) {
|
||||
sysfs_buf_printf(buf, lim, "%s\n", ((struct process *) ctx)->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sysfs_proc_ioctx(void *ctx, char *buf, size_t lim) {
|
||||
struct process *proc = ctx;
|
||||
sysfs_buf_printf(buf, lim, "%d:%d\n", proc->ioctx.uid, proc->ioctx.gid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct vnode *sysfs_proc_self(struct thread *ctx, struct vnode *link) {
|
||||
_assert(ctx && ctx->proc);
|
||||
return ctx->proc->fs_entry;
|
||||
}
|
||||
|
||||
static void proc_ensure_dir(void) {
|
||||
if (!g_sysfs_proc_dir) {
|
||||
_assert(sysfs_add_dir(NULL, "proc", &g_sysfs_proc_dir) == 0);
|
||||
|
||||
struct vnode *vn = vnode_create(VN_LNK, "self");
|
||||
vn->flags = VN_MEMORY | VN_PER_PROCESS;
|
||||
vn->target_func = sysfs_proc_self;
|
||||
vnode_attach(g_sysfs_proc_dir, vn);
|
||||
}
|
||||
}
|
||||
|
||||
void proc_add_entry(struct process *proc) {
|
||||
char name[16];
|
||||
_assert(proc && !(proc->flags & THREAD_KERNEL));
|
||||
_assert(proc->pid > 0);
|
||||
|
||||
proc_ensure_dir();
|
||||
|
||||
kdebug("BEGIN ADD ENTRY %d\n", proc->pid);
|
||||
snprintf(name, sizeof(name), "%d", proc->pid);
|
||||
_assert(sysfs_add_dir(g_sysfs_proc_dir, name, &proc->fs_entry) == 0);
|
||||
|
||||
_assert(sysfs_add_config_endpoint(proc->fs_entry, "name", SYSFS_MODE_DEFAULT, 64,
|
||||
proc, sysfs_proc_name, NULL) == 0);
|
||||
_assert(sysfs_add_config_endpoint(proc->fs_entry, "ioctx", SYSFS_MODE_DEFAULT, 64,
|
||||
proc, sysfs_proc_ioctx, NULL) == 0);
|
||||
kdebug("END ADD ENTRY %d\n", proc->pid);
|
||||
}
|
||||
|
||||
void proc_del_entry(struct process *proc) {
|
||||
_assert(proc && !(proc->flags & THREAD_KERNEL));
|
||||
_assert(proc->pid > 0);
|
||||
kdebug("BEGIN DEL ENTRY %d\n", proc->pid);
|
||||
sysfs_del_ent(proc->fs_entry);
|
||||
kdebug("END DEL ENTRY %d\n", proc->pid);
|
||||
}
|
||||
|
||||
void context_save_fpu(struct thread *new, struct thread *old) {
|
||||
_assert(old);
|
||||
@@ -45,7 +101,6 @@ void context_save_fpu(struct thread *new, struct thread *old) {
|
||||
memcpy(old->data.fxsave, fxsave_buf, FXSAVE_REGION);
|
||||
old->flags |= THREAD_FPU_SAVED;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void context_restore_fpu(struct thread *new, struct thread *old) {
|
||||
@@ -86,8 +141,6 @@ void process_ioctx_fork(struct process *dst, struct process *src) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int process_signal_pgid(pid_t pgid, int signum) {
|
||||
int ret = 0;
|
||||
|
||||
@@ -99,7 +152,18 @@ int process_signal_pgid(pid_t pgid, int signum) {
|
||||
}
|
||||
}
|
||||
|
||||
return ret == 0 ? -1 : ret;
|
||||
return ret == 0 ? -ECHILD : ret;
|
||||
}
|
||||
|
||||
int process_signal_children(struct process *proc, int signum) {
|
||||
int ret = 0;
|
||||
for (struct process *chld = proc->first_child; chld; chld = chld->next_child) {
|
||||
if (proc->proc_state != PROC_FINISHED) {
|
||||
process_signal(chld, signum);
|
||||
++ret;
|
||||
}
|
||||
}
|
||||
return ret == 0 ? -ECHILD : 0;
|
||||
}
|
||||
|
||||
struct process *process_find(pid_t pid) {
|
||||
@@ -156,6 +220,8 @@ void process_unchild(struct process *proc) {
|
||||
|
||||
void process_cleanup(struct process *proc) {
|
||||
// Leave only the system context required for hierachy tracking and error code/pid
|
||||
proc_del_entry(proc);
|
||||
|
||||
_assert(proc->proc_state == PROC_FINISHED);
|
||||
_assert(proc->thread_count == 1);
|
||||
proc->flags |= PROC_EMPTY;
|
||||
@@ -176,6 +242,13 @@ void process_free(struct process *proc) {
|
||||
// only main remains
|
||||
_assert(proc->thread_count == 1);
|
||||
|
||||
// Reparent children to #1 if any
|
||||
for (struct process *chld = proc->first_child; chld; chld = chld->next_child) {
|
||||
panic("Not implemented: #%d (%s) has children: #%d (%s)\n",
|
||||
proc->pid, proc->name,
|
||||
chld->pid, chld->name);
|
||||
}
|
||||
|
||||
// Sure that no code of this thread will be running anymore -
|
||||
// can clean up its stuff
|
||||
process_cleanup(proc);
|
||||
@@ -248,6 +321,9 @@ int process_init_thread(struct process *proc, uintptr_t entry, void *arg, int us
|
||||
proc->proc_state = PROC_ACTIVE;
|
||||
|
||||
list_add(&proc->g_link, &proc_all_head);
|
||||
if (user) {
|
||||
proc_add_entry(proc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -441,6 +517,10 @@ int sys_fork(struct sys_fork_frame *frame) {
|
||||
struct process *src = src_thread->proc;
|
||||
_assert(src);
|
||||
|
||||
if (src->flags & THREAD_KERNEL) {
|
||||
panic("XXX: kthread fork()ing not implemented\n");
|
||||
}
|
||||
|
||||
if (src->thread_count != 1) {
|
||||
panic("XXX: fork() a multithreaded process\n");
|
||||
}
|
||||
@@ -567,6 +647,7 @@ int sys_fork(struct sys_fork_frame *frame) {
|
||||
dst_thread->data.rsp0 = (uintptr_t) stack;
|
||||
|
||||
list_add(&dst->g_link, &proc_all_head);
|
||||
proc_add_entry(dst);
|
||||
sched_queue(dst_thread);
|
||||
|
||||
return dst->pid;
|
||||
@@ -739,10 +820,10 @@ int sys_kill(pid_t pid, int signum) {
|
||||
} else if (pid == 0) {
|
||||
proc = thread_self->proc;
|
||||
} else if (pid < -1) {
|
||||
// TODO: check if there's any process in that group
|
||||
process_signal_pgid(-pid, signum);
|
||||
|
||||
return 0;
|
||||
return process_signal_pgid(-pid, signum);
|
||||
} else if (pid == -1) {
|
||||
proc = thread_self->proc;
|
||||
return process_signal_children(proc, signum);
|
||||
} else {
|
||||
panic("Not implemented\n");
|
||||
}
|
||||
|
||||
+10
-6
@@ -144,7 +144,7 @@ static int wait_check_pid(struct process *chld, int flags) {
|
||||
|
||||
static int wait_check_pgrp(struct process *proc_self, pid_t pgrp, int flags, struct process **chld) {
|
||||
for (struct process *_chld = proc_self->first_child; _chld; _chld = _chld->next_child) {
|
||||
if (_chld->pgid == pgrp) {
|
||||
if (pgrp == -1 || _chld->pgid == -pgrp) {
|
||||
if (wait_check_pid(_chld, flags) == 0) {
|
||||
*chld = _chld;
|
||||
return 0;
|
||||
@@ -155,6 +155,7 @@ static int wait_check_pgrp(struct process *proc_self, pid_t pgrp, int flags, str
|
||||
}
|
||||
|
||||
int sys_waitpid(pid_t pid, int *status, int flags) {
|
||||
pid_t result_pid = -ECHILD;
|
||||
struct thread *thr = thread_self;
|
||||
_assert(thr);
|
||||
struct process *proc_self = thr->proc;
|
||||
@@ -180,7 +181,7 @@ int sys_waitpid(pid_t pid, int *status, int flags) {
|
||||
if (!any_proc) {
|
||||
return -ECHILD;
|
||||
}
|
||||
} else {
|
||||
} else if (pid != -1) {
|
||||
panic("Not implemented: waitpid(%d, ...)\n", pid);
|
||||
}
|
||||
|
||||
@@ -191,16 +192,16 @@ int sys_waitpid(pid_t pid, int *status, int flags) {
|
||||
}
|
||||
|
||||
res = thread_wait_io(thr, &chld->pid_notify);
|
||||
} else if (pid < -1) {
|
||||
} else if (pid <= -1) {
|
||||
// Check if anybody in pgrp has changed status
|
||||
if (wait_check_pgrp(proc_self, -pid, flags, &chld) == 0) {
|
||||
if (wait_check_pgrp(proc_self, pid, flags, &chld) == 0) {
|
||||
_assert(chld);
|
||||
break;
|
||||
}
|
||||
|
||||
// Build wait list
|
||||
for (struct process *_chld = proc_self->first_child; _chld; _chld = _chld->next_child) {
|
||||
if (_chld->pgid == -pid) {
|
||||
if (pid == -1 || _chld->pgid == -pid) {
|
||||
thread_wait_io_add(thr, &_chld->pid_notify);
|
||||
}
|
||||
}
|
||||
@@ -209,6 +210,8 @@ int sys_waitpid(pid_t pid, int *status, int flags) {
|
||||
res = thread_wait_io_any(thr, ¬ify);
|
||||
|
||||
thread_wait_io_clear(thr);
|
||||
} else {
|
||||
panic("Shouldn't run\n");
|
||||
}
|
||||
|
||||
if (res < 0) {
|
||||
@@ -217,6 +220,7 @@ int sys_waitpid(pid_t pid, int *status, int flags) {
|
||||
}
|
||||
}
|
||||
|
||||
result_pid = chld->pid;
|
||||
if (chld->proc_state == PROC_FINISHED) {
|
||||
if (status) {
|
||||
*status = chld->exit_status;
|
||||
@@ -234,5 +238,5 @@ int sys_waitpid(pid_t pid, int *status, int flags) {
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return result_pid;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user