提交 a5579e26 创建 作者: Frans Kaashoek's avatar Frans Kaashoek

partitioned proc table

上级 f70ef994
...@@ -190,7 +190,7 @@ consoleintr(int (*getc)(void)) ...@@ -190,7 +190,7 @@ consoleintr(int (*getc)(void))
while((c = getc()) >= 0){ while((c = getc()) >= 0){
switch(c){ switch(c){
case C('P'): // Process listing. case C('P'): // Process listing.
procdump(); procdump(cpunum());
break; break;
case C('U'): // Kill line. case C('U'): // Kill line.
while(input.e != input.w && while(input.e != input.w &&
......
...@@ -99,7 +99,7 @@ int fork(void); ...@@ -99,7 +99,7 @@ int fork(void);
int growproc(int); int growproc(int);
int kill(int); int kill(int);
void pinit(void); void pinit(void);
void procdump(void); void procdump(int);
void scheduler(void) __attribute__((noreturn)); void scheduler(void) __attribute__((noreturn));
void sched(void); void sched(void);
void sleep(void*, struct spinlock*); void sleep(void*, struct spinlock*);
......
#include "types.h" #include "types.h"
#include "param.h" #include "param.h"
#include "mmu.h" #include "mmu.h"
#include "spinlock.h"
#include "proc.h" #include "proc.h"
#include "defs.h" #include "defs.h"
#include "x86.h" #include "x86.h"
...@@ -17,6 +18,9 @@ exec(char *path, char **argv) ...@@ -17,6 +18,9 @@ exec(char *path, char **argv)
struct proghdr ph; struct proghdr ph;
pde_t *pgdir, *oldpgdir; pde_t *pgdir, *oldpgdir;
cprintf("%d: exec %s\n", cpunum(), path);
procdump(cpunum());
if((ip = namei(path)) == 0) if((ip = namei(path)) == 0)
return -1; return -1;
ilock(ip); ilock(ip);
...@@ -89,9 +93,12 @@ exec(char *path, char **argv) ...@@ -89,9 +93,12 @@ exec(char *path, char **argv)
switchuvm(proc); switchuvm(proc);
freevm(oldpgdir); freevm(oldpgdir);
cprintf("exec done\n");
return 0; return 0;
bad: bad:
cprintf("exec failed\n");
if(pgdir) if(pgdir)
freevm(pgdir); freevm(pgdir);
if(ip) if(ip)
......
...@@ -15,8 +15,8 @@ ...@@ -15,8 +15,8 @@
#include "param.h" #include "param.h"
#include "stat.h" #include "stat.h"
#include "mmu.h" #include "mmu.h"
#include "proc.h"
#include "spinlock.h" #include "spinlock.h"
#include "proc.h"
#include "buf.h" #include "buf.h"
#include "fs.h" #include "fs.h"
#include "file.h" #include "file.h"
......
...@@ -4,10 +4,10 @@ ...@@ -4,10 +4,10 @@
#include "defs.h" #include "defs.h"
#include "param.h" #include "param.h"
#include "mmu.h" #include "mmu.h"
#include "spinlock.h"
#include "proc.h" #include "proc.h"
#include "x86.h" #include "x86.h"
#include "traps.h" #include "traps.h"
#include "spinlock.h"
#include "buf.h" #include "buf.h"
#define IDE_BSY 0x80 #define IDE_BSY 0x80
...@@ -49,6 +49,7 @@ ideinit(void) ...@@ -49,6 +49,7 @@ ideinit(void)
initlock(&idelock, "ide"); initlock(&idelock, "ide");
picenable(IRQ_IDE); picenable(IRQ_IDE);
ioapicenable(IRQ_IDE, ncpu - 1); ioapicenable(IRQ_IDE, ncpu - 1);
// ioapicenable(IRQ_IDE, 0);
idewait(0); idewait(0);
// Check if disk 1 is present // Check if disk 1 is present
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include "defs.h" #include "defs.h"
#include "param.h" #include "param.h"
#include "mmu.h" #include "mmu.h"
#include "spinlock.h"
#include "proc.h" #include "proc.h"
#include "x86.h" #include "x86.h"
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "mp.h" #include "mp.h"
#include "x86.h" #include "x86.h"
#include "mmu.h" #include "mmu.h"
#include "spinlock.h"
#include "proc.h" #include "proc.h"
struct cpu cpus[NCPU]; struct cpu cpus[NCPU];
......
...@@ -2,10 +2,10 @@ ...@@ -2,10 +2,10 @@
#include "defs.h" #include "defs.h"
#include "param.h" #include "param.h"
#include "mmu.h" #include "mmu.h"
#include "spinlock.h"
#include "proc.h" #include "proc.h"
#include "fs.h" #include "fs.h"
#include "file.h" #include "file.h"
#include "spinlock.h"
#define PIPESIZE 512 #define PIPESIZE 512
......
...@@ -3,14 +3,10 @@ ...@@ -3,14 +3,10 @@
#include "param.h" #include "param.h"
#include "mmu.h" #include "mmu.h"
#include "x86.h" #include "x86.h"
#include "proc.h"
#include "spinlock.h" #include "spinlock.h"
#include "proc.h"
struct { struct ptable ptables[NCPU];
struct spinlock lock;
struct proc proc[NPROC];
} ptable;
static struct proc *initproc; static struct proc *initproc;
int nextpid = 1; int nextpid = 1;
...@@ -22,7 +18,7 @@ static void wakeup1(void *chan); ...@@ -22,7 +18,7 @@ static void wakeup1(void *chan);
void void
pinit(void) pinit(void)
{ {
initlock(&ptable.lock, "ptable"); initlock(&ptable->lock, "ptable");
} }
//PAGEBREAK: 32 //PAGEBREAK: 32
...@@ -36,17 +32,17 @@ allocproc(void) ...@@ -36,17 +32,17 @@ allocproc(void)
struct proc *p; struct proc *p;
char *sp; char *sp;
acquire(&ptable.lock); acquire(&ptable->lock);
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++) for(p = ptable->proc; p < &ptable->proc[NPROC]; p++)
if(p->state == UNUSED) if(p->state == UNUSED)
goto found; goto found;
release(&ptable.lock); release(&ptable->lock);
return 0; return 0;
found: found:
p->state = EMBRYO; p->state = EMBRYO;
p->pid = nextpid++; p->pid = nextpid++;
release(&ptable.lock); release(&ptable->lock);
// Allocate kernel stack if possible. // Allocate kernel stack if possible.
if((p->kstack = kalloc()) == 0){ if((p->kstack = kalloc()) == 0){
...@@ -130,6 +126,8 @@ fork(void) ...@@ -130,6 +126,8 @@ fork(void)
int i, pid; int i, pid;
struct proc *np; struct proc *np;
cprintf("%d: fork\n", cpunum());
// Allocate process. // Allocate process.
if((np = allocproc()) == 0) if((np = allocproc()) == 0)
return -1; return -1;
...@@ -182,13 +180,13 @@ exit(void) ...@@ -182,13 +180,13 @@ exit(void)
iput(proc->cwd); iput(proc->cwd);
proc->cwd = 0; proc->cwd = 0;
acquire(&ptable.lock); acquire(&ptable->lock);
// Parent might be sleeping in wait(). // Parent might be sleeping in wait().
wakeup1(proc->parent); wakeup1(proc->parent);
// Pass abandoned children to init. // Pass abandoned children to init.
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ for(p = ptable->proc; p < &ptable->proc[NPROC]; p++){
if(p->parent == proc){ if(p->parent == proc){
p->parent = initproc; p->parent = initproc;
if(p->state == ZOMBIE) if(p->state == ZOMBIE)
...@@ -210,11 +208,11 @@ wait(void) ...@@ -210,11 +208,11 @@ wait(void)
struct proc *p; struct proc *p;
int havekids, pid; int havekids, pid;
acquire(&ptable.lock); acquire(&ptable->lock);
for(;;){ for(;;){
// Scan through table looking for zombie children. // Scan through table looking for zombie children.
havekids = 0; havekids = 0;
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ for(p = ptable->proc; p < &ptable->proc[NPROC]; p++){
if(p->parent != proc) if(p->parent != proc)
continue; continue;
havekids = 1; havekids = 1;
...@@ -229,19 +227,19 @@ wait(void) ...@@ -229,19 +227,19 @@ wait(void)
p->parent = 0; p->parent = 0;
p->name[0] = 0; p->name[0] = 0;
p->killed = 0; p->killed = 0;
release(&ptable.lock); release(&ptable->lock);
return pid; return pid;
} }
} }
// No point waiting if we don't have any children. // No point waiting if we don't have any children.
if(!havekids || proc->killed){ if(!havekids || proc->killed){
release(&ptable.lock); release(&ptable->lock);
return -1; return -1;
} }
// Wait for children to exit. (See wakeup1 call in proc_exit.) // Wait for children to exit. (See wakeup1 call in proc_exit.)
sleep(proc, &ptable.lock); //DOC: wait-sleep sleep(proc, &ptable->lock); //DOC: wait-sleep
} }
} }
...@@ -263,13 +261,13 @@ scheduler(void) ...@@ -263,13 +261,13 @@ scheduler(void)
sti(); sti();
// Loop over process table looking for process to run. // Loop over process table looking for process to run.
acquire(&ptable.lock); acquire(&ptable->lock);
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ for(p = ptable->proc; p < &ptable->proc[NPROC]; p++){
if(p->state != RUNNABLE) if(p->state != RUNNABLE)
continue; continue;
// Switch to chosen process. It is the process's job // Switch to chosen process. It is the process's job
// to release ptable.lock and then reacquire it // to release ptable->lock and then reacquire it
// before jumping back to us. // before jumping back to us.
proc = p; proc = p;
switchuvm(p); switchuvm(p);
...@@ -281,20 +279,20 @@ scheduler(void) ...@@ -281,20 +279,20 @@ scheduler(void)
// It should have changed its p->state before coming back. // It should have changed its p->state before coming back.
proc = 0; proc = 0;
} }
release(&ptable.lock); release(&ptable->lock);
} }
} }
// Enter scheduler. Must hold only ptable.lock // Enter scheduler. Must hold only ptable->lock
// and have changed proc->state. // and have changed proc->state.
void void
sched(void) sched(void)
{ {
int intena; int intena;
if(!holding(&ptable.lock)) if(!holding(&ptable->lock))
panic("sched ptable.lock"); panic("sched ptable->lock");
if(cpu->ncli != 1) if(cpu->ncli != 1)
panic("sched locks"); panic("sched locks");
if(proc->state == RUNNING) if(proc->state == RUNNING)
...@@ -310,10 +308,10 @@ sched(void) ...@@ -310,10 +308,10 @@ sched(void)
void void
yield(void) yield(void)
{ {
acquire(&ptable.lock); //DOC: yieldlock acquire(&ptable->lock); //DOC: yieldlock
proc->state = RUNNABLE; proc->state = RUNNABLE;
sched(); sched();
release(&ptable.lock); release(&ptable->lock);
} }
// A fork child's very first scheduling by scheduler() // A fork child's very first scheduling by scheduler()
...@@ -321,8 +319,8 @@ yield(void) ...@@ -321,8 +319,8 @@ yield(void)
void void
forkret(void) forkret(void)
{ {
// Still holding ptable.lock from scheduler. // Still holding ptable->lock from scheduler.
release(&ptable.lock); release(&ptable->lock);
// Return to "caller", actually trapret (see allocproc). // Return to "caller", actually trapret (see allocproc).
} }
...@@ -338,14 +336,14 @@ sleep(void *chan, struct spinlock *lk) ...@@ -338,14 +336,14 @@ sleep(void *chan, struct spinlock *lk)
if(lk == 0) if(lk == 0)
panic("sleep without lk"); panic("sleep without lk");
// Must acquire ptable.lock in order to // Must acquire ptable->lock in order to
// change p->state and then call sched. // change p->state and then call sched.
// Once we hold ptable.lock, we can be // Once we hold ptable->lock, we can be
// guaranteed that we won't miss any wakeup // guaranteed that we won't miss any wakeup
// (wakeup runs with ptable.lock locked), // (wakeup runs with ptable->lock locked),
// so it's okay to release lk. // so it's okay to release lk.
if(lk != &ptable.lock){ //DOC: sleeplock0 if(lk != &ptable->lock){ //DOC: sleeplock0
acquire(&ptable.lock); //DOC: sleeplock1 acquire(&ptable->lock); //DOC: sleeplock1
release(lk); release(lk);
} }
...@@ -358,8 +356,8 @@ sleep(void *chan, struct spinlock *lk) ...@@ -358,8 +356,8 @@ sleep(void *chan, struct spinlock *lk)
proc->chan = 0; proc->chan = 0;
// Reacquire original lock. // Reacquire original lock.
if(lk != &ptable.lock){ //DOC: sleeplock2 if(lk != &ptable->lock){ //DOC: sleeplock2
release(&ptable.lock); release(&ptable->lock);
acquire(lk); acquire(lk);
} }
} }
...@@ -372,7 +370,7 @@ wakeup1(void *chan) ...@@ -372,7 +370,7 @@ wakeup1(void *chan)
{ {
struct proc *p; struct proc *p;
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++) for(p = ptable->proc; p < &ptable->proc[NPROC]; p++)
if(p->state == SLEEPING && p->chan == chan) if(p->state == SLEEPING && p->chan == chan)
p->state = RUNNABLE; p->state = RUNNABLE;
} }
...@@ -381,9 +379,9 @@ wakeup1(void *chan) ...@@ -381,9 +379,9 @@ wakeup1(void *chan)
void void
wakeup(void *chan) wakeup(void *chan)
{ {
acquire(&ptable.lock); acquire(&ptable->lock);
wakeup1(chan); wakeup1(chan);
release(&ptable.lock); release(&ptable->lock);
} }
// Kill the process with the given pid. // Kill the process with the given pid.
...@@ -394,18 +392,18 @@ kill(int pid) ...@@ -394,18 +392,18 @@ kill(int pid)
{ {
struct proc *p; struct proc *p;
acquire(&ptable.lock); acquire(&ptable->lock);
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ for(p = ptable->proc; p < &ptable->proc[NPROC]; p++){
if(p->pid == pid){ if(p->pid == pid){
p->killed = 1; p->killed = 1;
// Wake process from sleep if necessary. // Wake process from sleep if necessary.
if(p->state == SLEEPING) if(p->state == SLEEPING)
p->state = RUNNABLE; p->state = RUNNABLE;
release(&ptable.lock); release(&ptable->lock);
return 0; return 0;
} }
} }
release(&ptable.lock); release(&ptable->lock);
return -1; return -1;
} }
...@@ -414,7 +412,7 @@ kill(int pid) ...@@ -414,7 +412,7 @@ kill(int pid)
// Runs when user types ^P on console. // Runs when user types ^P on console.
// No lock to avoid wedging a stuck machine further. // No lock to avoid wedging a stuck machine further.
void void
procdump(void) procdump(int c)
{ {
static char *states[] = { static char *states[] = {
[UNUSED] "unused", [UNUSED] "unused",
...@@ -429,7 +427,8 @@ procdump(void) ...@@ -429,7 +427,8 @@ procdump(void)
char *state; char *state;
uint pc[10]; uint pc[10];
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ cprintf("proc table cpu %d\n", c);
for(p = ptables[c].proc; p < &ptables[c].proc[NPROC]; p++){
if(p->state == UNUSED) if(p->state == UNUSED)
continue; continue;
if(p->state >= 0 && p->state < NELEM(states) && states[p->state]) if(p->state >= 0 && p->state < NELEM(states) && states[p->state])
......
...@@ -8,34 +8,6 @@ ...@@ -8,34 +8,6 @@
#define SEG_TSS 6 // this process's task state #define SEG_TSS 6 // this process's task state
#define NSEGS 7 #define NSEGS 7
// Per-CPU state
struct cpu {
uchar id; // Local APIC ID; index into cpus[] below
struct context *scheduler; // swtch() here to enter scheduler
struct taskstate ts; // Used by x86 to find stack for interrupt
struct segdesc gdt[NSEGS]; // x86 global descriptor table
volatile uint booted; // Has the CPU started?
int ncli; // Depth of pushcli nesting.
int intena; // Were interrupts enabled before pushcli?
// Cpu-local storage variables; see below
struct cpu *cpu;
struct proc *proc; // The currently-running process.
};
extern struct cpu cpus[NCPU];
extern int ncpu;
// Per-CPU variables, holding pointers to the
// current cpu and to the current process.
// The asm suffix tells gcc to use "%gs:0" to refer to cpu
// and "%gs:4" to refer to proc. seginit sets up the
// %gs segment register so that %gs refers to the memory
// holding those two variables in the local cpu's struct cpu.
// This is similar to how thread-local variables are implemented
// in thread libraries such as Linux pthreads.
extern struct cpu *cpu asm("%gs:0"); // &cpus[cpunum()]
extern struct proc *proc asm("%gs:4"); // cpus[cpunum()].proc
//PAGEBREAK: 17 //PAGEBREAK: 17
// Saved registers for kernel context switches. // Saved registers for kernel context switches.
...@@ -80,3 +52,40 @@ struct proc { ...@@ -80,3 +52,40 @@ struct proc {
// original data and bss // original data and bss
// fixed-size stack // fixed-size stack
// expandable heap // expandable heap
// Per-CPU state
struct cpu {
uchar id; // Local APIC ID; index into cpus[] below
struct context *scheduler; // swtch() here to enter scheduler
struct taskstate ts; // Used by x86 to find stack for interrupt
struct segdesc gdt[NSEGS]; // x86 global descriptor table
volatile uint booted; // Has the CPU started?
int ncli; // Depth of pushcli nesting.
int intena; // Were interrupts enabled before pushcli?
// Cpu-local storage variables; see below
struct cpu *cpu;
struct proc *proc; // The currently-running process.
struct ptable *ptable; // The per-core proc table
};
struct ptable {
struct spinlock lock;
struct proc proc[NPROC];
};
extern struct ptable ptables[NCPU];
extern struct cpu cpus[NCPU];
extern int ncpu;
// Per-CPU variables, holding pointers to the
// current cpu and to the current process.
// The asm suffix tells gcc to use "%gs:0" to refer to cpu
// and "%gs:4" to refer to proc. seginit sets up the
// %gs segment register so that %gs refers to the memory
// holding those two variables in the local cpu's struct cpu.
// This is similar to how thread-local variables are implemented
// in thread libraries such as Linux pthreads.
extern struct cpu *cpu asm("%gs:0"); // &cpus[cpunum()]
extern struct proc *proc asm("%gs:4"); // cpus[cpunum()].proc
extern struct ptable *ptable asm("%gs:8"); // &ptables[cpunum()]
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
#include "param.h" #include "param.h"
#include "x86.h" #include "x86.h"
#include "mmu.h" #include "mmu.h"
#include "proc.h"
#include "spinlock.h" #include "spinlock.h"
#include "proc.h"
void void
initlock(struct spinlock *lk, char *name) initlock(struct spinlock *lk, char *name)
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include "defs.h" #include "defs.h"
#include "param.h" #include "param.h"
#include "mmu.h" #include "mmu.h"
#include "spinlock.h"
#include "proc.h" #include "proc.h"
#include "x86.h" #include "x86.h"
#include "syscall.h" #include "syscall.h"
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include "param.h" #include "param.h"
#include "stat.h" #include "stat.h"
#include "mmu.h" #include "mmu.h"
#include "spinlock.h"
#include "proc.h" #include "proc.h"
#include "fs.h" #include "fs.h"
#include "file.h" #include "file.h"
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include "defs.h" #include "defs.h"
#include "param.h" #include "param.h"
#include "mmu.h" #include "mmu.h"
#include "spinlock.h"
#include "proc.h" #include "proc.h"
int int
......
...@@ -2,10 +2,10 @@ ...@@ -2,10 +2,10 @@
#include "defs.h" #include "defs.h"
#include "param.h" #include "param.h"
#include "mmu.h" #include "mmu.h"
#include "spinlock.h"
#include "proc.h" #include "proc.h"
#include "x86.h" #include "x86.h"
#include "traps.h" #include "traps.h"
#include "spinlock.h"
// Interrupt descriptor table (shared by all CPUs). // Interrupt descriptor table (shared by all CPUs).
struct gatedesc idt[256]; struct gatedesc idt[256];
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include "defs.h" #include "defs.h"
#include "x86.h" #include "x86.h"
#include "mmu.h" #include "mmu.h"
#include "spinlock.h"
#include "proc.h" #include "proc.h"
#include "elf.h" #include "elf.h"
...@@ -35,8 +36,8 @@ seginit(void) ...@@ -35,8 +36,8 @@ seginit(void)
c->gdt[SEG_UCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, DPL_USER); c->gdt[SEG_UCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, DPL_USER);
c->gdt[SEG_UDATA] = SEG(STA_W, 0, 0xffffffff, DPL_USER); c->gdt[SEG_UDATA] = SEG(STA_W, 0, 0xffffffff, DPL_USER);
// Map cpu, and curproc // Map cpu, curproc, and ptable
c->gdt[SEG_KCPU] = SEG(STA_W, &c->cpu, 8, 0); c->gdt[SEG_KCPU] = SEG(STA_W, &c->cpu, 12, 0);
lgdt(c->gdt, sizeof(c->gdt)); lgdt(c->gdt, sizeof(c->gdt));
loadgs(SEG_KCPU << 3); loadgs(SEG_KCPU << 3);
...@@ -44,6 +45,7 @@ seginit(void) ...@@ -44,6 +45,7 @@ seginit(void)
// Initialize cpu-local storage. // Initialize cpu-local storage.
cpu = c; cpu = c;
proc = 0; proc = 0;
ptable = &ptables[cpunum()];
} }
// Return the address of the PTE in page table pgdir // Return the address of the PTE in page table pgdir
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论