Some hacking on the sampling profiler

上级 fbecbf0c
......@@ -102,7 +102,8 @@ UPROGS= \
_dirbench \
_usertests \
_lockstat \
_preadtest
_preadtest \
_perf
UPROGS := $(addprefix $(O)/, $(UPROGS))
all: $(O)/kernel
......@@ -155,6 +156,9 @@ $(O)/_%: $(O)/_%.unstripped
$(O)/mkfs: mkfs.c fs.h
gcc -m32 -Werror -Wall -o $@ mkfs.c
$(O)/print-perf: print-perf.c sampler.h
gcc -m32 -Werror -Wall -o $@ print-perf.c
$(O)/fs.img: $(O)/mkfs README $(UPROGS)
@echo " MKFS $@"
$(Q)$(O)/mkfs $@ README $(UPROGS)
......
#include "types.h"
#include "stat.h"
#include "user.h"
#include "fcntl.h"
#include "sampler.h"
static u64 selector =
0UL << 32 |
1 << 24 |
1 << 22 |
1 << 20 |
1 << 17 |
1 << 16 |
0x00 << 8 |
0x76;
static u64 period = 100000;
static void
conf(int fd, sampop_t op)
{
struct sampconf c = {
op: op,
selector: selector,
period: period,
};
if (write(fd, &c, sizeof(c)) != sizeof(c))
die("perf: write failed");
close(fd);
}
static void
save(void)
{
static char buf[4096];
int fd, sfd;
int r;
fd = open("/dev/sampler", O_RDONLY);
if (fd < 0)
die("perf: open failed");
unlink("perf.data");
sfd = open("perf.data", O_RDWR|O_CREATE);
if (sfd < 0)
die("perf: open failed");
while (1) {
r = read(fd, buf, sizeof(buf));
if (r < 0)
die("perf: read failed");
if (r == 0)
break;
if (write(sfd, buf, r) != r)
die("perf: truncated write");
}
close(sfd);
close(fd);
}
int
main(int ac, const char *av[])
{
int fd = open("/dev/sampler", O_RDWR);
if (fd < 0)
die("perf: open failed");
int pid = fork(0);
if (pid < 0)
die("perf: fork failed");
if (pid == 0) {
conf(fd, SAMP_ENABLE);
exec(av[1], av+1);
die("perf: exec failed");
}
wait();
conf(fd, SAMP_DISABLE);
save();
exit();
}
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include "types.h"
#include "sampler.h"
int
main(int ac, char **av)
{
static const char *pathname = "perf.data";
struct logheader *header;
struct stat buf;
void *x;
int fd;
int i;
if (ac > 1)
pathname = av[1];
fd = open(pathname, O_RDONLY);
if (fd < 0) {
perror("open");
exit(EXIT_FAILURE);
}
if (fstat(fd, &buf) < 0) {
perror("fstat");
exit(EXIT_FAILURE);
}
x = mmap(0, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (x == MAP_FAILED) {
perror("mmap");
exit(EXIT_FAILURE);
}
header = x;
printf("ncpus %u\n", header->ncpus);
for (i = 0; i < header->ncpus; i++) {
printf(" offset %lu size %lu\n",
header->cpu[i].offset, header->cpu[i].size);
}
return 0;
}
......@@ -15,17 +15,8 @@ extern "C" {
#include "sampler.h"
}
static const u64 debug_sel =
0UL << 32 |
1 << 24 |
1 << 22 |
1 << 20 |
1 << 17 |
1 << 16 |
0x00 << 8 |
0x76;
static const u64 debug_cnt = 100000;
static volatile u64 selector;
static volatile u64 period;
struct pmu {
void (*config)(u64 ctr, u64 sel, u64 val);
......@@ -84,20 +75,21 @@ void
sampconf(void)
{
pushcli();
pmu.config(0, debug_sel, -debug_cnt);
pmu.config(0, selector, -period);
popcli();
}
void
sampstart(void)
{
pushcli();
for(struct cpu *c = cpus; c < cpus+ncpu; c++) {
if(c == cpus+cpunum())
continue;
lapic_sampconf(c->id);
}
sampconf();
popcli();
}
static int
......@@ -129,7 +121,7 @@ sampintr(struct trapframe *tf)
return 0;
if (samplog(tf))
pmu.config(0, debug_sel, -debug_cnt);
pmu.config(0, selector, -period);
return 1;
}
......@@ -205,6 +197,35 @@ sampread(struct inode *ip, char *dst, u32 off, u32 n)
return ret;
}
static int
sampwrite(struct inode *ip, char *buf, u32 off, u32 n)
{
struct sampconf *conf;
if (n != sizeof(*conf))
return -1;
conf = (struct sampconf*)buf;
switch(conf->op) {
case SAMP_ENABLE:
selector = conf->selector;
period = conf->period;
cprintf("sampwrite: selector %lu period %lu\n",
selector, period);
sampstart();
break;
case SAMP_DISABLE:
selector = 0;
period = 0;
for (int i = 0; i < NCPU; i++)
cprintf("sampwrite: count %lu\n", pmulog[i].count);
sampstart();
break;
}
return n;
}
void
initsamp(void)
{
......@@ -234,6 +255,6 @@ initsamp(void)
pmulog[cpunum()].event = (pmuevent*) p;
pmulog[cpunum()].capacity = PERFSIZE / sizeof(struct pmuevent);
devsw[SAMPLER].write = 0;
devsw[SAMPLER].write = sampwrite;
devsw[SAMPLER].read = sampread;
}
typedef enum { SAMP_ENABLE, SAMP_DISABLE } sampop_t;
struct sampconf {
sampop_t op;
u64 selector;
u64 period;
};
struct pmuevent {
u64 rip;
};
......
......@@ -114,7 +114,7 @@ static struct spinlock lockstat_lock = {
void
lockstat_init(struct spinlock *lk)
{
lk->stat = (struct klockstat*) kmalloc(sizeof(*lk->stat));
lk->stat = (struct klockstat*) kmalloc(sizeof(*lk->stat));
if (lk->stat == NULL)
return;
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论