Plan 9 from Bell Labs’s /usr/web/sources/plan9/sys/lib/acid/kernel

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


include("/sys/lib/acid/syscall");

// print various /proc files
defn fd() {
	rc("cat /proc/"+itoa(pid)+"/fd");
}

defn segment() {
	rc("cat /proc/"+itoa(pid)+"/segment");
}

defn ns() {
	rc("cat /proc/"+itoa(pid)+"/ns");
}

defn qid(qid) {
	complex Qid qid;
	return itoa(qid.path\X)+"."+itoa(qid.vers\X);
}

defn path(p) {
	complex Path p;
	if p != 0 then {
		return *(p.s\s);
	} else
		return "<null>";
}

// print Image cache contents
// requires include("/sys/src/9/xxx/segment.acid")
IHASHSIZE = 64;
defn imagecacheline(h) {
	while h != 0 do {
		complex Image h;
		print (h\X, " ", qid(h.qid), " type ", h.type\D, " ref ", h.ref, " next ", h.next\X, " ", path(h.c.path), "\n");
		h = h.hash;
	}
}

defn imagecache() {
	local i;

	i=0; loop 1,IHASHSIZE do {
		imagecacheline(imagealloc.free[i]);
		i = i+1;
	}
}

// dump channels
defn chan(c) {
	local d, q;

	c = (Chan)c;
	d=(Dev)(*(devtab+4*c.type));
	q=c.qid;
	print("chan(", c\X, "): ref=", c.ref\D, " #", d.dc\r, c.dev\D, " (", q.path, " ", q.vers\D, " ", q.type\X, ")");
	print(" fid=", c.fid\D, " iounit=", c.iounit\D);
	if c.ref != 0 then {
		print(" ", path(c.path), " mchan=", c.mchan\X);
		if c.mchan != 0 then {
			print(" ", path(c.mchan.path));
		}
	}
	print("\n");
}

defn chans() {
	local c;

	c = (Chan)chanalloc.list;
	while c != 0 do {
		if c.ref != 0 then
			chan(c);
		c=(Chan)c.link;
	}
}

defn nchans() {
	local c, n;
	
	n = 0;
	c = (Chan)chanalloc.list;
	while c != 0 do {
		if c.ref != 0 then
			n++;
		c = (Chan)c.link;
	}
	return n;
}

defn activechanlist() {
	local l, n;
	
	l = {};
	c = (Chan)chanalloc.list;
	while c != 0 do {
		if c.ref != 0 then
			l = append l,c;
		c = (Chan)c.link;
	}
	return l;
}

defn difflist(a, b) {
	local l, x;
	
	l = {};
	while a != {} do {
		x = head a;
		if match(x, b) == -1 then
			l = append l, x;
		a = tail a;
	}
	return l;
}

_active_chan_list = {};
defn newchans() {
	local l, new;
	
	l = activechanlist();
	if _active_chan_list != {} then
		newerchans(_active_chan_list);
	_active_chan_list = l;
}

defn newerchans(oldlist){
	local new;
	
	new = difflist(activechanlist(), oldlist);
	while new != {} do {
		chan(head new);
		new = tail new;
	}
}

// look for channels that refer to themselves
defn badchans() {
	local bad, c, i, len, mtpt, p;
	
	c = (Chan)chanalloc.list;
	while c != 0 do {
		if c.ref != 0 then {
			bad = "";
			p = (Path)c.path;
			if p != 0 then {
				path(p);
				mtpt = p.mtpt;
				len = p.mlen;
				i=0; loop 1,len do {
					if mtpt[i] == c then
						bad = bad+" mtpt self-ref";
					i = i+1;
				}
			}
			if bad != "" then
				print("chan(", c\X, "):", bad, "\n");
		}
		c = (Chan)c.link;
	}
}

// manipulate processes
defn proctab(x) {
	return procalloc.arena+sizeofProc*x;
}

defn proc(p) {
	complex Proc p;
	local s, i;

	if p.state != 0 && p.pid != 0 && p.text != 0 then {	// 0 is Dead
		s = p.psstate;
		if s == 0 then {
			s = "kproc";
		} else {
			s = *(s\s);
		}
		print(p\X, " ", p.pid, ": ", *(p.text\s), " ", *(p.user\s), " pc ", p.pc\X, " ", s, " (", *(statename[p.state]\s), ") ut ", p.time[0]\D, " st ", p.time[1]\D, " qpc ", p.qpc\X, "\n");
	}
}

