Skip to content
Snippets Groups Projects
Commit c100d9ee authored by kolya's avatar kolya
Browse files

cleaner swtch.S

parent 228e500a
No related branches found
No related tags found
No related merge requests found
...@@ -107,7 +107,7 @@ void wakeup(void*); ...@@ -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*);
......
...@@ -137,9 +137,9 @@ copyproc(struct proc *p) ...@@ -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) ...@@ -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]);
} }
......
...@@ -7,21 +7,17 @@ ...@@ -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 { ...@@ -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 { ...@@ -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?
......
# 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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment