summaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
authordzwdz2023-01-24 13:53:44 +0100
committerdzwdz2023-01-24 13:53:44 +0100
commitba2f957dd39a44e0828ab4efd809d36d704fd537 (patch)
treecadd70d806481fee77f7b5922c746e40d458046e /src/kernel
parent1e2f807b30cc94fc6dc9fcb24f3e1675fe147439 (diff)
kernel/procfs: allow interrupting processes
Diffstat (limited to 'src/kernel')
-rwxr-xr-xsrc/kernel/proc.c4
-rw-r--r--src/kernel/vfs/procfs.c72
2 files changed, 57 insertions, 19 deletions
diff --git a/src/kernel/proc.c b/src/kernel/proc.c
index d8c7e57..b49b645 100755
--- a/src/kernel/proc.c
+++ b/src/kernel/proc.c
@@ -196,8 +196,8 @@ void process_kill(struct process *p, int ret) {
process_transition(p, PS_TOMBSTONE);
}
}
- if (p == process_first) {
- assert(!p->child);
+ if (p == process_first && p->child) {
+ _panic("init killed prematurely");
}
process_tryreap(p);
diff --git a/src/kernel/vfs/procfs.c b/src/kernel/vfs/procfs.c
index 5837012..7ca8c14 100644
--- a/src/kernel/vfs/procfs.c
+++ b/src/kernel/vfs/procfs.c
@@ -6,40 +6,65 @@
#include <kernel/vfs/request.h>
#include <shared/mem.h>
-static uint32_t openpath(const char *path, size_t len, struct process *root);
+enum phandle_type {
+ PhDir,
+ PhIntr,
+};
+
+struct phandle {
+ uint32_t gid;
+ enum phandle_type type;
+};
+
+static struct phandle *openpath(const char *path, size_t len, struct process *root);
static struct process *findgid(uint32_t gid, struct process *root);
static void procfs_accept(struct vfs_request *req);
static void procfs_cleanup(struct vfs_backend *be);
+static int isdigit(int c);
-static uint32_t
+static struct phandle *
openpath(const char *path, size_t len, struct process *p)
{
- if (len == 0) return 0;
+ struct phandle *h;
+ enum phandle_type type;
+ if (len == 0) return NULL;
path++, len--;
- while (len) {
+ while (len && isdigit(*path)) {
+ /* parse numerical segment / "directory" name */
uint32_t cid = 0;
for (; 0 < len && *path != '/'; path++, len--) {
char c = *path;
- if (!('0' <= c && c <= '9')) {
- return 0;
+ if (!isdigit(c)) {
+ return NULL;
}
cid = cid * 10 + *path - '0';
}
- if (len == 0) {
- return 0;
- }
+ if (len == 0) return NULL;
assert(*path == '/');
path++, len--;
p = p->child;
- if (!p) return 0;
+ if (!p) return NULL;
while (p->cid != cid) {
p = p->sibling;
- if (!p) return 0;
+ if (!p) return NULL;
}
}
- return p->globalid;
+
+ /* parse the per-process part */
+ if (len == 0) {
+ type = PhDir;
+ } else if (len == 4 && memcmp(path, "intr", 4) == 0) {
+ type = PhIntr;
+ } else {
+ return NULL;
+ }
+
+ h = kmalloc(sizeof *h);
+ h->gid = p->globalid;
+ h->type = type;
+ return h;
}
static struct process *
@@ -55,29 +80,31 @@ static void
procfs_accept(struct vfs_request *req)
{
struct process *root = req->backend->kern.data;
+ struct phandle *h = (__force void*)req->id;
struct process *p;
char buf[512];
assert(root);
if (req->type == VFSOP_OPEN) {
- int gid;
assert(req->input.kern);
- gid = openpath(req->input.buf_kern, req->input.len, root);
- vfsreq_finish_short(req, gid == 0 ? -ENOENT : gid);
+ h = openpath(req->input.buf_kern, req->input.len, root);
+ vfsreq_finish_short(req, h ? (long)h : -ENOENT);
return;
}
- p = findgid((uintptr_t)req->id, root);
+ assert(h);
+ p = findgid(h->gid, root);
if (!p) {
vfsreq_finish_short(req, -EGENERIC);
return;
}
- if (req->type == VFSOP_READ) {
+ if (req->type == VFSOP_READ && h->type == PhDir) {
// TODO port dirbuild to kernel
int pos = 0;
if (req->offset != 0) {
vfsreq_finish_short(req, -ENOSYS);
return;
}
+ pos += snprintf(buf + pos, 512 - pos, "intr")+1;
for (struct process *iter = p->child; iter; iter = iter->sibling) {
assert(pos < 512);
// processes could possibly be identified by unique identifiers instead
@@ -91,6 +118,12 @@ procfs_accept(struct vfs_request *req)
assert(0 <= pos && (size_t)pos <= sizeof buf);
virt_cpy_to(req->caller->pages, req->output.buf, buf, pos);
vfsreq_finish_short(req, pos);
+ } else if (req->type == VFSOP_WRITE && h->type == PhIntr) {
+ process_intr(p);
+ vfsreq_finish_short(req, req->input.len);
+ } else if (req->type == VFSOP_CLOSE) {
+ kfree(h);
+ vfsreq_finish_short(req, 0);
} else {
vfsreq_finish_short(req, -ENOSYS);
}
@@ -104,6 +137,11 @@ procfs_cleanup(struct vfs_backend *be)
p->refcount--;
}
+static int
+isdigit(int c) {
+ return '0' <= c && c <= '9';
+}
+
struct vfs_backend *
procfs_backend(struct process *proc)
{