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 };