#include "dat.h"#include "fns.h"#include "error.h"#include "interp.h"#include <isa.h>#include "runt.h" extern Pool* imagmem;extern void (*memmonitor)(int, ulong, ulong, ulong); static void cpxec(Prog *);static void memprof(int, void*, ulong);static void memprofmi(int, ulong, ulong, ulong); extern Inst* pc2dispc(Inst*, Module*); static int interval = 100; /* Sampling interval in milliseconds */ enum{ HSIZE = 32,}; #define HASH(m) ((m)%HSIZE) /* cope with multiple profilers some day */ typedef struct Record Record;struct Record{ int id; char* name; char* path; Inst* base; int size; /*Module* m; */ ulong mtime; Qid qid; Record* hash; Record* link; ulong bucket[1];}; struct{ Lock l; vlong time; Record* hash[HSIZE]; Record* list;} profile; typedef struct Pmod Pmod;struct Pmod{ char* name; Pmod* link;} *pmods; #define QSHIFT 4#define QID(q) ((ulong)(q).path&0xf)#define QPID(pid) ((pid)<<QSHIFT)#define PID(q) ((q).vers)#define PATH(q) ((ulong)(q).path&~((1<<QSHIFT)-1)) enum{ Qdir, Qname, Qpath, Qhist, Qpctl, Qctl,}; Dirtab profdir[] ={ ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555, "name", {Qname}, 0, 0444, "path", {Qpath}, 0, 0444, "histogram", {Qhist}, 0, 0444, "pctl", {Qpctl}, 0, 0222, "ctl", {Qctl}, 0, 0222,}; enum{ Pnil, /* null profiler */ Psam, /* sampling profiler */ Pcov, /* coverage profiler */ Pmem, /* heap memory profiler */}; enum{ Mnone = 0, Mmain = 1, Mheap = 2, Mimage = 4,}; static int profiler = Pnil;static int mprofiler = Mnone; static int ids;static int samplefn; static void sampler(void*); static Record*getrec(int id){ Record *r; for(r = profile.list; r != nil; r = r->link) if(r->id == id) break; return r;} static voidaddpmod(char *m){ Pmod *p = malloc(sizeof(Pmod)); if(p == nil) return; p->name = malloc(strlen(m)+1); if(p->name == nil){ free(p); return; } strcpy(p->name, m); p->link = pmods; pmods = p;} static voidfreepmods(void){ Pmod *p, *np; for(p = pmods; p != nil; p = np){ free(p->name); np = p->link; free(p); } pmods = nil;} static intinpmods(char *m){ Pmod *p; for(p = pmods; p != nil; p = p->link) if(strcmp(p->name, m) == 0) return 1; return 0;} static voidfreeprof(void){ int i; Record *r, *nr; ids = 0; profiler = Pnil; mprofiler = Mnone; freepmods(); for(r = profile.list; r != nil; r = nr){ free(r->name); free(r->path); nr = r->link; free(r); } profile.list = nil; profile.time = 0; for(i = 0; i < HSIZE; i++) profile.hash[i] = nil;} static intprofgen(Chan *c, char *name, Dirtab *d, int nd, int s, Dir *dp){ Qid qid; Record *r; ulong path, perm, len; Dirtab *tab; USED(name); USED(d); USED(nd); if(s == DEVDOTDOT) { mkqid(&qid, Qdir, 0, QTDIR); devdir(c, qid, "#P", 0, eve, 0555, dp); return 1; } if(c->qid.path == Qdir && c->qid.type & QTDIR) { acquire(); if(s-- == 0){ tab = &profdir[Qctl]; mkqid(&qid, PATH(c->qid)|tab->qid.path, c->qid.vers, QTFILE); devdir(c, qid, tab->name, tab->length, eve, tab->perm, dp); release(); return 1; } r = profile.list; while(s-- && r != nil) r = r->link; if(r == nil) { release(); return -1; } sprint(up->genbuf, "%.8lux", (ulong)r->id); mkqid(&qid, (r->id<<QSHIFT), r->id, QTDIR); devdir(c, qid, up->genbuf, 0, eve, DMDIR|0555, dp); release(); return 1; } if(s >= nelem(profdir)-1) error(Enonexist); /* was return -1; */ tab = &profdir[s]; path = PATH(c->qid); acquire(); r = getrec(PID(c->qid)); if(r == nil) { release(); error(Enonexist); /* was return -1; */ } perm = tab->perm; len = tab->length; mkqid(&qid, path|tab->qid.path, c->qid.vers, QTFILE); devdir(c, qid, tab->name, len, eve, perm, dp); release(); return 1;} static Chan*profattach(char *spec){ return devattach('P', spec);} static Walkqid*profwalk(Chan *c, Chan *nc, char **name, int nname){ return devwalk(c, nc, name, nname, 0, 0, profgen);} static intprofstat(Chan *c, uchar *db, int n){ return devstat(c, db, n, 0, 0, profgen);} static Chan*profopen(Chan *c, int omode){ int qid; Record *r; if(c->qid.type & QTDIR) { if(omode != OREAD) error(Eisdir); c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; } if(omode&OTRUNC) error(Eperm); qid = QID(c->qid); if(qid == Qctl || qid == Qpctl){ if (omode != OWRITE) error(Eperm); } else{ if(omode != OREAD) error(Eperm); } if(qid != Qctl){ acquire(); r = getrec(PID(c->qid)); release(); if(r == nil) error(Ethread); } c->offset = 0; c->flag |= COPEN; c->mode = openmode(omode); if(QID(c->qid) == Qhist) c->aux = nil; return c;} static intprofwstat(Chan *c, uchar *dp, int n){ Dir d; Record *r; if(strcmp(up->env->user, eve)) error(Eperm); if(c->qid.type & QTDIR) error(Eperm); acquire(); r = getrec(PID(c->qid)); release(); if(r == nil) error(Ethread); n = convM2D(dp, n, &d, nil); if(n == 0) error(Eshortstat); d.mode &= 0777; /* TO DO: copy to c->aux->perm, once that exists */ return n;} static voidprofclose(Chan *c){ USED(c);} static longprofread(Chan *c, void *va, long n, vlong offset){ int i; Record *r; char *a = va; if(c->qid.type & QTDIR) return devdirread(c, a, n, 0, 0, profgen); acquire(); r = getrec(PID(c->qid)); release(); if(r == nil) error(Ethread); switch(QID(c->qid)){ case Qname: return readstr(offset, va, n, r->name); case Qpath: return readstr(offset, va, n, r->path); case Qhist: i = (int)c->aux; while(i < r->size && r->bucket[i] == 0) i++; if(i >= r->size) return 0; c->aux = (void*)(i+1); if(n < 20) error(Etoosmall); return sprint(a, "%d %lud", i, r->bucket[i]); case Qctl: error(Eperm); } return 0;} static longprofwrite(Chan *c, void *va, long n, vlong offset){ int i; char *a = va; char buf[128], *fields[128]; void (*f)(int, ulong, ulong, ulong); USED(va); USED(n); USED(offset); if(c->qid.type & QTDIR) error(Eisdir); switch(QID(c->qid)){ case Qctl: if(n > sizeof(buf)-1) n = sizeof(buf)-1; memmove(buf, a, n); buf[n] = 0; i = getfields(buf, fields, nelem(fields), 1, " \t\n"); if(i > 0 && strcmp(fields[0], "module") == 0){ f = memmonitor; memmonitor = nil; freepmods(); while(--i > 0) addpmod(fields[i]); memmonitor = f; return n; } if(i == 1){ if(strcmp(fields[0], "start") == 0){ if(profiler == Pnil) { profiler = Psam; if(!samplefn){ samplefn = 1; kproc("prof", sampler, 0, 0); } } } else if(strncmp(fields[0], "startmp", 7) == 0){ if(profiler == Pnil){ profiler = Pmem; for(a = &fields[0][7]; *a != '\0'; a++){ if(*a == '1'){ memmonitor = memprofmi; mprofiler |= Mmain; } else if(*a == '2'){ heapmonitor = memprof; mprofiler |= Mheap; } else if(*a == '3'){ memmonitor = memprofmi; mprofiler |= Mimage; } }; } } else if(strcmp(fields[0], "stop") == 0){ profiler = Pnil; mprofiler = Mnone; } else if(strcmp(fields[0], "end") == 0){ profiler = Pnil; mprofiler = Mnone; memmonitor = nil; freeprof(); interval = 100; } else error(Ebadarg); } else if (i == 2){ if(strcmp(fields[0], "interval") == 0) interval = strtoul(fields[1], nil, 0); else if(strcmp(fields[0], "startcp") == 0){ Prog *p; acquire(); p = progpid(strtoul(fields[1], nil, 0)); if(p == nil){ release(); return -1; } if(profiler == Pnil){ profiler = Pcov; p->xec = cpxec; } release(); } else error(Ebadarg); } else error(Ebadarg); return n; default: error(Eperm); } return 0;} static Record*newmodule(Module *m, int vm, int scale, int origin){ int dsize; Record *r, **l; if(!vm) acquire(); if((m->compiled && m->pctab == nil) || m->prog == nil) { if(!vm) release(); return nil; } if(m->compiled) dsize = m->nprog * sizeof(r->bucket[0]); else dsize = (msize(m->prog)/sizeof(Inst)) * sizeof(r->bucket[0]); dsize *= scale; dsize += origin; r = malloc(sizeof(Record)+dsize); if(r == nil) { if(!vm) release(); return nil; } r->id = ++ids; if(ids == (1<<8)-1) ids = 0; kstrdup(&r->name, m->name); kstrdup(&r->path, m->path);Lines 1–500 of 817. Load more
#include "dat.h" #include "fns.h" #include "error.h" #include "interp.h" #include <isa.h> #include "runt.h" extern Pool* imagmem; extern void (*memmonitor)(int, ulong, ulong, ulong); static void cpxec(Prog *); static void memprof(int, void*, ulong); static void memprofmi(int, ulong, ulong, ulong); extern Inst* pc2dispc(Inst*, Module*); static int interval = 100; /* Sampling interval in milliseconds */ enum { HSIZE = 32, }; #define HASH(m) ((m)%HSIZE) /* cope with multiple profilers some day */ typedef struct Record Record; struct Record { int id; char* name; char* path; Inst* base; int size; /*Module* m; */ ulong mtime; Qid qid; Record* hash; Record* link; ulong bucket[1]; }; struct { Lock l; vlong time; Record* hash[HSIZE]; Record* list; } profile; typedef struct Pmod Pmod; struct Pmod { char* name; Pmod* link; } *pmods; #define QSHIFT 4 #define QID(q) ((ulong)(q).path&0xf) #define QPID(pid) ((pid)<<QSHIFT) #define PID(q) ((q).vers) #define PATH(q) ((ulong)(q).path&~((1<<QSHIFT)-1)) enum { Qdir, Qname, Qpath, Qhist, Qpctl, Qctl, }; Dirtab profdir[] = { ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555, "name", {Qname}, 0, 0444, "path", {Qpath}, 0, 0444, "histogram", {Qhist}, 0, 0444, "pctl", {Qpctl}, 0, 0222, "ctl", {Qctl}, 0, 0222, }; enum{ Pnil, /* null profiler */ Psam, /* sampling profiler */ Pcov, /* coverage profiler */ Pmem, /* heap memory profiler */ }; enum{ Mnone = 0, Mmain = 1, Mheap = 2, Mimage = 4, }; static int profiler = Pnil; static int mprofiler = Mnone; static int ids; static int samplefn; static void sampler(void*); static Record* getrec(int id) { Record *r; for(r = profile.list; r != nil; r = r->link) if(r->id == id) break; return r; } static void addpmod(char *m) { Pmod *p = malloc(sizeof(Pmod)); if(p == nil) return; p->name = malloc(strlen(m)+1); if(p->name == nil){ free(p); return; } strcpy(p->name, m); p->link = pmods; pmods = p; } static void freepmods(void) { Pmod *p, *np; for(p = pmods; p != nil; p = np){ free(p->name); np = p->link; free(p); } pmods = nil; } static int inpmods(char *m) { Pmod *p; for(p = pmods; p != nil; p = p->link) if(strcmp(p->name, m) == 0) return 1; return 0; } static void freeprof(void) { int i; Record *r, *nr; ids = 0; profiler = Pnil; mprofiler = Mnone; freepmods(); for(r = profile.list; r != nil; r = nr){ free(r->name); free(r->path); nr = r->link; free(r); } profile.list = nil; profile.time = 0; for(i = 0; i < HSIZE; i++) profile.hash[i] = nil; } static int profgen(Chan *c, char *name, Dirtab *d, int nd, int s, Dir *dp) { Qid qid; Record *r; ulong path, perm, len; Dirtab *tab; USED(name); USED(d); USED(nd); if(s == DEVDOTDOT) { mkqid(&qid, Qdir, 0, QTDIR); devdir(c, qid, "#P", 0, eve, 0555, dp); return 1; } if(c->qid.path == Qdir && c->qid.type & QTDIR) { acquire(); if(s-- == 0){ tab = &profdir[Qctl]; mkqid(&qid, PATH(c->qid)|tab->qid.path, c->qid.vers, QTFILE); devdir(c, qid, tab->name, tab->length, eve, tab->perm, dp); release(); return 1; } r = profile.list; while(s-- && r != nil) r = r->link; if(r == nil) { release(); return -1; } sprint(up->genbuf, "%.8lux", (ulong)r->id); mkqid(&qid, (r->id<<QSHIFT), r->id, QTDIR); devdir(c, qid, up->genbuf, 0, eve, DMDIR|0555, dp); release(); return 1; } if(s >= nelem(profdir)-1) error(Enonexist); /* was return -1; */ tab = &profdir[s]; path = PATH(c->qid); acquire(); r = getrec(PID(c->qid)); if(r == nil) { release(); error(Enonexist); /* was return -1; */ } perm = tab->perm; len = tab->length; mkqid(&qid, path|tab->qid.path, c->qid.vers, QTFILE); devdir(c, qid, tab->name, len, eve, perm, dp); release(); return 1; } static Chan* profattach(char *spec) { return devattach('P', spec); } static Walkqid* profwalk(Chan *c, Chan *nc, char **name, int nname) { return devwalk(c, nc, name, nname, 0, 0, profgen); } static int profstat(Chan *c, uchar *db, int n) { return devstat(c, db, n, 0, 0, profgen); } static Chan* profopen(Chan *c, int omode) { int qid; Record *r; if(c->qid.type & QTDIR) { if(omode != OREAD) error(Eisdir); c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; } if(omode&OTRUNC) error(Eperm); qid = QID(c->qid); if(qid == Qctl || qid == Qpctl){ if (omode != OWRITE) error(Eperm); } else{ if(omode != OREAD) error(Eperm); } if(qid != Qctl){ acquire(); r = getrec(PID(c->qid)); release(); if(r == nil) error(Ethread); } c->offset = 0; c->flag |= COPEN; c->mode = openmode(omode); if(QID(c->qid) == Qhist) c->aux = nil; return c; } static int profwstat(Chan *c, uchar *dp, int n) { Dir d; Record *r; if(strcmp(up->env->user, eve)) error(Eperm); if(c->qid.type & QTDIR) error(Eperm); acquire(); r = getrec(PID(c->qid)); release(); if(r == nil) error(Ethread); n = convM2D(dp, n, &d, nil); if(n == 0) error(Eshortstat); d.mode &= 0777; /* TO DO: copy to c->aux->perm, once that exists */ return n; } static void profclose(Chan *c) { USED(c); } static long profread(Chan *c, void *va, long n, vlong offset) { int i; Record *r; char *a = va; if(c->qid.type & QTDIR) return devdirread(c, a, n, 0, 0, profgen); acquire(); r = getrec(PID(c->qid)); release(); if(r == nil) error(Ethread); switch(QID(c->qid)){ case Qname: return readstr(offset, va, n, r->name); case Qpath: return readstr(offset, va, n, r->path); case Qhist: i = (int)c->aux; while(i < r->size && r->bucket[i] == 0) i++; if(i >= r->size) return 0; c->aux = (void*)(i+1); if(n < 20) error(Etoosmall); return sprint(a, "%d %lud", i, r->bucket[i]); case Qctl: error(Eperm); } return 0; } static long profwrite(Chan *c, void *va, long n, vlong offset) { int i; char *a = va; char buf[128], *fields[128]; void (*f)(int, ulong, ulong, ulong); USED(va); USED(n); USED(offset); if(c->qid.type & QTDIR) error(Eisdir); switch(QID(c->qid)){ case Qctl: if(n > sizeof(buf)-1) n = sizeof(buf)-1; memmove(buf, a, n); buf[n] = 0; i = getfields(buf, fields, nelem(fields), 1, " \t\n"); if(i > 0 && strcmp(fields[0], "module") == 0){ f = memmonitor; memmonitor = nil; freepmods(); while(--i > 0) addpmod(fields[i]); memmonitor = f; return n; } if(i == 1){ if(strcmp(fields[0], "start") == 0){ if(profiler == Pnil) { profiler = Psam; if(!samplefn){ samplefn = 1; kproc("prof", sampler, 0, 0); } } } else if(strncmp(fields[0], "startmp", 7) == 0){ if(profiler == Pnil){ profiler = Pmem; for(a = &fields[0][7]; *a != '\0'; a++){ if(*a == '1'){ memmonitor = memprofmi; mprofiler |= Mmain; } else if(*a == '2'){ heapmonitor = memprof; mprofiler |= Mheap; } else if(*a == '3'){ memmonitor = memprofmi; mprofiler |= Mimage; } }; } } else if(strcmp(fields[0], "stop") == 0){ profiler = Pnil; mprofiler = Mnone; } else if(strcmp(fields[0], "end") == 0){ profiler = Pnil; mprofiler = Mnone; memmonitor = nil; freeprof(); interval = 100; } else error(Ebadarg); } else if (i == 2){ if(strcmp(fields[0], "interval") == 0) interval = strtoul(fields[1], nil, 0); else if(strcmp(fields[0], "startcp") == 0){ Prog *p; acquire(); p = progpid(strtoul(fields[1], nil, 0)); if(p == nil){ release(); return -1; } if(profiler == Pnil){ profiler = Pcov; p->xec = cpxec; } release(); } else error(Ebadarg); } else error(Ebadarg); return n; default: error(Eperm); } return 0; } static Record* newmodule(Module *m, int vm, int scale, int origin) { int dsize; Record *r, **l; if(!vm) acquire(); if((m->compiled && m->pctab == nil) || m->prog == nil) { if(!vm) release(); return nil; } if(m->compiled) dsize = m->nprog * sizeof(r->bucket[0]); else dsize = (msize(m->prog)/sizeof(Inst)) * sizeof(r->bucket[0]); dsize *= scale; dsize += origin; r = malloc(sizeof(Record)+dsize); if(r == nil) { if(!vm) release(); return nil; } r->id = ++ids; if(ids == (1<<8)-1) ids = 0; kstrdup(&r->name, m->name); kstrdup(&r->path, m->path);