cleaner swtch.S
This commit is contained in:
parent
228e500a0c
commit
c100d9ee2d
4 changed files with 31 additions and 41 deletions
2
defs.h
2
defs.h
|
@ -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
8
proc.c
|
@ -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
26
proc.h
|
@ -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
36
swtch.S
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue