9os

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 0513366ff3f257540c112bef1ad71975cbae9e18
parent d9aeebc9c944482cd9e40f7666f5f4226aa5c04d
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Tue,  8 Sep 2020 15:06:47 +0200

devproc: Add devproc

This device driver helps to inspect and interact with
processes and tasks.

Change-Id: I1faa120078a150b6a7995957cc724442527ceadc

Diffstat:
Msrc/kernel/arch/hosted/9os | 1+
Msrc/kernel/arch/hosted/kernel.c | 2++
Asrc/kernel/dev/devproc.c | 304+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/kernel/dev/devroot.c | 2++
4 files changed, 309 insertions(+), 0 deletions(-)

diff --git a/src/kernel/arch/hosted/9os b/src/kernel/arch/hosted/9os @@ -7,4 +7,5 @@ dev blk dummyblk ar + proc end diff --git a/src/kernel/arch/hosted/kernel.c b/src/kernel/arch/hosted/kernel.c @@ -71,6 +71,8 @@ namespace(void) panic("bind:/dev/cons"); if (bind("#b", "/dev/blk") < 0) panic("bind:/dev/blk"); + if (bind("#p", "/proc") < 0) + panic("bind:/proc"); if ((fd = open("/dev/cons/ctl", O_WRITE)) < 0) panic("open:/dev/cons/ctl write"); diff --git a/src/kernel/dev/devproc.c b/src/kernel/dev/devproc.c @@ -0,0 +1,304 @@ +#include <9os/9os.h> +#include <9os/io.h> +#include <libk.h> + +#include "dev.h" + +#define PATH(b, p, t) \ + ((unsigned long long) (b) << 32 | \ + (unsigned long long) (p) << 16 | \ + (unsigned long long) (t)) + +#define TYPE(q) (((q.path) >> 32) & 0xFF) +#define PROC(q) (((q.path) >> 16) & 0xFFFF) +#define TASK(q) ((q.path) & 0xFFFF) + +enum procqid { + Qprocfs, + Qprocdir, + Qtaskdir, + + Qprocattr, + Qprocstatus, + Qproctask, + Qtaskattr, + Qtaskstatus, +}; + +static const Dirtab procdirtab[] = { + {"attr", QID(CHFILE, 0, Qprocattr), 0, O_READ}, + {"status", QID(CHFILE, 0, Qprocstatus), 0, O_READ}, +}; + +static const Dirtab tasktab[] = { + {"attr", QID(CHFILE, 0, Qtaskattr), 0, O_READ}, + {"status", QID(CHFILE, 0, Qtaskstatus), 0, O_READ}, +}; + +static int +procfsgen(Chan *c, const Dirtab *tab, int ntab, int n, Dir *dir) +{ + Proc *p; + char nam[NAMELEN]; + + if ((p = getnproc(n)) == NULL) + return 0; + + ksnprint(nam, NAMELEN, "%d", p->pid); + mkentry(c, dir, + nam, 0, + QID(CHDIR, 0, PATH(Qprocdir, p->pid, 0)), + O_READ); + + return 1; +} + +static int +procdirgen(Chan *c, const Dirtab *tab, int ntab, int n, Dir *dir) +{ + Proc *pp; + Task *tp; + int r; + char nam[NAMELEN]; + + if ((pp = getproc(PROC(c->qid))) == NULL) + panic("procdirgen"); + + r = devgen(c, procdirtab, NELEM(procdirtab), n, dir); + if (r) { + dir->qid.path = PATH(dir->qid.path, pp->pid, 0); + return 1; + } + + n -= NELEM(procdirtab); + if ((tp = getntask(pp, n)) == NULL) + return 0; + + ksnprint(nam, NAMELEN, "%d", tp->tid); + mkentry(c, dir, + nam, 0, + QID(CHDIR, 0, PATH(Qtaskdir, pp->pid, tp->tid)), + O_READ); + + return 1; +} + +static int +taskgen(Chan *c, const Dirtab *tab, int ntab, int n, Dir *dir) +{ + int pid = PROC(c->qid); + int tid = TASK(c->qid); + + if (!devgen(c, tasktab, NELEM(tasktab), n, dir)) + return 0; + dir->qid.path = PATH(dir->qid.path, pid, tid); + + return 1; +} + +static int +procgen(Chan *c, const Dirtab *tab, int ntab, int n, Dir *dir) +{ + switch (TYPE(c->qid)) { + case Qprocfs: + return procfsgen(c, tab, ntab, n, dir); + case Qprocdir: + return procdirgen(c, tab, ntab, n, dir); + case Qtaskdir: + return taskgen(c, tab, ntab, n, dir); + default: + return 0; + } +} + +static int +procwalk(Chan *c, const char *name) +{ + return devwalk(c, name, NULL, 0, procgen); +} + +static int +procattrread(Chan *c, void *buf, int n) +{ + int len; + Proc *pp; + char tmp[1024]; + + if ((pp = getproc(PROC(c->qid))) == NULL) + panic("procattrread:getproc"); + + len = ksnprint(tmp, + sizeof(tmp), + "name: %s\n" + "pid: %d\n" + "period: %ld\n" + "duration: %ld\n" + "affinity: %lx\n" + "entry: %p\n" + "system: %s\n", + pp->name, + pp->pid, + pp->period, + pp->duration, + pp->affinity, + pp->entry, + (pp->flags & PSYSTEM) ? "yes" : "no"); + + if (len == sizeof(tmp)) + panic("procattrread:len"); + return buf2chan(c, buf, tmp, n, len); +} + +static int +procstatusread(Chan *c, void *buf, int n) +{ + int len; + Proc *pp; + static char *modes[] = { + [PDISABLED] = "disabled", + [PCOLD_START] = "cold_start", + [PWARM_START] = "warm_boot", + [PIDLE] = "idle", + [PNORMAL] = "normal", + }; + static char *starts[] = { + [SNORMAL] = "normal", + }; + char tmp[1024]; + + if ((pp = getproc(PROC(c->qid))) == NULL) + panic("procstatusread:getproc"); + + len = ksnprint(tmp, + sizeof(tmp), + "locklevel: %d\n" + "mode: %s\n" + "start: %s\n" + "ehandler: %p\n", + pp->locklevel, + modes[pp->mode], + starts[pp->start], + pp->errhdl); + + if (len == sizeof(tmp)) + panic("procstatusread:len"); + return buf2chan(c, buf, tmp, n, len); +} + +static int +taskattrread(Chan *c, void *buf, int n) +{ + int len; + Proc *pp; + Task *tp; + char tmp[1024]; + + if ((pp = getproc(PROC(c->qid))) == NULL) + panic("bad process"); + if ((tp = gettask(pp, TASK(c->qid))) == NULL) + panic(""); + + len = ksnprint(tmp, + sizeof(tmp), + "name: %s\n" + "tid: %d\n" + "entry: %p\n" + "stack size: %zd\n" + "base prio: %d\n" + "period: %ld\n" + "capacity: %ld\n" + "deadline: %ld\n", + tp->name, + tp->tid, + tp->entry, + tp->stack, + tp->prio, + tp->period, + tp->capacity, + tp->deadline); + + if (len == sizeof(tmp)) + panic("temporary buffer too short"); + return buf2chan(c, buf, tmp, n, len); +} + +static int +taskstatusread(Chan *c, void *buf, int n) +{ + int len; + Proc *pp; + Task *tp; + char tmp[1024]; + static char *states[] = { + [TDORMANT] = "dormant", + [TREADY] = "ready", + [TRUNNING] = "running", + [TWAITING] = "waiting", + [FAULTED] = "faulted", + }; + + if ((pp = getproc(PROC(c->qid))) == NULL) + panic("taskstatusread:getproc"); + + if ((tp = gettask(pp, TASK(c->qid))) == NULL) + panic("taskstatusread:gettask"); + + len = ksnprint(tmp, + sizeof(tmp), + "prio: %d\n" + "flags: %x\n" + "deadline time: %ld\n" + "state: %s\n" + "affinity: %lx\n" + "retained prio: %d\n", + tp->prio, + tp->flags, + tp->deadtime, + states[tp->state], + tp->affinity, + tp->retainprio); + + if (len == sizeof(tmp)) + panic("temporary buffer too short"); + return buf2chan(c, buf, tmp, n, len); +} + +static int +procread(Chan *c, void *buf, int n) +{ + switch (TYPE(c->qid)) { + case Qprocfs: + case Qprocdir: + case Qtaskdir: + return dirread(c, buf, n, NULL, 0, procgen); + case Qprocattr: + return procattrread(c, buf, n); + case Qprocstatus: + return procstatusread(c, buf, n); + case Qtaskattr: + return taskattrread(c, buf, n); + case Qtaskstatus: + return taskstatusread(c, buf, n); + default: + panic("procread"); + } +} + +static int +procstat(Chan *c, char *file, unsigned char *buf, int n) +{ + return devstat(c, file, buf, n, NULL, 0, procgen); +} + +const Dev procdevtab = { + .id = 'p', + .stat = procstat, + .clone = devclone, + .attach = devattach, + .walk = procwalk, + .read = procread, + .write = deverrwrite, + .mount = deverrmount, + .seek = devseek, + .sync = devsync, +}; diff --git a/src/kernel/dev/devroot.c b/src/kernel/dev/devroot.c @@ -15,6 +15,7 @@ enum Orootqid { Qdevblk, Qarfs, Qfip, + Qproc, Qblobs, Qblobctl, }; @@ -27,6 +28,7 @@ static const Dirtab dirtab[] = { {"blobs", QID(CHDIR, 0, Qblobs), 0, O_READ}, {"arfs", QID(CHDIR, 0, Qarfs), 0, O_READ}, {"fip", QID(CHDIR, 0, Qfip), 0, O_READ}, + {"proc", QID(CHDIR, 0, Qproc), 0, O_READ}, }; static const Dirtab devfstab[] = {