summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrsc <rsc>2007-08-28 12:48:33 +0000
committerrsc <rsc>2007-08-28 12:48:33 +0000
commit818fc0125e7d73fdf4f1a94f178254e5d05c9831 (patch)
tree2aefee5aad4478bc570d772a73ee1999d6066b54
parentb52dea08bc1252bd842bf86f34d912c9ab7a02df (diff)
downloadxv6-labs-818fc0125e7d73fdf4f1a94f178254e5d05c9831.tar.gz
xv6-labs-818fc0125e7d73fdf4f1a94f178254e5d05c9831.tar.bz2
xv6-labs-818fc0125e7d73fdf4f1a94f178254e5d05c9831.zip
replace setjmp/longjmp with swtch
-rw-r--r--Makefile19
-rw-r--r--defs.h7
-rw-r--r--proc.c16
-rw-r--r--proc.h16
-rw-r--r--runoff.list2
-rw-r--r--setjmp.S49
-rw-r--r--swtch.S32
7 files changed, 55 insertions, 86 deletions
diff --git a/Makefile b/Makefile
index a27ec5f..0e2bc0f 100644
--- a/Makefile
+++ b/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
diff --git a/defs.h b/defs.h
index a72ecaf..35323ea 100644
--- a/defs.h
+++ b/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*);
diff --git a/proc.c b/proc.c
index eb7d1f8..46a38bf 100644
--- a/proc.c
+++ b/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]);
}
diff --git a/proc.h b/proc.h
index 84dc57d..f76e264 100644
--- a/proc.h
+++ b/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
diff --git a/runoff.list b/runoff.list
index 80c8f35..cbc8fca 100644
--- a/runoff.list
+++ b/runoff.list
@@ -22,7 +22,7 @@ spinlock.c
# processes
proc.h
proc.c
-setjmp.S
+swtch.S
kalloc.c
# system calls
diff --git a/setjmp.S b/setjmp.S
deleted file mode 100644
index 3fe23c5..0000000
--- a/setjmp.S
+++ /dev/null
@@ -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
diff --git a/swtch.S b/swtch.S
new file mode 100644
index 0000000..786e9ac
--- /dev/null
+++ b/swtch.S
@@ -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