replace setjmp/longjmp with swtch
This commit is contained in:
parent
b52dea08bc
commit
818fc0125e
19
Makefile
19
Makefile
|
@ -14,9 +14,9 @@ OBJS = \
|
|||
picirq.o\
|
||||
pipe.o\
|
||||
proc.o\
|
||||
setjmp.o\
|
||||
spinlock.o\
|
||||
string.o\
|
||||
swtch.o\
|
||||
syscall.o\
|
||||
sysfile.o\
|
||||
sysproc.o\
|
||||
|
@ -67,7 +67,7 @@ initcode: initcode.S
|
|||
kernel: $(OBJS) bootother initcode
|
||||
$(LD) -Ttext 0x100000 -e main -o kernel $(OBJS) -b binary initcode bootother
|
||||
$(OBJDUMP) -S kernel > kernel.asm
|
||||
$(OBJDUMP) -t kernel | sed '1,/SYMBOL TABLE/d; s/ .* //' > kernel.sym
|
||||
$(OBJDUMP) -t kernel | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > kernel.sym
|
||||
|
||||
tags: $(OBJS) bootother.S _init
|
||||
etags *.S *.c
|
||||
|
@ -80,7 +80,7 @@ ULIB = ulib.o usys.o printf.o umalloc.o
|
|||
_%: %.o $(ULIB)
|
||||
$(LD) -N -e main -Ttext 0 -o $@ $^
|
||||
$(OBJDUMP) -S $@ > $*.asm
|
||||
$(OBJDUMP) -t $@ | sed '1,/SYMBOL TABLE/d; s/ .* //' > $*.sym
|
||||
$(OBJDUMP) -t $@ | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $*.sym
|
||||
|
||||
_forktest: forktest.o $(ULIB)
|
||||
# forktest has less library code linked in - needs to be small
|
||||
|
@ -119,18 +119,7 @@ clean:
|
|||
$(UPROGS)
|
||||
|
||||
# make a printout
|
||||
PRINT = \
|
||||
runoff.list \
|
||||
README\
|
||||
types.h param.h defs.h x86.h asm.h elf.h mmu.h spinlock.h\
|
||||
bootasm.S bootother.S main.c init.c spinlock.c\
|
||||
proc.h proc.c setjmp.S kalloc.c\
|
||||
syscall.h trapasm.S traps.h trap.c vectors.pl syscall.c sysproc.c\
|
||||
buf.h dev.h fcntl.h stat.h file.h fs.h fsvar.h file.c fs.c bio.c ide.c sysfile.c\
|
||||
pipe.c exec.c\
|
||||
mp.h ioapic.h mp.c lapic.c ioapic.c picirq.c\
|
||||
console.c\
|
||||
string.c\
|
||||
PRINT = runoff.list $(shell grep -v '^\#' runoff.list)
|
||||
|
||||
xv6.pdf: $(PRINT)
|
||||
./runoff
|
||||
|
|
7
defs.h
7
defs.h
|
@ -1,7 +1,7 @@
|
|||
struct buf;
|
||||
struct context;
|
||||
struct file;
|
||||
struct inode;
|
||||
struct jmpbuf;
|
||||
struct pipe;
|
||||
struct proc;
|
||||
struct spinlock;
|
||||
|
@ -109,9 +109,8 @@ void userinit(void);
|
|||
void wakeup(void*);
|
||||
void yield(void);
|
||||
|
||||
// setjmp.S
|
||||
void longjmp(struct jmpbuf*);
|
||||
int setjmp(struct jmpbuf*);
|
||||
// swtch.S
|
||||
void swtch(struct context*, struct context*);
|
||||
|
||||
// spinlock.c
|
||||
void acquire(struct spinlock*);
|
||||
|
|
16
proc.c
16
proc.c
|
@ -134,10 +134,10 @@ copyproc(struct proc *p)
|
|||
np->cwd = idup(p->cwd);
|
||||
}
|
||||
|
||||
// Set up new jmpbuf to start executing at forkret (see below).
|
||||
memset(&np->jmpbuf, 0, sizeof(np->jmpbuf));
|
||||
np->jmpbuf.eip = (uint)forkret;
|
||||
np->jmpbuf.esp = (uint)np->tf - 4;
|
||||
// Set up new context to start executing at forkret (see below).
|
||||
memset(&np->context, 0, sizeof(np->context));
|
||||
np->context.eip = (uint)forkret;
|
||||
np->context.esp = (uint)np->tf;
|
||||
|
||||
// Clear %eax so that fork system call returns 0 in child.
|
||||
np->tf->eax = 0;
|
||||
|
@ -206,8 +206,7 @@ scheduler(void)
|
|||
setupsegs(p);
|
||||
cp = p;
|
||||
p->state = RUNNING;
|
||||
if(setjmp(&cpus[cpu()].jmpbuf) == 0)
|
||||
longjmp(&p->jmpbuf);
|
||||
swtch(&cpus[cpu()].context, &p->context);
|
||||
|
||||
// Process is done running for now.
|
||||
// It should have changed its p->state before coming back.
|
||||
|
@ -232,8 +231,7 @@ sched(void)
|
|||
if(cpus[cpu()].nlock != 1)
|
||||
panic("sched locks");
|
||||
|
||||
if(setjmp(&cp->jmpbuf) == 0)
|
||||
longjmp(&cpus[cpu()].jmpbuf);
|
||||
swtch(&cp->context, &cpus[cpu()].context);
|
||||
}
|
||||
|
||||
// Give up the CPU for one scheduling round.
|
||||
|
@ -458,7 +456,7 @@ procdump(void)
|
|||
state = "???";
|
||||
cprintf("%d %s %s", p->pid, state, p->name);
|
||||
if(p->state == SLEEPING) {
|
||||
getcallerpcs((uint*)p->jmpbuf.ebp+2, pc);
|
||||
getcallerpcs((uint*)p->context.ebp+2, pc);
|
||||
for(j=0; j<10 && pc[j] != 0; j++)
|
||||
cprintf(" %p", pc[j]);
|
||||
}
|
||||
|
|
16
proc.h
16
proc.h
|
@ -10,18 +10,18 @@
|
|||
// Don't need to save all the %fs etc. segment registers,
|
||||
// because they are constant across kernel contexts.
|
||||
// Save all the regular registers so we don't need to care
|
||||
// which are caller save.
|
||||
// Don't save %eax, because that's the return register.
|
||||
// The layout of jmpbuf must match code in setjmp.S.
|
||||
struct jmpbuf {
|
||||
// which are caller save, but not the return register %eax.
|
||||
// (Not saving %eax just simplifies the switching code.)
|
||||
// The layout of context must match code in swtch.S.
|
||||
struct context {
|
||||
int eip;
|
||||
int esp;
|
||||
int ebx;
|
||||
int ecx;
|
||||
int edx;
|
||||
int esi;
|
||||
int edi;
|
||||
int esp;
|
||||
int ebp;
|
||||
int eip;
|
||||
};
|
||||
|
||||
enum proc_state { UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE };
|
||||
|
@ -38,7 +38,7 @@ struct proc {
|
|||
int killed; // If non-zero, have been killed
|
||||
struct file *ofile[NOFILE]; // Open files
|
||||
struct inode *cwd; // Current directory
|
||||
struct jmpbuf jmpbuf; // Jump here to run process
|
||||
struct context context; // Switch here to run process
|
||||
struct trapframe *tf; // Trap frame for current interrupt
|
||||
char name[16]; // Process name (debugging)
|
||||
};
|
||||
|
@ -61,7 +61,7 @@ extern struct proc *curproc[NCPU]; // Current (running) process per CPU
|
|||
// Per-CPU state
|
||||
struct cpu {
|
||||
uchar apicid; // Local APIC ID
|
||||
struct jmpbuf jmpbuf; // Jump here to enter scheduler
|
||||
struct context context; // Switch here to enter scheduler
|
||||
struct taskstate ts; // Used by x86 to find stack for interrupt
|
||||
struct segdesc gdt[NSEGS]; // x86 global descriptor table
|
||||
char mpstack[MPSTACK]; // Per-CPU startup stack
|
||||
|
|
|
@ -22,7 +22,7 @@ spinlock.c
|
|||
# processes
|
||||
proc.h
|
||||
proc.c
|
||||
setjmp.S
|
||||
swtch.S
|
||||
kalloc.c
|
||||
|
||||
# system calls
|
||||
|
|
49
setjmp.S
49
setjmp.S
|
@ -1,49 +0,0 @@
|
|||
# int setjmp(struct jmpbuf *jmp);
|
||||
# void longjmp(struct jmpbuf *jmp);
|
||||
#
|
||||
# Setjmp saves its stack environment in jmp for later use by longjmp.
|
||||
# It returns 0.
|
||||
#
|
||||
# Longjmp restores the environment saved by the last call of setjmp.
|
||||
# It then causes execution to continue as if the call of setjmp
|
||||
# had just returned 1.
|
||||
#
|
||||
# The caller of setjmp must not itself have returned in the interim.
|
||||
# All accessible data have values as of the time longjmp was called.
|
||||
#
|
||||
# [Description, but not code, borrowed from Plan 9.]
|
||||
|
||||
.globl setjmp
|
||||
setjmp:
|
||||
movl 4(%esp), %eax
|
||||
|
||||
movl %ebx, 0(%eax)
|
||||
movl %ecx, 4(%eax)
|
||||
movl %edx, 8(%eax)
|
||||
movl %esi, 12(%eax)
|
||||
movl %edi, 16(%eax)
|
||||
movl %esp, 20(%eax)
|
||||
movl %ebp, 24(%eax)
|
||||
pushl 0(%esp) # %eip
|
||||
popl 28(%eax)
|
||||
|
||||
movl $0, %eax # return value
|
||||
ret
|
||||
|
||||
.globl longjmp
|
||||
longjmp:
|
||||
movl 4(%esp), %eax
|
||||
|
||||
movl 0(%eax), %ebx
|
||||
movl 4(%eax), %ecx
|
||||
movl 8(%eax), %edx
|
||||
movl 12(%eax), %esi
|
||||
movl 16(%eax), %edi
|
||||
movl 20(%eax), %esp
|
||||
movl 24(%eax), %ebp
|
||||
|
||||
addl $4, %esp # pop and discard %eip
|
||||
pushl 28(%eax) # push new %eip
|
||||
|
||||
movl $1, %eax # return value (appears to come from setjmp!)
|
||||
ret
|
32
swtch.S
Normal file
32
swtch.S
Normal file
|
@ -0,0 +1,32 @@
|
|||
# void swtch(struct context *old, struct context *new);
|
||||
#
|
||||
# Save current register context in old
|
||||
# and then load register context from new.
|
||||
|
||||
.globl swtch
|
||||
swtch:
|
||||
# Save old registers
|
||||
movl 4(%esp), %eax
|
||||
|
||||
popl 0(%eax) # %eip
|
||||
movl %esp, 4(%eax)
|
||||
movl %ebx, 8(%eax)
|
||||
movl %ecx, 12(%eax)
|
||||
movl %edx, 16(%eax)
|
||||
movl %esi, 20(%eax)
|
||||
movl %edi, 24(%eax)
|
||||
movl %ebp, 28(%eax)
|
||||
|
||||
# Load new registers
|
||||
movl 4(%esp), %eax # not 8(%esp) - popped return address above
|
||||
|
||||
movl 28(%eax), %ebp
|
||||
movl 24(%eax), %edi
|
||||
movl 20(%eax), %esi
|
||||
movl 16(%eax), %edx
|
||||
movl 12(%eax), %ecx
|
||||
movl 8(%eax), %ebx
|
||||
movl 4(%eax), %esp
|
||||
pushl 0(%eax) # %eip
|
||||
|
||||
ret
|
Loading…
Reference in a new issue