提交 05659653 创建 作者: Frans Kaashoek's avatar Frans Kaashoek

Merge commit 'origin/mtrace' into scale

Conflicts: kalloc.c proc.c spinlock.c
...@@ -14,3 +14,6 @@ initcode.out ...@@ -14,3 +14,6 @@ initcode.out
kernel kernel
mkfs mkfs
.gdbinit .gdbinit
mtrace.out
mscan.syms
mscan.kern
...@@ -50,8 +50,16 @@ TOOLPREFIX := $(shell if i386-jos-elf-objdump -i 2>&1 | grep '^elf32-i386$$' >/d ...@@ -50,8 +50,16 @@ TOOLPREFIX := $(shell if i386-jos-elf-objdump -i 2>&1 | grep '^elf32-i386$$' >/d
echo "***" 1>&2; exit 1; fi) echo "***" 1>&2; exit 1; fi)
endif endif
# The i386 ('qemu') mtrace doesn't work, but 'qemu-system-x86_64' mtrace works.
MTRACE = qemu-system-x86_64
QEMUSRC ?=
ifeq ($(QEMUSRC),)
$(error You need to set QEMUSRC (e.g. make QEMUSRC=~/qemu))
endif
# If the makefile can't find QEMU, specify its path here # If the makefile can't find QEMU, specify its path here
#QEMU = #QEMU =
# Try to infer the correct QEMU # Try to infer the correct QEMU
ifndef QEMU ifndef QEMU
...@@ -72,7 +80,7 @@ AS = $(TOOLPREFIX)gas ...@@ -72,7 +80,7 @@ AS = $(TOOLPREFIX)gas
LD = $(TOOLPREFIX)ld LD = $(TOOLPREFIX)ld
OBJCOPY = $(TOOLPREFIX)objcopy OBJCOPY = $(TOOLPREFIX)objcopy
OBJDUMP = $(TOOLPREFIX)objdump OBJDUMP = $(TOOLPREFIX)objdump
CFLAGS = -fno-pic -static -fno-builtin -fno-strict-aliasing -O2 -Wall -MD -ggdb -m32 -Werror CFLAGS = -fno-pic -static -fno-builtin -fno-strict-aliasing -O2 -Wall -MD -ggdb -m32 -Werror -I$(QEMUSRC)
CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector) CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector)
ASFLAGS = -m32 -gdwarf-2 ASFLAGS = -m32 -gdwarf-2
# FreeBSD ld wants ``elf_i386_fbsd'' # FreeBSD ld wants ``elf_i386_fbsd''
...@@ -163,6 +171,7 @@ UPROGS=\ ...@@ -163,6 +171,7 @@ UPROGS=\
_usertests\ _usertests\
_wc\ _wc\
_zombie\ _zombie\
_halt\
fs.img: mkfs README $(UPROGS) fs.img: mkfs README $(UPROGS)
./mkfs fs.img README $(UPROGS) ./mkfs fs.img README $(UPROGS)
...@@ -191,6 +200,12 @@ bochs : fs.img xv6.img ...@@ -191,6 +200,12 @@ bochs : fs.img xv6.img
if [ ! -e .bochsrc ]; then ln -s dot-bochsrc .bochsrc; fi if [ ! -e .bochsrc ]; then ln -s dot-bochsrc .bochsrc; fi
bochs -q bochs -q
mscan.syms: kernel
nm -S $< > $@
mscan.kern: kernel
cp $< $@
# try to generate a unique GDB port # try to generate a unique GDB port
GDBPORT = $(shell expr `id -u` % 5000 + 25000) GDBPORT = $(shell expr `id -u` % 5000 + 25000)
# QEMU's gdb stub command line changed in 0.11 # QEMU's gdb stub command line changed in 0.11
...@@ -201,6 +216,7 @@ ifndef CPUS ...@@ -201,6 +216,7 @@ ifndef CPUS
CPUS := 2 CPUS := 2
endif endif
QEMUOPTS = -hdb fs.img xv6.img -smp $(CPUS) QEMUOPTS = -hdb fs.img xv6.img -smp $(CPUS)
MTRACEOPTS = -mtrace-enable -mtrace-file mtrace.out -mtrace-quantum 10000
qemu: fs.img xv6.img qemu: fs.img xv6.img
$(QEMU) -serial mon:stdio $(QEMUOPTS) $(QEMU) -serial mon:stdio $(QEMUOPTS)
...@@ -211,6 +227,9 @@ qemu-memfs: xv6memfs.img ...@@ -211,6 +227,9 @@ qemu-memfs: xv6memfs.img
qemu-nox: fs.img xv6.img qemu-nox: fs.img xv6.img
$(QEMU) -nographic $(QEMUOPTS) $(QEMU) -nographic $(QEMUOPTS)
mtrace-nox: fs.img xv6.img mscan.syms mscan.kern
$(MTRACE) -nographic $(QEMUOPTS) $(MTRACEOPTS)
.gdbinit: .gdbinit.tmpl .gdbinit: .gdbinit.tmpl
sed "s/localhost:1234/localhost:$(GDBPORT)/" < $^ > $@ sed "s/localhost:1234/localhost:$(GDBPORT)/" < $^ > $@
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "types.h" #include "types.h"
#include "stat.h" #include "stat.h"
#include "user.h" #include "user.h"
#include "xv6-mtrace.h"
#define N 1000 #define N 1000
...@@ -13,13 +14,31 @@ printf(int fd, char *s, ...) ...@@ -13,13 +14,31 @@ printf(int fd, char *s, ...)
write(fd, s, strlen(s)); write(fd, s, strlen(s));
} }
char*
strncpy(char *s, const char *t, int n)
{
int tlen = strlen((char *)t);
memmove(s, (char *)t, n > tlen ? tlen : n);
if (n > tlen)
s[tlen] = 0;
return s;
}
void*
memcpy(void *dst, const void *src, uint n)
{
return memmove(dst, (void *)src, n);
}
void void
forktest(void) forktest(void)
{ {
struct mtrace_appdata_entry entry;
int n, pid; int n, pid;
printf(1, "fork test\n"); printf(1, "fork test\n");
mtrace_enable_set(1, "xv6-forktest");
for(n=0; n<N; n++){ for(n=0; n<N; n++){
pid = fork(); pid = fork();
if(pid < 0) if(pid < 0)
...@@ -44,8 +63,13 @@ forktest(void) ...@@ -44,8 +63,13 @@ forktest(void)
printf(1, "wait got too many\n"); printf(1, "wait got too many\n");
exit(); exit();
} }
entry.u64 = n;
mtrace_appdata_register(&entry);
mtrace_enable_set(0, "xv6-forktest");
printf(1, "fork test OK\n"); printf(1, "fork test OK\n");
halt();
} }
int int
......
#include "types.h"
#include "user.h"
int
main(int argc, char *argv[])
{
halt();
exit();
}
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "queue.h" #include "queue.h"
#include "proc.h" #include "proc.h"
#include "kalloc.h" #include "kalloc.h"
#include "xv6-mtrace.h"
struct kmem kmems[NCPU]; struct kmem kmems[NCPU];
...@@ -58,9 +59,7 @@ kfree(char *v) ...@@ -58,9 +59,7 @@ kfree(char *v)
{ {
struct run *r; struct run *r;
// cprintf("%d: free 0x%x\n", cpu->id, v); if((uint)v % PGSIZE || v < end || (uint)v >= PHYSTOP)
if((uint)v % PGSIZE || v < end || (uint)v >= PHYSTOP)
panic("kfree"); panic("kfree");
// Fill with junk to catch dangling refs. // Fill with junk to catch dangling refs.
...@@ -70,6 +69,13 @@ kfree(char *v) ...@@ -70,6 +69,13 @@ kfree(char *v)
r = (struct run*)v; r = (struct run*)v;
r->next = kmem->freelist; r->next = kmem->freelist;
kmem->freelist = r; kmem->freelist = r;
mtrace_label_register(mtrace_label_block,
r,
0,
0,
0,
RET_EIP());
release(&kmem->lock); release(&kmem->lock);
} }
...@@ -87,6 +93,12 @@ kalloc(void) ...@@ -87,6 +93,12 @@ kalloc(void)
r = kmem->freelist; r = kmem->freelist;
if(r) if(r)
kmem->freelist = r->next; kmem->freelist = r->next;
mtrace_label_register(mtrace_label_block,
r,
4096,
"kalloc",
sizeof("kalloc"),
RET_EIP());
release(&kmem->lock); release(&kmem->lock);
if (r == 0) if (r == 0)
cprintf("%d: kalloc out\n", cpunum()); cprintf("%d: kalloc out\n", cpunum());
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "condvar.h" #include "condvar.h"
#include "queue.h" #include "queue.h"
#include "proc.h" #include "proc.h"
#include "xv6-mtrace.h"
struct ptable ptables[NCPU]; struct ptable ptables[NCPU];
struct runq runqs[NCPU]; struct runq runqs[NCPU];
...@@ -358,6 +359,15 @@ void ...@@ -358,6 +359,15 @@ void
scheduler(void) scheduler(void)
{ {
struct proc *p; struct proc *p;
int pid;
acquire(&ptable.lock);
pid = nextpid++;
release(&ptable.lock);
// Enabling mtrace calls in scheduler generates many mtrace_call_entrys.
// mtrace_call_set(1, cpunum());
mtrace_fcall_register(pid, (unsigned long)scheduler, 0, mtrace_start);
for(;;){ for(;;){
// Enable interrupts on this processor. // Enable interrupts on this processor.
...@@ -380,8 +390,12 @@ scheduler(void) ...@@ -380,8 +390,12 @@ scheduler(void)
proc = p; proc = p;
switchuvm(p); switchuvm(p);
p->state = RUNNING; p->state = RUNNING;
// cprintf("%d: running %d\n", cpu->id, p->pid); mtrace_fcall_register(pid, 0, 0, mtrace_pause);
mtrace_fcall_register(proc->pid, 0, 0, mtrace_resume);
mtrace_call_set(1, cpunum());
swtch(&cpu->scheduler, proc->context); swtch(&cpu->scheduler, proc->context);
mtrace_fcall_register(pid, 0, 0, mtrace_resume);
mtrace_call_set(0, cpunum());
switchkvm(); switchkvm();
// Process is done running for now. // Process is done running for now.
...@@ -413,6 +427,9 @@ sched(void) ...@@ -413,6 +427,9 @@ sched(void)
if(readeflags()&FL_IF) if(readeflags()&FL_IF)
panic("sched interruptible"); panic("sched interruptible");
intena = cpu->intena; intena = cpu->intena;
mtrace_fcall_register(proc->pid, 0, 0, mtrace_pause);
mtrace_call_set(0, cpunum());
swtch(&proc->context, cpu->scheduler); swtch(&proc->context, cpu->scheduler);
cpu->intena = intena; cpu->intena = intena;
} }
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "condvar.h" #include "condvar.h"
#include "queue.h" #include "queue.h"
#include "proc.h" #include "proc.h"
#include "xv6-mtrace.h"
void void
initlock(struct spinlock *lk, char *name) initlock(struct spinlock *lk, char *name)
...@@ -31,12 +32,24 @@ acquire(struct spinlock *lk) ...@@ -31,12 +32,24 @@ acquire(struct spinlock *lk)
panic("acquire"); panic("acquire");
} }
mtrace_lock_register(RET_EIP(),
lk,
lk->name,
mtrace_lockop_acquire,
0);
// The xchg is atomic. // The xchg is atomic.
// It also serializes, so that reads after acquire are not // It also serializes, so that reads after acquire are not
// reordered before it. // reordered before it.
while(xchg(&lk->locked, 1) != 0) while(xchg(&lk->locked, 1) != 0)
; ;
mtrace_lock_register(RET_EIP(),
lk,
lk->name,
mtrace_lockop_acquired,
0);
// Record info about lock acquisition for debugging. // Record info about lock acquisition for debugging.
lk->cpu = cpu; lk->cpu = cpu;
getcallerpcs(&lk, lk->pcs); getcallerpcs(&lk, lk->pcs);
...@@ -51,10 +64,16 @@ release(struct spinlock *lk) ...@@ -51,10 +64,16 @@ release(struct spinlock *lk)
panic("release"); panic("release");
} }
mtrace_lock_register(RET_EIP(),
lk,
lk->name,
mtrace_lockop_release,
0);
lk->pcs[0] = 0; lk->pcs[0] = 0;
lk->cpu = 0; lk->cpu = 0;
// The xchg serializes, so that reads before release are // The xchg serializes, so that reads before release are
// not reordered after it. The 1996 PentiumPro manual (Volume 3, // not reordered after it. The 1996 PentiumPro manual (Volume 3,
// 7.2) says reads can be carried out speculatively and in // 7.2) says reads can be carried out speculatively and in
// any order, which implies we need to serialize here. // any order, which implies we need to serialize here.
...@@ -74,7 +93,7 @@ getcallerpcs(void *v, uint pcs[]) ...@@ -74,7 +93,7 @@ getcallerpcs(void *v, uint pcs[])
{ {
uint *ebp; uint *ebp;
int i; int i;
ebp = (uint*)v - 2; ebp = (uint*)v - 2;
for(i = 0; i < 10; i++){ for(i = 0; i < 10; i++){
if(ebp == 0 || ebp < (uint*)0x100000 || ebp == (uint*)0xffffffff) if(ebp == 0 || ebp < (uint*)0x100000 || ebp == (uint*)0xffffffff)
...@@ -102,7 +121,7 @@ void ...@@ -102,7 +121,7 @@ void
pushcli(void) pushcli(void)
{ {
int eflags; int eflags;
eflags = readeflags(); eflags = readeflags();
cli(); cli();
if(cpu->ncli++ == 0) if(cpu->ncli++ == 0)
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "proc.h" #include "proc.h"
#include "x86.h" #include "x86.h"
#include "syscall.h" #include "syscall.h"
#include "xv6-mtrace.h"
// User code makes a system call with INT T_SYSCALL. // User code makes a system call with INT T_SYSCALL.
// System call number in %eax. // System call number in %eax.
...@@ -100,6 +101,7 @@ extern int sys_unlink(void); ...@@ -100,6 +101,7 @@ extern int sys_unlink(void);
extern int sys_wait(void); extern int sys_wait(void);
extern int sys_write(void); extern int sys_write(void);
extern int sys_uptime(void); extern int sys_uptime(void);
extern int sys_halt(void);
static int (*syscalls[])(void) = { static int (*syscalls[])(void) = {
[SYS_chdir] sys_chdir, [SYS_chdir] sys_chdir,
...@@ -123,17 +125,26 @@ static int (*syscalls[])(void) = { ...@@ -123,17 +125,26 @@ static int (*syscalls[])(void) = {
[SYS_wait] sys_wait, [SYS_wait] sys_wait,
[SYS_write] sys_write, [SYS_write] sys_write,
[SYS_uptime] sys_uptime, [SYS_uptime] sys_uptime,
[SYS_halt] sys_halt,
}; };
void void
syscall(void) syscall(void)
{ {
int num; int num;
num = proc->tf->eax; num = proc->tf->eax;
if(num >= 0 && num < NELEM(syscalls) && syscalls[num]) if(num >= 0 && num < NELEM(syscalls) && syscalls[num]) {
mtrace_fcall_register(proc->pid, (unsigned long)syscalls[num],
0,
mtrace_start);
mtrace_call_set(1, cpunum());
proc->tf->eax = syscalls[num](); proc->tf->eax = syscalls[num]();
else { mtrace_fcall_register(proc->pid, (unsigned long)syscalls[num],
0,
mtrace_done);
mtrace_call_set(0, cpunum());
} else {
cprintf("%d %s: unknown sys call %d\n", cprintf("%d %s: unknown sys call %d\n",
proc->pid, proc->name, num); proc->pid, proc->name, num);
proc->tf->eax = -1; proc->tf->eax = -1;
......
...@@ -20,3 +20,4 @@ ...@@ -20,3 +20,4 @@
#define SYS_sbrk 19 #define SYS_sbrk 19
#define SYS_sleep 20 #define SYS_sleep 20
#define SYS_uptime 21 #define SYS_uptime 21
#define SYS_halt 22
...@@ -90,3 +90,14 @@ sys_uptime(void) ...@@ -90,3 +90,14 @@ sys_uptime(void)
release(&tickslock); release(&tickslock);
return xticks; return xticks;
} }
int
sys_halt(void)
{
int i;
const char s[] = "Shutdown";
for(i = 0; i < 8; i++)
outb(0x8900, s[i]);
return 0;
}
...@@ -22,6 +22,7 @@ int getpid(void); ...@@ -22,6 +22,7 @@ int getpid(void);
char* sbrk(int); char* sbrk(int);
int sleep(int); int sleep(int);
int uptime(void); int uptime(void);
void halt(void);
// ulib.c // ulib.c
int stat(char*, struct stat*); int stat(char*, struct stat*);
......
...@@ -29,3 +29,4 @@ SYSCALL(getpid) ...@@ -29,3 +29,4 @@ SYSCALL(getpid)
SYSCALL(sbrk) SYSCALL(sbrk)
SYSCALL(sleep) SYSCALL(sleep)
SYSCALL(uptime) SYSCALL(uptime)
SYSCALL(halt)
#include <stdint.h>
void* memcpy(void *dst, const void *src, uint n);
char* strncpy(char *s, const char *t, int n);
#define RET_EIP() ((unsigned long)__builtin_return_address(0))
#include "mtrace-magic.h"
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论