cleaner swtch.S

This commit is contained in:
kolya 2008-10-15 05:14:10 +00:00
parent 228e500a0c
commit c100d9ee2d
4 changed files with 31 additions and 41 deletions

2
defs.h
View file

@ -107,7 +107,7 @@ void wakeup(void*);
void yield(void); void yield(void);
// swtch.S // swtch.S
void swtch(struct context*, struct context*); void swtch(struct context**, struct context**);
// spinlock.c // spinlock.c
void acquire(struct spinlock*); void acquire(struct spinlock*);

8
proc.c
View file

@ -137,9 +137,9 @@ copyproc(struct proc *p)
} }
// Set up new context to start executing at forkret (see below). // Set up new context to start executing at forkret (see below).
memset(&np->context, 0, sizeof(np->context)); np->context = (struct context *)np->tf - 1;
np->context.eip = (uint)forkret; memset(np->context, 0, sizeof(*np->context));
np->context.esp = (uint)np->tf; np->context->eip = (uint)forkret;
// Clear %eax so that fork system call returns 0 in child. // Clear %eax so that fork system call returns 0 in child.
np->tf->eax = 0; np->tf->eax = 0;
@ -477,7 +477,7 @@ procdump(void)
state = "???"; state = "???";
cprintf("%d %s %s", p->pid, state, p->name); cprintf("%d %s %s", p->pid, state, p->name);
if(p->state == SLEEPING){ if(p->state == SLEEPING){
getcallerpcs((uint*)p->context.ebp+2, pc); getcallerpcs((uint*)p->context->ebp+2, pc);
for(j=0; j<10 && pc[j] != 0; j++) for(j=0; j<10 && pc[j] != 0; j++)
cprintf(" %p", pc[j]); cprintf(" %p", pc[j]);
} }

26
proc.h
View file

@ -7,21 +7,17 @@
#define NSEGS 6 #define NSEGS 6
// Saved registers for kernel context switches. // Saved registers for kernel context switches.
// Don't need to save all the %fs etc. segment registers, // Don't need to save all the segment registers (%cs, etc),
// because they are constant across kernel contexts. // because they are constant across kernel contexts.
// Save all the regular registers so we don't need to care // Stack pointer is encoded in the address of context,
// which are caller save, but not the return register %eax. // which must be placed at the bottom of the stack.
// (Not saving %eax just simplifies the switching code.)
// The layout of context must match code in swtch.S. // The layout of context must match code in swtch.S.
struct context { struct context {
int eip; uint edi;
int esp; uint esi;
int ebx; uint ebx;
int ecx; uint ebp;
int edx; uint eip;
int esi;
int edi;
int ebp;
}; };
enum proc_state { UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE }; enum proc_state { UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE };
@ -38,8 +34,8 @@ struct proc {
int killed; // If non-zero, have been killed int killed; // If non-zero, have been killed
struct file *ofile[NOFILE]; // Open files struct file *ofile[NOFILE]; // Open files
struct inode *cwd; // Current directory struct inode *cwd; // Current directory
struct context context; // Switch here to run process struct context *context; // Switch here to run process
struct trapframe *tf; // Trap frame for current interrupt struct trapframe *tf; // Trap frame for current syscall
char name[16]; // Process name (debugging) char name[16]; // Process name (debugging)
}; };
@ -53,7 +49,7 @@ struct proc {
struct cpu { struct cpu {
uchar apicid; // Local APIC ID uchar apicid; // Local APIC ID
struct proc *curproc; // Process currently running. struct proc *curproc; // Process currently running.
struct context context; // Switch here to enter scheduler struct context *context; // Switch here to enter scheduler
struct taskstate ts; // Used by x86 to find stack for interrupt struct taskstate ts; // Used by x86 to find stack for interrupt
struct segdesc gdt[NSEGS]; // x86 global descriptor table struct segdesc gdt[NSEGS]; // x86 global descriptor table
volatile uint booted; // Has the CPU started? volatile uint booted; // Has the CPU started?

36
swtch.S
View file

@ -1,32 +1,26 @@
# void swtch(struct context *old, struct context *new); # void swtch(struct context **old, struct context **new);
# #
# Save current register context in old # Save current register context in old
# and then load register context from new. # and then load register context from new.
.globl swtch .globl swtch
swtch: swtch:
# Save old registers
movl 4(%esp), %eax movl 4(%esp), %eax
movl 8(%esp), %edx
popl 0(%eax) # %eip # Save old callee-save registers
movl %esp, 4(%eax) pushl %ebp
movl %ebx, 8(%eax) pushl %ebx
movl %ecx, 12(%eax) pushl %esi
movl %edx, 16(%eax) pushl %edi
movl %esi, 20(%eax)
movl %edi, 24(%eax)
movl %ebp, 28(%eax)
# Load new registers # Switch stacks
movl 4(%esp), %eax # not 8(%esp) - popped return address above movl %esp, (%eax)
movl (%edx), %esp
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
# Load new callee-save registers
popl %edi
popl %esi
popl %ebx
popl %ebp
ret ret