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

Primitive partitioned memory allocater (no stealing)

Primitive partitioned proc table, per core runq, and non-scalable stealing Panics on two cores, but i should make more frequent checkpoints
上级 a5579e26
...@@ -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(cpunum()); procdumpall();
break; break;
case C('U'): // Kill line. case C('U'): // Kill line.
while(input.e != input.w && while(input.e != input.w &&
......
...@@ -100,6 +100,7 @@ int growproc(int); ...@@ -100,6 +100,7 @@ int growproc(int);
int kill(int); int kill(int);
void pinit(void); void pinit(void);
void procdump(int); void procdump(int);
void procdumpall(void);
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*);
......
...@@ -19,7 +19,7 @@ exec(char *path, char **argv) ...@@ -19,7 +19,7 @@ exec(char *path, char **argv)
pde_t *pgdir, *oldpgdir; pde_t *pgdir, *oldpgdir;
cprintf("%d: exec %s\n", cpunum(), path); cprintf("%d: exec %s\n", cpunum(), path);
procdump(cpunum()); procdumpall();
if((ip = namei(path)) == 0) if((ip = namei(path)) == 0)
return -1; return -1;
......
...@@ -48,8 +48,8 @@ ideinit(void) ...@@ -48,8 +48,8 @@ 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); ioapicenable(IRQ_IDE, 0);
idewait(0); idewait(0);
// Check if disk 1 is present // Check if disk 1 is present
......
...@@ -7,15 +7,10 @@ ...@@ -7,15 +7,10 @@
#include "param.h" #include "param.h"
#include "mmu.h" #include "mmu.h"
#include "spinlock.h" #include "spinlock.h"
#include "proc.h"
#include "kalloc.h"
struct run { struct kmem kmems[NCPU];
struct run *next;
};
struct {
struct spinlock lock;
struct run *freelist;
} kmem;
extern char end[]; // first address after kernel loaded from ELF file extern char end[]; // first address after kernel loaded from ELF file
...@@ -23,12 +18,35 @@ extern char end[]; // first address after kernel loaded from ELF file ...@@ -23,12 +18,35 @@ extern char end[]; // first address after kernel loaded from ELF file
void void
kinit(void) kinit(void)
{ {
struct run *r;
char *p; char *p;
int c;
int n;
int i;
for (c = 0; c < NCPU; c++) {
kmems[c].name[0] = (char) c;
safestrcpy(kmems[c].name+1, "kmem", MAXNAME-1);
initlock(&kmems[c].lock, kmems[c].name);
}
initlock(&kmem.lock, "kmem");
p = (char*)PGROUNDUP((uint)end); p = (char*)PGROUNDUP((uint)end);
for(; p + PGSIZE <= (char*)PHYSTOP; p += PGSIZE) n = (char*)PHYSTOP - p;
kfree(p);
cprintf("n = %d\n", n);
n = n / PGSIZE;
cprintf("n = %d\n", n);
for (c = 0; c < NCPU; c++) {
for (i = 0; i < n; i++, p += PGSIZE) {
memset(p, 1, PGSIZE);
r = (struct run*)p;
r->next = kmems[c].freelist;
kmems[c].freelist = r;
}
}
} }
//PAGEBREAK: 21 //PAGEBREAK: 21
...@@ -47,11 +65,11 @@ kfree(char *v) ...@@ -47,11 +65,11 @@ kfree(char *v)
// Fill with junk to catch dangling refs. // Fill with junk to catch dangling refs.
memset(v, 1, PGSIZE); memset(v, 1, PGSIZE);
acquire(&kmem.lock); acquire(&kmem->lock);
r = (struct run*)v; r = (struct run*)v;
r->next = kmem.freelist; r->next = kmem->freelist;
kmem.freelist = r; kmem->freelist = r;
release(&kmem.lock); release(&kmem->lock);
} }
// Allocate one 4096-byte page of physical memory. // Allocate one 4096-byte page of physical memory.
...@@ -62,11 +80,14 @@ kalloc(void) ...@@ -62,11 +80,14 @@ kalloc(void)
{ {
struct run *r; struct run *r;
acquire(&kmem.lock); cprintf("%d: kalloc\n", cpunum());
r = kmem.freelist; acquire(&kmem->lock);
r = kmem->freelist;
if(r) if(r)
kmem.freelist = r->next; kmem->freelist = r->next;
release(&kmem.lock); release(&kmem->lock);
if (r == 0)
cprintf("%d: kalloc out\n", cpunum());
return (char*)r; return (char*)r;
} }
...@@ -58,7 +58,6 @@ mainc(void) ...@@ -58,7 +58,6 @@ mainc(void)
timerinit(); // uniprocessor timer timerinit(); // uniprocessor timer
userinit(); // first user process userinit(); // first user process
bootothers(); // start other processors bootothers(); // start other processors
// Finish setting up this processor in mpmain. // Finish setting up this processor in mpmain.
mpmain(); mpmain();
} }
...@@ -75,8 +74,10 @@ mpmain(void) ...@@ -75,8 +74,10 @@ mpmain(void)
} }
vmenable(); // turn on paging vmenable(); // turn on paging
cprintf("cpu%d: starting\n", cpu->id); cprintf("cpu%d: starting\n", cpu->id);
procdumpall();
idtinit(); // load idt register idtinit(); // load idt register
xchg(&cpu->booted, 1); // tell bootothers() we're up xchg(&cpu->booted, 1); // tell bootothers() we're up
procdumpall();
scheduler(); // start running processes scheduler(); // start running processes
} }
......
#define NPROC 64 // maximum number of processes #define NPROC 64 // maximum number of processes
#define KSTACKSIZE 4096 // size of per-process kernel stack #define KSTACKSIZE 4096 // size of per-process kernel stack
#define NCPU 8 // maximum number of CPUs #define NCPU 2 // maximum number of CPUs
#define NOFILE 16 // open files per process #define NOFILE 16 // open files per process
#define NFILE 100 // open files per system #define NFILE 100 // open files per system
#define NBUF 10 // size of disk block cache #define NBUF 10 // size of disk block cache
...@@ -10,3 +10,4 @@ ...@@ -10,3 +10,4 @@
#define USERTOP 0xA0000 // end of user address space #define USERTOP 0xA0000 // end of user address space
#define PHYSTOP 0x1000000 // use phys mem up to here as free pool #define PHYSTOP 0x1000000 // use phys mem up to here as free pool
#define MAXARG 32 // max exec arguments #define MAXARG 32 // max exec arguments
#define MAXNAME 16 // max string names
...@@ -18,7 +18,12 @@ static void wakeup1(void *chan); ...@@ -18,7 +18,12 @@ static void wakeup1(void *chan);
void void
pinit(void) pinit(void)
{ {
initlock(&ptable->lock, "ptable"); int c;
for (c = 0; c < NCPU; c++) {
ptables[c].name[0] = (char) c;
safestrcpy(ptables[c].name+1, "ptable", MAXNAME-1);
initlock(&ptables[c].lock, ptables[c].name);
}
} }
//PAGEBREAK: 32 //PAGEBREAK: 32
...@@ -41,7 +46,7 @@ allocproc(void) ...@@ -41,7 +46,7 @@ allocproc(void)
found: found:
p->state = EMBRYO; p->state = EMBRYO;
p->pid = nextpid++; p->pid = nextpid++; // XXX global var!
release(&ptable->lock); release(&ptable->lock);
// Allocate kernel stack if possible. // Allocate kernel stack if possible.
...@@ -68,6 +73,63 @@ found: ...@@ -68,6 +73,63 @@ found:
return p; return p;
} }
static void
addrun1(struct proc *p)
{
struct proc *q;
cprintf("%d: add to run %d\n", cpu->id, p->pid);
for (q = ptable->runq; q != 0; q = q->next) {
if (q == p) {
cprintf("allready on q\n");
p->state = RUNNABLE;
return;
}
}
p->state = RUNNABLE; // race?
p->next = ptable->runq;
ptable->runq = p;
}
static void
addrun(struct proc *p)
{
acquire(&ptable->lock);
addrun1(p);
release(&ptable->lock);
procdumpall();
}
static void
delrun1(struct ptable *pt, struct proc *proc)
{
struct proc *p = 0;
struct proc *n;
n = pt->runq;
while (n != 0) {
if (n == proc) {
if (p == 0) {
pt->runq = n->next;
} else {
p->next = n->next;
}
n->next = 0;
return;
} else {
p = n;
n = n->next;
}
}
}
void
delrun(struct proc *proc)
{
acquire(&ptable->lock);
delrun1(ptable, proc);
release(&ptable->lock);
}
//PAGEBREAK: 32 //PAGEBREAK: 32
// Set up first user process. // Set up first user process.
void void
...@@ -93,8 +155,7 @@ userinit(void) ...@@ -93,8 +155,7 @@ userinit(void)
safestrcpy(p->name, "initcode", sizeof(p->name)); safestrcpy(p->name, "initcode", sizeof(p->name));
p->cwd = namei("/"); p->cwd = namei("/");
addrun(p);
p->state = RUNNABLE;
} }
// Grow current process's memory by n bytes. // Grow current process's memory by n bytes.
...@@ -152,7 +213,7 @@ fork(void) ...@@ -152,7 +213,7 @@ fork(void)
np->cwd = idup(proc->cwd); np->cwd = idup(proc->cwd);
pid = np->pid; pid = np->pid;
np->state = RUNNABLE; addrun(np);
safestrcpy(np->name, proc->name, sizeof(proc->name)); safestrcpy(np->name, proc->name, sizeof(proc->name));
return pid; return pid;
} }
...@@ -180,8 +241,12 @@ exit(void) ...@@ -180,8 +241,12 @@ exit(void)
iput(proc->cwd); iput(proc->cwd);
proc->cwd = 0; proc->cwd = 0;
cprintf("%d: exit %s\n", cpunum(), proc->name);
acquire(&ptable->lock); acquire(&ptable->lock);
delrun1(ptable, proc);
// Parent might be sleeping in wait(). // Parent might be sleeping in wait().
wakeup1(proc->parent); wakeup1(proc->parent);
...@@ -243,6 +308,34 @@ wait(void) ...@@ -243,6 +308,34 @@ wait(void)
} }
} }
void
steal(void)
{
int c;
struct proc *p;
int r = 0;
for (c = 0; c < NCPU; c++) {
if (c == cpunum())
continue;
acquire(&ptables[c].lock);
for(p = ptables[c].runq; p != 0; p = p->next) {
if (p->state == RUNNABLE) {
cprintf("%d: steal %d from %d\n", cpunum(), p->pid, c);
delrun1(&ptables[c], p);
addrun(p);
r = 1;
break;
}
}
release(&ptables[c].lock);
if (r) {
procdumpall();
return;
}
}
}
//PAGEBREAK: 42 //PAGEBREAK: 42
// Per-CPU process scheduler. // Per-CPU process scheduler.
// Each CPU calls scheduler() after setting itself up. // Each CPU calls scheduler() after setting itself up.
...@@ -262,7 +355,7 @@ scheduler(void) ...@@ -262,7 +355,7 @@ scheduler(void)
// 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->runq; p != 0; p = p->next) {
if(p->state != RUNNABLE) if(p->state != RUNNABLE)
continue; continue;
...@@ -272,6 +365,7 @@ scheduler(void) ...@@ -272,6 +365,7 @@ scheduler(void)
proc = p; proc = p;
switchuvm(p); switchuvm(p);
p->state = RUNNING; p->state = RUNNING;
cprintf("%d: running %d\n", cpu->id, p->pid);
swtch(&cpu->scheduler, proc->context); swtch(&cpu->scheduler, proc->context);
switchkvm(); switchkvm();
...@@ -280,7 +374,7 @@ scheduler(void) ...@@ -280,7 +374,7 @@ scheduler(void)
proc = 0; proc = 0;
} }
release(&ptable->lock); release(&ptable->lock);
steal();
} }
} }
...@@ -309,7 +403,7 @@ void ...@@ -309,7 +403,7 @@ void
yield(void) yield(void)
{ {
acquire(&ptable->lock); //DOC: yieldlock acquire(&ptable->lock); //DOC: yieldlock
proc->state = RUNNABLE; proc->state = RUNNABLE; // race? stays in runqueue
sched(); sched();
release(&ptable->lock); release(&ptable->lock);
} }
...@@ -350,6 +444,7 @@ sleep(void *chan, struct spinlock *lk) ...@@ -350,6 +444,7 @@ sleep(void *chan, struct spinlock *lk)
// Go to sleep. // Go to sleep.
proc->chan = chan; proc->chan = chan;
proc->state = SLEEPING; proc->state = SLEEPING;
delrun1(ptable, proc);
sched(); sched();
// Tidy up. // Tidy up.
...@@ -372,13 +467,14 @@ wakeup1(void *chan) ...@@ -372,13 +467,14 @@ wakeup1(void *chan)
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; addrun1(p);
} }
// Wake up all processes sleeping on chan. // Wake up all processes sleeping on chan.
void void
wakeup(void *chan) wakeup(void *chan)
{ {
// XXX should go through all proctables
acquire(&ptable->lock); acquire(&ptable->lock);
wakeup1(chan); wakeup1(chan);
release(&ptable->lock); release(&ptable->lock);
...@@ -398,7 +494,7 @@ kill(int pid) ...@@ -398,7 +494,7 @@ kill(int 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; addrun1(p);
release(&ptable->lock); release(&ptable->lock);
return 0; return 0;
} }
...@@ -424,6 +520,7 @@ procdump(int c) ...@@ -424,6 +520,7 @@ procdump(int c)
}; };
int i; int i;
struct proc *p; struct proc *p;
struct proc *q;
char *state; char *state;
uint pc[10]; uint pc[10];
...@@ -443,6 +540,22 @@ procdump(int c) ...@@ -443,6 +540,22 @@ procdump(int c)
} }
cprintf("\n"); cprintf("\n");
} }
cprintf("runq: ");
for (q = ptables[c].runq; q != 0; q = q->next) {
if(q->state >= 0 && q->state < NELEM(states) && states[q->state])
state = states[q->state];
else
state = "???";
cprintf("%d %s %s, ", q->pid, state, q->name);
}
cprintf("\n");
} }
void
procdumpall(void)
{
int c;
for (c = 0; c < NCPU; c++) {
procdump(c);
}
}
...@@ -45,6 +45,7 @@ struct proc { ...@@ -45,6 +45,7 @@ struct proc {
struct file *ofile[NOFILE]; // Open files struct file *ofile[NOFILE]; // Open files
struct inode *cwd; // Current directory struct inode *cwd; // Current directory
char name[16]; // Process name (debugging) char name[16]; // Process name (debugging)
struct proc *next;
}; };
// Process memory is laid out contiguously, low addresses first: // Process memory is laid out contiguously, low addresses first:
...@@ -67,11 +68,14 @@ struct cpu { ...@@ -67,11 +68,14 @@ struct cpu {
struct cpu *cpu; struct cpu *cpu;
struct proc *proc; // The currently-running process. struct proc *proc; // The currently-running process.
struct ptable *ptable; // The per-core proc table struct ptable *ptable; // The per-core proc table
struct kmem *kmem; // The per-core proc table
}; };
struct ptable { struct ptable {
char name[MAXNAME];
struct spinlock lock; struct spinlock lock;
struct proc proc[NPROC]; struct proc proc[NPROC];
struct proc *runq;
}; };
extern struct ptable ptables[NCPU]; extern struct ptable ptables[NCPU];
...@@ -89,3 +93,4 @@ extern int ncpu; ...@@ -89,3 +93,4 @@ extern int ncpu;
extern struct cpu *cpu asm("%gs:0"); // &cpus[cpunum()] extern struct cpu *cpu asm("%gs:0"); // &cpus[cpunum()]
extern struct proc *proc asm("%gs:4"); // cpus[cpunum()].proc extern struct proc *proc asm("%gs:4"); // cpus[cpunum()].proc
extern struct ptable *ptable asm("%gs:8"); // &ptables[cpunum()] extern struct ptable *ptable asm("%gs:8"); // &ptables[cpunum()]
extern struct kmem *kmem asm("%gs:12"); // &kmems[cpunum()]
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "spinlock.h" #include "spinlock.h"
#include "proc.h" #include "proc.h"
#include "elf.h" #include "elf.h"
#include "kalloc.h"
extern char data[]; // defined in data.S extern char data[]; // defined in data.S
...@@ -36,8 +37,8 @@ seginit(void) ...@@ -36,8 +37,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, curproc, and ptable // Map cpu, curproc, ptable, kmem
c->gdt[SEG_KCPU] = SEG(STA_W, &c->cpu, 12, 0); c->gdt[SEG_KCPU] = SEG(STA_W, &c->cpu, 16, 0);
lgdt(c->gdt, sizeof(c->gdt)); lgdt(c->gdt, sizeof(c->gdt));
loadgs(SEG_KCPU << 3); loadgs(SEG_KCPU << 3);
...@@ -46,6 +47,7 @@ seginit(void) ...@@ -46,6 +47,7 @@ seginit(void)
cpu = c; cpu = c;
proc = 0; proc = 0;
ptable = &ptables[cpunum()]; ptable = &ptables[cpunum()];
kmem = &kmems[cpunum()];
} }
// Return the address of the PTE in page table pgdir // Return the address of the PTE in page table pgdir
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论