plan9fox/sys/lib/acid/kernel
cinap_lenrek 2bc9e8e5e3 kernel: make image cache not hold onto the channel, remove nocache flag
the image cache should not hold onto the text file channel
when not neccesary. now, the image keeps track of the number
of page cache references in Image.pgref. if the number of
page cache references and Image.ref are equal, this means
all the references to this image are from the page cache.
so no segments are using this image. in that case, we can
close the channel, but keep the Image in the hash table.

when attachimage() finds our image, it will check if Image.c
is nil and reattach the channel to the image before it is
used.

the Image.nocache flag isnt needed anymore.
2013-11-08 22:31:26 +01:00

429 lines
6.9 KiB
Plaintext

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
IHASHSIZE = 64;
defn imagecacheline(h) {
local d, p, q;
while h != 0 do {
complex Image h;
d=(Dev)(*(devtab+4*h.type));
p = "*closed*";
if h.c != 0 then
p = path(h.c.path);
q = h.qid;
print (h\X, " ref=", h.ref, " pgref=", h.pgref, "\t#", d.dc\r, h.dev\D, " (",
q.path, " ", q.vers\D, " ", q.type\X, ") ", p, "\n");
h = h.hash;
}
}
defn imagecache() {
local i;
i=0; loop 1,IHASHSIZE do {
imagecacheline(imagealloc.hash[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 findchan(dev,type,path) {
local c;
c = (Chan)chanalloc.list;
while c != 0 do {
if c.ref != 0 then {
if c.dev == dev && c.type == type && c.qid.path == path then
return c;
}
c=(Chan)c.link;
}
return 0;
}
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;
}
}
NHASH=128;
defn mntcache() {
local i, m, c;
i=0; loop 1,NHASH do {
m = cache.hash[i];
while m != 0 do {
complex Mntcache m;
print(m\X, " dev ", m.dev\D, " type ", m.type, " qid (",
m.qid.path, " ", m.qid.vers\D, ")\n");
c = findchan(m.dev, m.type, m.qid.path);
if c != 0 then {
print(" ");
chan(c);
}
m = m.hash;
}
i = i+1;
}
}
// 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 i, e, v;
e = p.egrp;
complex Egrp e;
i=0; loop 1,e.nent do {
v = e.ent[i];
i = i+1;
complex Evalue v;
print(*(v.name\s), "=");
printstringn(v.value, v.len);
print("\n");
}
}
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, t, i, j;
p = intrtimes;
i=0; loop 1,256 do {
t=0;
j=0; loop 1,20 do {
t = t+*p++;
j=j+1;
}
print(itoa(i, "%5d"), " ", itoa(t, "%11d"), "\n");
i=i+1;
}
}
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");
needacid("chan");
needacid("segment");
needacid("cache");
}
}