diff options
author | dzwdz | 2023-01-24 13:53:44 +0100 |
---|---|---|
committer | dzwdz | 2023-01-24 13:53:44 +0100 |
commit | ba2f957dd39a44e0828ab4efd809d36d704fd537 (patch) | |
tree | cadd70d806481fee77f7b5922c746e40d458046e /src/kernel | |
parent | 1e2f807b30cc94fc6dc9fcb24f3e1675fe147439 (diff) |
kernel/procfs: allow interrupting processes
Diffstat (limited to 'src/kernel')
-rwxr-xr-x | src/kernel/proc.c | 4 | ||||
-rw-r--r-- | src/kernel/vfs/procfs.c | 72 |
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) { |