9os

Experimental kernel using plan9 ideas for embedded device
git clone git://git.simple-cc.org/9os
Log | Files | Refs | README | LICENSE

devproc.c (3821B)


      1 #include <os9/os9.h>
      2 #include <libk.h>
      3 
      4 #include "dev.h"
      5 
      6 #define PATH(b, t) \
      7 	((unsigned long long) (b) << 32 | \
      8 	 (unsigned long long) (t))
      9 
     10 #define TYPE(q) (((q.path) >> 32) & 0xFF)
     11 #define TASK(q) ((q.path) & 0xFFFFFFFF)
     12 
     13 enum procqid {
     14 	Qprocfs,
     15 	Qtaskdir,
     16 
     17 	Qtaskattr,
     18 	Qtaskstatus,
     19 };
     20 
     21 static Dirtab tasktab[] = {
     22 	{"attr",  QID(CHFILE, 0, Qtaskattr), 0, O_READ},
     23 	{"status", QID(CHFILE, 0, Qtaskstatus), 0, O_READ},
     24 };
     25 
     26 static int
     27 procfsgen(Chan *c, int n, Dir *dir)
     28 {
     29 	Task *tp;
     30 	char nam[NAMELEN];
     31 
     32 	switch (n) {
     33 	case NR_TASKS:
     34 		mkentry(c, dir,
     35 		        "cur", 0,
     36 		        QID(CHDIR, 0, PATH(Qtaskdir, proc->pid)),
     37 		        O_READ);
     38 		return 1;
     39 	case NR_TASKS+1:
     40 		return -1;
     41 	default:
     42 		n = getntask(n, &tp);
     43 		if (n < 0)
     44 			return -1;
     45 		if (n == 0)
     46 			return 0;
     47 
     48 		ksnprint(nam, NAMELEN, "%d", tp->pid);
     49 		mkentry(c, dir,
     50 			nam, 0,
     51 			QID(CHDIR, 0, PATH(Qtaskdir, tp->pid)),
     52 		        O_READ);
     53 		unlocktask(tp);
     54 		return 1;
     55 	}
     56 }
     57 
     58 static int
     59 taskgen(Chan *c, int n, Dir *dir)
     60 {
     61 	int r, pid = TASK(c->qid);
     62 
     63 	if ((r = devgen(c, tasktab, NELEM(tasktab), n, dir)) == 1)
     64 		dir->qid.path = PATH(dir->qid.path, pid);
     65 	return r;
     66 }
     67 
     68 static int
     69 procgen(Chan *c, Dirtab *tab, int ntab, int n, Dir *dir)
     70 {
     71 	switch (TYPE(c->qid)) {
     72 	case Qprocfs:
     73 		return procfsgen(c, n, dir);
     74 	case Qtaskdir:
     75 		return taskgen(c, n, dir);
     76 	default:
     77 		return 0;
     78 	}
     79 }
     80 
     81 static int
     82 procwalk(Chan *c, char *name)
     83 {
     84 	return devwalk(c, name, NULL, 0, procgen);
     85 }
     86 
     87 static int
     88 taskattrread(Chan *c, void *buf, int n)
     89 {
     90 	int len;
     91 	Task *tp;
     92 	char tmp[1024];
     93 
     94 	if ((tp = gettask(TASK(c->qid))) == NULL)
     95 		panic("taskattrread:gettask");
     96 
     97 	len = ksnprint(tmp,
     98 	               sizeof(tmp),
     99 	               "pid: %d\n"
    100 	               "entry: %p\n"
    101 	               "errno: %d\n"
    102 	               "stack size: %zd\n"
    103 	               "base prio: %d\n"
    104 	               "period: %ld\n"
    105 	               "capacity: %ld\n"
    106 	               "deadline: %ld\n",
    107 	               tp->pid,
    108 	               tp->entry,
    109 	               tp->errno,
    110 	               tp->stack,
    111 	               tp->prio,
    112 	               tp->period,
    113 	               tp->capacity,
    114 	               tp->deadline);
    115 	unlocktask(tp);
    116 
    117 	if (len == sizeof(tmp))
    118 		panic("temporary buffer too short");
    119 	return buf2chan(c, buf, tmp, n, len);
    120 }
    121 
    122 static int
    123 taskstatusread(Chan *c, void *buf, int n)
    124 {
    125 	int len;
    126 	Task *tp;
    127 	char tmp[1024];
    128 	static char *states[] = {
    129 		[TINIT] = "init",
    130 		[TREADY] = "ready",
    131 		[TRUNNING] = "running",
    132 		[TWAITING] = "waiting",
    133 		[TFAULTED] = "faulted",
    134 	};
    135 
    136 	if ((tp = gettask(TASK(c->qid))) ==  NULL)
    137 		panic("taskstatusread:gettask");
    138 
    139 	len = ksnprint(tmp,
    140 	               sizeof(tmp),
    141 	               "prio: %d\n"
    142 	               "flags: %x\n"
    143 	               "deadline time: %ld\n"
    144 	               "state: %s\n"
    145 	               "affinity: %lx\n"
    146 	               "retained prio: %d\n",
    147 	               tp->prio,
    148 	               tp->flags,
    149 	               tp->deadtime,
    150 	               states[tp->state],
    151 	               tp->affinity,
    152 	               tp->retainprio);
    153 	unlock(&tp->m);
    154 
    155 	if (len == sizeof(tmp))
    156 		panic("temporary buffer too short");
    157 	return buf2chan(c, buf, tmp, n, len);
    158 }
    159 
    160 static int
    161 procread(Chan *c, void *buf, int n)
    162 {
    163 	switch (TYPE(c->qid)) {
    164 	case Qprocfs:
    165 	case Qtaskdir:
    166                 return dirread(c, buf, n, NULL, 0, procgen);
    167 	case Qtaskattr:
    168 		return taskattrread(c, buf, n);
    169 	case Qtaskstatus:
    170 		return taskstatusread(c, buf, n);
    171 	default:
    172 		panic("procread");
    173 	}
    174 }
    175 
    176 static int
    177 procstat(Chan *c, char *file, unsigned char *buf, int n)
    178 {
    179 	return devstat(c, file, buf, n, NULL, 0, procgen);
    180 }
    181 
    182 Dev procdevtab = {
    183 	.id = 'p',
    184 	.stat = procstat,
    185 	.clone = devclone,
    186 	.attach = devattach,
    187 	.walk = procwalk,
    188 	.read = procread,
    189 	.write = deverrwrite,
    190 	.mount = deverrmount,
    191 	.seek = devseek,
    192 	.sync = devsync,
    193 	.close = devclose,
    194 };