defn procenv(p) {
	complex Proc p;
	local e, v;

	e = p.egrp;
	complex Egrp e;
	v = e.ent;
	while v != 0 do {
		complex Evalue v;
		print(*(v.name\s), "=");
		printstringn(v.value, v.len);
		print("\n");
		v = v.link;
	}
}

KSTACK=4096;

defn procstksize(p) {
	complex Proc p;
	local top, sp;

	if p.state != 0 then {	// 0 is Dead
		top = p.kstack+KSTACK;
		sp = *p.sched;
		print(top-sp\D, "\n");
	}
}

defn procstk(p) {
	complex Proc p;
	local l;

	if p.state != 0 then {	// 0 is Dead
		l = p.sched;
		if objtype=="386" then
			_stk(gotolabel, *l, linkreg(0), 0);
		else
			_stk(*(l+4), *l, linkreg(0), 0);
	}
}

defn procs() {
	local i;

	i=0; loop 1,conf.nproc do {
		proc(proctab(i));
		i = i+1;
	}
}

defn stacks() {
	local i, p;

	i=0; loop 1,conf.nproc do {
		p = (Proc)proctab(i);
		if p.state != 0 then {
			print("=========================================================\n");
			proc(p);
			procstk(p);
		}
		i = i+1;
	}
}

defn stacksizes() {
	local i;

	i=0; loop 1,conf.nproc do {
		procstksize(proctab(i));
		i = i+1;
	}
}

// segment-related
defn procsegs(p) {
	complex Proc p;
	local i;

	i=0; loop 1,NSEG do {
		psegment(p.seg[i]);
		i = i+1;
	}
}

segtypes = { "text", "data", "bss", "stack", "shared", "physical", "shdata", "map" };
defn psegment(s) {
	complex Segment s;

	if s != 0 then {
		print(s\X, " ", segtypes[s.type&SG_TYPE], " ", s.base\X, "-", s.top\X, " image ", s.image\X, "\n");
	}
}

// find physical address for an address in a given process
defn procaddr(p, a) {
	complex Proc p;
	local i, s, r;

	r = 0;
	i=0; loop 1,NSEG do {
		s = p.seg[i];
		if s != 0 then {
			complex Segment s;
			if s.base <= a && a < s.top then {
				r = segaddr(s, a);
			}
		}
		i = i+1;
	}
	return r;
}

// find an address in a given segment
defn segaddr(s, a) {
	complex Segment s;
	local pte, pg;

	a = a - s.base;
	if s.map == 0 || s.mapsize < a/PTEMAPMEM then {
		return 0;
	}

	pte = s.map[a/PTEMAPMEM];
	if pte == 0 then {
		return 0;
	}

	complex Pte pte;
	pg = pte.pages[(a%PTEMAPMEM)/BY2PG];
	if pg == 0 then {
		return 0;
	}

	if pg & 1 then {	// swapped out, return disk address
		return pg&~1;
	}

	complex Page pg;
	return (KZERO|(pg.pa+(a%BY2PG)))\X;
}

defn kzero() {
	return main - (main & 0x0FFFFFFF);
}

// PC only
PTEMAPMEM = (1024*1024);
BY2PG = 4096;
PTEPERTAB = (PTEMAPMEM/BY2PG);
defn up() {
	local mach;

	MACHADDR = KZERO+0x15000;
	mach = MACHADDR;
	complex Mach mach;
	return mach.externup;
}

defn intrcount() {
	local p, pp, t, i, j;

	p = intrtimes;
	i=0;
	loop 1,256 do {
		pp = p[i];
		i=i+1;
		if pp != 0 then {
			j=0;
			t=0;
			loop 1,1000 do {
				t = t+pp[j];
				j=j+1;
			}
			print(itoa(i, "%5d"), " ", itoa(t, "%11d"), "\n");
		}
	}
}

print("/sys/lib/acid/kernel");

defn needacid(s){
	print("\trc(\"cd /sys/src/9/", kdir, "; mk ", s, ".acid\")\n");
	print("\tinclude(\"/sys/src/9/", kdir, "/", s, ".acid\")\n");
}

defn kinit() {
if (map()[2]) != {} then {	// map has more than two elements -> active proc
	kdir = "unknown";
	KZERO = kzero();
	
	if objtype == "386" then {
		map({"*data", KZERO, 0xffffffff, KZERO});
		kdir="pc";
	}
	if (objtype == "mips" || objtype == "mips2") then {
		kdir = "ch";
	}
	if objtype == "alpha" then {
		map({"*data", KZERO, 0xffffffff, KZERO});
		kdir = "alpha";
	}
	needacid("proc");
}
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.