diff options
| author | rsc <rsc> | 2007-08-28 12:48:33 +0000 | 
|---|---|---|
| committer | rsc <rsc> | 2007-08-28 12:48:33 +0000 | 
| commit | 818fc0125e7d73fdf4f1a94f178254e5d05c9831 (patch) | |
| tree | 2aefee5aad4478bc570d772a73ee1999d6066b54 | |
| parent | b52dea08bc1252bd842bf86f34d912c9ab7a02df (diff) | |
| download | xv6-labs-818fc0125e7d73fdf4f1a94f178254e5d05c9831.tar.gz xv6-labs-818fc0125e7d73fdf4f1a94f178254e5d05c9831.tar.bz2 xv6-labs-818fc0125e7d73fdf4f1a94f178254e5d05c9831.zip | |
replace setjmp/longjmp with swtch
| -rw-r--r-- | Makefile | 19 | ||||
| -rw-r--r-- | defs.h | 7 | ||||
| -rw-r--r-- | proc.c | 16 | ||||
| -rw-r--r-- | proc.h | 16 | ||||
| -rw-r--r-- | runoff.list | 2 | ||||
| -rw-r--r-- | setjmp.S | 49 | ||||
| -rw-r--r-- | swtch.S | 32 | 
7 files changed, 55 insertions, 86 deletions
| @@ -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 @@ -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*); @@ -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]);      } @@ -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 @@ -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 | 
