📄 trace.c
字号:
#include <u.h>#include <tos.h>#include <libc.h>#include <thread.h>#include <ip.h>#include <bio.h>#include <draw.h>#include <mouse.h>#include <cursor.h>#include <keyboard.h>#include "trace.h"#pragma varargck type "t" vlong#pragma varargck type "U" uvlong#define NS(x) ((vlong)x)#define US(x) (NS(x) * 1000ULL)#define MS(x) (US(x) * 1000ULL)#define S(x) (MS(x) * 1000ULL)#define numblocks(a, b) (((a) + (b) - 1) / (b))#define roundup(a, b) (numblocks((a), (b)) * (b))enum { OneRound = MS(1)/2LL, MilliRound = US(1)/2LL,};typedef struct Event Event;typedef struct Task Task;struct Event { Traceevent; vlong etime; /* length of block to draw */};struct Task { int pid; char *name; int nevents; Event *events; vlong tstart; vlong total; vlong runtime; vlong runmax; vlong runthis; long runs; ulong tevents[Nevent];};enum { Nevents = 1024, Ncolor = 6, K = 1024,};vlong now, prevts;int newwin;int Width = 1000; int Height = 100; // Per taskint topmargin = 8;int bottommargin = 4;int lineht = 12;int wctlfd;int nevents;Traceevent *eventbuf;Event *event;void drawtrace(void);int schedparse(char*, char*, char*);int timeconv(Fmt*);char *schedstatename[] = { [SAdmit] = "Admit", [SSleep] = "Sleep", [SDead] = "Dead", [SDeadline] = "Deadline", [SEdf] = "Edf", [SExpel] = "Expel", [SReady] = "Ready", [SRelease] = "Release", [SRun] = "Run", [SSlice] = "Slice", [SInts] = "Ints", [SInte] = "Inte", [SUser] = "User", [SYield] = "Yield",};struct { vlong scale; vlong bigtics; vlong littletics; int sleep;} scales[] = { { US(500), US(100), US(50), 0}, { US(1000), US(500), US(100), 0}, { US(2000), US(1000), US(200), 0}, { US(5000), US(1000), US(500), 0}, { MS(10), MS(5), MS(1), 20}, { MS(20), MS(10), MS(2), 20}, { MS(50), MS(10), MS(5), 20}, { MS(100), MS(50), MS(10), 20}, /* starting scaleno */ { MS(200), MS(100), MS(20), 20}, { MS(500), MS(100), MS(50), 50}, { MS(1000), MS(500), MS(100), 100}, { MS(2000), MS(1000), MS(200), 100}, { MS(5000), MS(1000), MS(500), 100}, { S(10), S(50), S(1), 100}, { S(20), S(10), S(2), 100}, { S(50), S(10), S(5), 100}, { S(100), S(50), S(10), 100}, { S(200), S(100), S(20), 100}, { S(500), S(100), S(50), 100}, { S(1000), S(500), S(100), 100},};int ntasks, verbose, triggerproc, paused;Task *tasks;Image *cols[Ncolor][4];Font *mediumfont, *tinyfont;Image *grey, *red, *green, *blue, *bg, *fg;char*profdev = "/proc/trace";static voidusage(void){ fprint(2, "Usage: %s [-d profdev] [-w] [-v] [-t triggerproc] [processes]\n", argv0); exits(nil);}voidthreadmain(int argc, char **argv){ int fd, i; char fname[80]; fmtinstall('t', timeconv); ARGBEGIN { case 'd': profdev = EARGF(usage()); break; case 'v': verbose = 1; break; case 'w': newwin++; break; case 't': triggerproc = (int)strtol(EARGF(usage()), nil, 0); break; default: usage(); } ARGEND; fname[sizeof fname - 1] = 0; for(i = 0; i < argc; i++){ snprint(fname, sizeof fname - 2, "/proc/%s/ctl", argv[i]); if((fd = open(fname, OWRITE)) < 0){ fprint(2, "%s: cannot open %s: %r\n", argv[0], fname); continue; } if(fprint(fd, "trace 1") < 0) fprint(2, "%s: cannot enable tracing on %s: %r\n", argv[0], fname); close(fd); } drawtrace();}static voidmkcol(int i, int c0, int c1, int c2){ cols[i][0] = allocimagemix(display, c0, DWhite); cols[i][1] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, c1); cols[i][2] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, c2); cols[i][3] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, c0);}static voidcolinit(void){ mediumfont = openfont(display, "/lib/font/bit/lucidasans/unicode.10.font"); if(mediumfont == nil) mediumfont = font; tinyfont = openfont(display, "/lib/font/bit/lucidasans/unicode.7.font"); if(tinyfont == nil) tinyfont = font; topmargin = mediumfont->height+2; bottommargin = tinyfont->height+2; /* Peach */ mkcol(0, 0xFFAAAAFF, 0xFFAAAAFF, 0xBB5D5DFF); /* Aqua */ mkcol(1, DPalebluegreen, DPalegreygreen, DPurpleblue); /* Yellow */ mkcol(2, DPaleyellow, DDarkyellow, DYellowgreen); /* Green */ mkcol(3, DPalegreen, DMedgreen, DDarkgreen); /* Blue */ mkcol(4, 0x00AAFFFF, 0x00AAFFFF, 0x0088CCFF); /* Grey */ cols[5][0] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0xEEEEEEFF); cols[5][1] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0xCCCCCCFF); cols[5][2] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x888888FF); cols[5][3] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0xAAAAAAFF); grey = cols[5][2]; red = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0xFF0000FF); green = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x00FF00FF); blue = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x0000FFFF); bg = display->white; fg = display->black;}static voidredraw(int scaleno){ int n, i, j, x; char buf[256]; Point p, q; Rectangle r, rtime; Task *t; vlong ts, oldestts, newestts, period, ppp, scale, s, ss;# define time2x(t) ((int)(((t) - oldestts) / ppp)) scale = scales[scaleno].scale; period = scale + scales[scaleno].littletics; ppp = period / Width; // period per pixel. /* Round `now' to a nice number */ newestts = now - (now % scales[scaleno].bigtics) + (scales[scaleno].littletics>>1); oldestts = newestts - period;//print("newestts %t, period %t, %d-%d\n", newestts, period, time2x(oldestts), time2x(newestts)); if (prevts < oldestts){ oldestts = newestts - period; prevts = oldestts; draw(screen, screen->r, bg, nil, ZP); }else{ /* just white out time */ rtime = screen->r; rtime.min.x = rtime.max.x - stringwidth(mediumfont, "00000000000.000s"); rtime.max.y = rtime.min.y + mediumfont->height; draw(screen, rtime, bg, nil, ZP); } p = screen->r.min; for (n = 0; n != ntasks; n++) { t = &tasks[n]; /* p is upper left corner for this task */ rtime = Rpt(p, addpt(p, Pt(500, mediumfont->height))); draw(screen, rtime, bg, nil, ZP); snprint(buf, sizeof(buf), "%d %s", t->pid, t->name); q = string(screen, p, fg, ZP, mediumfont, buf); s = now - t->tstart; if(t->tevents[SRelease]) snprint(buf, sizeof(buf), " per %t — avg: %t max: %t", (vlong)(s/t->tevents[SRelease]), (vlong)(t->runtime/t->tevents[SRelease]), t->runmax); else if((s /=1000000000LL) != 0) snprint(buf, sizeof(buf), " per 1s — avg: %t total: %t", t->total/s, t->total); else snprint(buf, sizeof(buf), " total: %t", t->total); string(screen, q, fg, ZP, tinyfont, buf); p.y += Height; } x = time2x(prevts); p = screen->r.min; for (n = 0; n != ntasks; n++) { t = &tasks[n]; /* p is upper left corner for this task */ /* Move part already drawn */ r = Rect(p.x, p.y + topmargin, p.x + x, p.y+Height); draw(screen, r, screen, nil, Pt(p.x + Width - x, p.y + topmargin)); r.max.x = screen->r.max.x; r.min.x += x; draw(screen, r, bg, nil, ZP); line(screen, addpt(p, Pt(x, Height - lineht)), Pt(screen->r.max.x, p.y + Height - lineht), Endsquare, Endsquare, 0, cols[n % Ncolor][1], ZP); for (i = 0; i < t->nevents-1; i++) if (prevts < t->events[i + 1].time) break; if (i > 0) { memmove(t->events, t->events + i, (t->nevents - i) * sizeof(Event)); t->nevents -= i; } for (i = 0; i != t->nevents; i++) { Event *e = &t->events[i], *_e; int sx, ex; switch (e->etype & 0xffff) { case SAdmit: if (e->time > prevts && e->time <= newestts) { sx = time2x(e->time); line(screen, addpt(p, Pt(sx, topmargin)), addpt(p, Pt(sx, Height - bottommargin)), Endarrow, Endsquare, 1, green, ZP); } break; case SExpel: if (e->time > prevts && e->time <= newestts) { sx = time2x(e->time); line(screen, addpt(p, Pt(sx, topmargin)), addpt(p, Pt(sx, Height - bottommargin)), Endsquare, Endarrow, 1, red, ZP); } break; case SRelease: if (e->time > prevts && e->time <= newestts) { sx = time2x(e->time); line(screen, addpt(p, Pt(sx, topmargin)), addpt(p, Pt(sx, Height - bottommargin)), Endarrow, Endsquare, 1, fg, ZP); } break; case SDeadline: if (e->time > prevts && e->time <= newestts) { sx = time2x(e->time); line(screen, addpt(p, Pt(sx, topmargin)), addpt(p, Pt(sx, Height - bottommargin)), Endsquare, Endarrow, 1, fg, ZP); } break; case SYield: case SUser: if (e->time > prevts && e->time <= newestts) { sx = time2x(e->time); line(screen, addpt(p, Pt(sx, topmargin)), addpt(p, Pt(sx, Height - bottommargin)), Endsquare, Endarrow, 0, (e->etype == SYield)? green: blue, ZP); } break; case SSlice: if (e->time > prevts && e->time <= newestts) { sx = time2x(e->time); line(screen, addpt(p, Pt(sx, topmargin)), addpt(p, Pt(sx, Height - bottommargin)), Endsquare, Endarrow, 0, red, ZP); } break; case SRun: case SEdf: sx = time2x(e->time); ex = time2x(e->etime); if(ex == sx) ex++; r = Rect(sx, topmargin + 8, ex, Height - lineht); r = rectaddpt(r, p); draw(screen, r, cols[n % Ncolor][e->etype==SRun?1:3], nil, ZP); if(t->pid == triggerproc && ex < Width) paused ^= 1; for(j = 0; j < t->nevents; j++){ _e = &t->events[j]; switch(_e->etype & 0xffff){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -