Skip to content

Commit

Permalink
replace setjmp/longjmp with swtch
Browse files Browse the repository at this point in the history
  • Loading branch information
rsc committed Aug 28, 2007
1 parent b52dea0 commit 818fc01
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 86 deletions.
19 changes: 4 additions & 15 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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\
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
7 changes: 3 additions & 4 deletions defs.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
struct buf;
struct context;
struct file;
struct inode;
struct jmpbuf;
struct pipe;
struct proc;
struct spinlock;
Expand Down Expand Up @@ -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*);
Expand Down
16 changes: 7 additions & 9 deletions proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand All @@ -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.
Expand Down Expand Up @@ -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]);
}
Expand Down
16 changes: 8 additions & 8 deletions proc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand All @@ -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)
};
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion runoff.list
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ spinlock.c
# processes
proc.h
proc.c
setjmp.S
swtch.S
kalloc.c

# system calls
Expand Down
49 changes: 0 additions & 49 deletions setjmp.S

This file was deleted.

32 changes: 32 additions & 0 deletions swtch.S
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 818fc01

Please sign in to comment.