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

partitioned proc table

上级 f70ef994
......@@ -190,7 +190,7 @@ consoleintr(int (*getc)(void))
while((c = getc()) >= 0){
switch(c){
case C('P'): // Process listing.
procdump();
procdump(cpunum());
break;
case C('U'): // Kill line.
while(input.e != input.w &&
......
......@@ -99,7 +99,7 @@ int fork(void);
int growproc(int);
int kill(int);
void pinit(void);
void procdump(void);
void procdump(int);
void scheduler(void) __attribute__((noreturn));
void sched(void);
void sleep(void*, struct spinlock*);
......
#include "types.h"
#include "param.h"
#include "mmu.h"
#include "spinlock.h"
#include "proc.h"
#include "defs.h"
#include "x86.h"
......@@ -17,6 +18,9 @@ exec(char *path, char **argv)
struct proghdr ph;
pde_t *pgdir, *oldpgdir;
cprintf("%d: exec %s\n", cpunum(), path);
procdump(cpunum());
if((ip = namei(path)) == 0)
return -1;
ilock(ip);
......@@ -89,9 +93,12 @@ exec(char *path, char **argv)
switchuvm(proc);
freevm(oldpgdir);
cprintf("exec done\n");
return 0;
bad:
cprintf("exec failed\n");
if(pgdir)
freevm(pgdir);
if(ip)
......
......@@ -15,8 +15,8 @@
#include "param.h"
#include "stat.h"
#include "mmu.h"
#include "proc.h"
#include "spinlock.h"
#include "proc.h"
#include "buf.h"
#include "fs.h"
#include "file.h"
......
......@@ -4,10 +4,10 @@
#include "defs.h"
#include "param.h"
#include "mmu.h"
#include "spinlock.h"
#include "proc.h"
#include "x86.h"
#include "traps.h"
#include "spinlock.h"
#include "buf.h"
#define IDE_BSY 0x80
......@@ -49,6 +49,7 @@ ideinit(void)
initlock(&idelock, "ide");
picenable(IRQ_IDE);
ioapicenable(IRQ_IDE, ncpu - 1);
// ioapicenable(IRQ_IDE, 0);
idewait(0);
// Check if disk 1 is present
......
......@@ -2,6 +2,7 @@
#include "defs.h"
#include "param.h"
#include "mmu.h"
#include "spinlock.h"
#include "proc.h"
#include "x86.h"
......
......@@ -8,6 +8,7 @@
#include "mp.h"
#include "x86.h"
#include "mmu.h"
#include "spinlock.h"
#include "proc.h"
struct cpu cpus[NCPU];
......
......@@ -2,10 +2,10 @@
#include "defs.h"
#include "param.h"
#include "mmu.h"
#include "spinlock.h"
#include "proc.h"
#include "fs.h"
#include "file.h"
#include "spinlock.h"
#define PIPESIZE 512
......
......@@ -3,14 +3,10 @@
#include "param.h"
#include "mmu.h"
#include "x86.h"
#include "proc.h"
#include "spinlock.h"
#include "proc.h"
struct {
struct spinlock lock;
struct proc proc[NPROC];
} ptable;
struct ptable ptables[NCPU];
static struct proc *initproc;
int nextpid = 1;
......@@ -22,7 +18,7 @@ static void wakeup1(void *chan);
void
pinit(void)
{
initlock(&ptable.lock, "ptable");
initlock(&ptable->lock, "ptable");
}
//PAGEBREAK: 32
......@@ -36,17 +32,17 @@ allocproc(void)
struct proc *p;
char *sp;
acquire(&ptable.lock);
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++)
acquire(&ptable->lock);
for(p = ptable->proc; p < &ptable->proc[NPROC]; p++)
if(p->state == UNUSED)
goto found;
release(&ptable.lock);
release(&ptable->lock);
return 0;
found:
p->state = EMBRYO;
p->pid = nextpid++;
release(&ptable.lock);
release(&ptable->lock);
// Allocate kernel stack if possible.
if((p->kstack = kalloc()) == 0){
......@@ -130,6 +126,8 @@ fork(void)
int i, pid;
struct proc *np;
cprintf("%d: fork\n", cpunum());
// Allocate process.
if((np = allocproc()) == 0)
return -1;
......@@ -182,13 +180,13 @@ exit(void)
iput(proc->cwd);
proc->cwd = 0;
acquire(&ptable.lock);
acquire(&ptable->lock);
// Parent might be sleeping in wait().
wakeup1(proc->parent);
// 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){
p->parent = initproc;
if(p->state == ZOMBIE)
......@@ -210,11 +208,11 @@ wait(void)
struct proc *p;
int havekids, pid;
acquire(&ptable.lock);
acquire(&ptable->lock);
for(;;){
// Scan through table looking for zombie children.
havekids = 0;
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
for(p = ptable->proc; p < &ptable->proc[NPROC]; p++){
if(p->parent != proc)
continue;
havekids = 1;
......@@ -229,19 +227,19 @@ wait(void)
p->parent = 0;
p->name[0] = 0;
p->killed = 0;
release(&ptable.lock);
release(&ptable->lock);
return pid;
}
}
// No point waiting if we don't have any children.
if(!havekids || proc->killed){
release(&ptable.lock);
release(&ptable->lock);
return -1;
}
// 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)
sti();
// Loop over process table looking for process to run.
acquire(&ptable.lock);
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
acquire(&ptable->lock);
for(p = ptable->proc; p < &ptable->proc[NPROC]; p++){
if(p->state != RUNNABLE)
continue;
// 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.
proc = p;
switchuvm(p);
......@@ -281,20 +279,20 @@ scheduler(void)
// It should have changed its p->state before coming back.
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.
void
sched(void)
{
int intena;
if(!holding(&ptable.lock))
panic("sched ptable.lock");
if(!holding(&ptable->lock))
panic("sched ptable->lock");
if(cpu->ncli != 1)
panic("sched locks");
if(proc->state == RUNNING)
......@@ -310,10 +308,10 @@ sched(void)
void
yield(void)
{
acquire(&ptable.lock); //DOC: yieldlock
acquire(&ptable->lock); //DOC: yieldlock
proc->state = RUNNABLE;
sched();
release(&ptable.lock);
release(&ptable->lock);
}
// A fork child's very first scheduling by scheduler()
......@@ -321,8 +319,8 @@ yield(void)
void
forkret(void)
{
// Still holding ptable.lock from scheduler.
release(&ptable.lock);
// Still holding ptable->lock from scheduler.
release(&ptable->lock);
// Return to "caller", actually trapret (see allocproc).
}
......@@ -338,14 +336,14 @@ sleep(void *chan, struct spinlock *lk)
if(lk == 0)
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.
// Once we hold ptable.lock, we can be
// Once we hold ptable->lock, we can be
// 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.
if(lk != &ptable.lock){ //DOC: sleeplock0
acquire(&ptable.lock); //DOC: sleeplock1
if(lk != &ptable->lock){ //DOC: sleeplock0
acquire(&ptable->lock); //DOC: sleeplock1
release(lk);
}
......@@ -358,8 +356,8 @@ sleep(void *chan, struct spinlock *lk)
proc->chan = 0;
// Reacquire original lock.
if(lk != &ptable.lock){ //DOC: sleeplock2
release(&ptable.lock);
if(lk != &ptable->lock){ //DOC: sleeplock2
release(&ptable->lock);
acquire(lk);
}
}
......@@ -372,7 +370,7 @@ wakeup1(void *chan)
{
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)
p->state = RUNNABLE;
}
......@@ -381,9 +379,9 @@ wakeup1(void *chan)
void
wakeup(void *chan)
{
acquire(&ptable.lock);
acquire(&ptable->lock);
wakeup1(chan);
release(&ptable.lock);
release(&ptable->lock);
}
// Kill the process with the given pid.
......@@ -394,18 +392,18 @@ kill(int pid)
{
struct proc *p;
acquire(&ptable.lock);
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
acquire(&ptable->lock);
for(p = ptable->proc; p < &ptable->proc[NPROC]; p++){
if(p->pid == pid){
p->killed = 1;
// Wake process from sleep if necessary.
if(p->state == SLEEPING)
p->state = RUNNABLE;
release(&ptable.lock);
release(&ptable->lock);
return 0;
}
}
release(&ptable.lock);
release(&ptable->lock);
return -1;
}
......@@ -414,7 +412,7 @@ kill(int pid)
// Runs when user types ^P on console.
// No lock to avoid wedging a stuck machine further.
void
procdump(void)
procdump(int c)
{
static char *states[] = {
[UNUSED] "unused",
......@@ -429,7 +427,8 @@ procdump(void)
char *state;
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)
continue;
if(p->state >= 0 && p->state < NELEM(states) && states[p->state])
......
......@@ -8,34 +8,6 @@
#define SEG_TSS 6 // this process's task state
#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
// Saved registers for kernel context switches.
......@@ -80,3 +52,40 @@ struct proc {
// original data and bss
// fixed-size stack
// 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 @@
#include "param.h"
#include "x86.h"
#include "mmu.h"
#include "proc.h"
#include "spinlock.h"
#include "proc.h"
void
initlock(struct spinlock *lk, char *name)
......
......@@ -2,6 +2,7 @@
#include "defs.h"
#include "param.h"
#include "mmu.h"
#include "spinlock.h"
#include "proc.h"
#include "x86.h"
#include "syscall.h"
......
......@@ -3,6 +3,7 @@
#include "param.h"
#include "stat.h"
#include "mmu.h"
#include "spinlock.h"
#include "proc.h"
#include "fs.h"
#include "file.h"
......
......@@ -3,6 +3,7 @@
#include "defs.h"
#include "param.h"
#include "mmu.h"
#include "spinlock.h"
#include "proc.h"
int
......
......@@ -2,10 +2,10 @@
#include "defs.h"
#include "param.h"
#include "mmu.h"
#include "spinlock.h"
#include "proc.h"
#include "x86.h"
#include "traps.h"
#include "spinlock.h"
// Interrupt descriptor table (shared by all CPUs).
struct gatedesc idt[256];
......
......@@ -3,6 +3,7 @@
#include "defs.h"
#include "x86.h"
#include "mmu.h"
#include "spinlock.h"
#include "proc.h"
#include "elf.h"
......@@ -35,8 +36,8 @@ seginit(void)
c->gdt[SEG_UCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, DPL_USER);
c->gdt[SEG_UDATA] = SEG(STA_W, 0, 0xffffffff, DPL_USER);
// Map cpu, and curproc
c->gdt[SEG_KCPU] = SEG(STA_W, &c->cpu, 8, 0);
// Map cpu, curproc, and ptable
c->gdt[SEG_KCPU] = SEG(STA_W, &c->cpu, 12, 0);
lgdt(c->gdt, sizeof(c->gdt));
loadgs(SEG_KCPU << 3);
......@@ -44,6 +45,7 @@ seginit(void)
// Initialize cpu-local storage.
cpu = c;
proc = 0;
ptable = &ptables[cpunum()];
}
// Return the address of the PTE in page table pgdir
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论