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

condvars

上级 0d948cbd
OBJS = \
bio.o\
condvar.o\
console.o\
exec.o\
file.o\
......
......@@ -25,6 +25,7 @@
#include "defs.h"
#include "param.h"
#include "spinlock.h"
#include "condvar.h"
#include "buf.h"
struct {
......@@ -53,6 +54,7 @@ binit(void)
b->dev = -1;
bcache.head.next->prev = b;
bcache.head.next = b;
initlock(&b->cv.lock, "bache");
}
}
......@@ -75,7 +77,7 @@ bget(uint dev, uint sector)
release(&bcache.lock);
return b;
}
sleep(b, &bcache.lock);
cv_sleep(&b->cv, &bcache.lock);
goto loop;
}
}
......@@ -132,7 +134,7 @@ brelse(struct buf *b)
bcache.head.next = b;
b->flags &= ~B_BUSY;
wakeup(b);
cv_wakeup(&b->cv);
release(&bcache.lock);
}
......
......@@ -5,6 +5,7 @@ struct buf {
struct buf *prev; // LRU cache list
struct buf *next;
struct buf *qnext; // disk queue
struct condvar cv;
uchar data[512];
};
#define B_BUSY 0x1 // buffer is locked by some process
......
#include "types.h"
#include "defs.h"
#include "param.h"
#include "x86.h"
#include "mmu.h"
#include "spinlock.h"
#include "condvar.h"
#include "proc.h"
void
cv_sleep(struct condvar *cv, struct spinlock *lk)
{
if(proc == 0)
panic("sleep");
if(lk == 0)
panic("sleep without lk");
// Must acquire cv_lock to avoid sleep/wakeup race
acquire(&cv->lock);
cprintf("cv_sleep: 0x%x\n", cv);
release(lk);
if (cv->waiters != 0)
panic("cv_sleep\n");
cv->waiters = proc; // XXX should be queue
delrun(proc);
acquire(&proc->lock);
release(&cv->lock);
proc->state = SLEEPING;
sched();
release(&proc->lock);
acquire(&cv->lock);
// Tidy up.
cv->waiters = 0;
// Reacquire original lock.
cprintf("acquire %s\n", lk->name);
acquire(lk);
release(&cv->lock);
}
void
cv_wakeup(struct condvar *cv)
{
acquire(&cv->lock);
if (cv->waiters != 0) {
cprintf("wakeup 0x%x %d\n", cv, cv->waiters->pid);
addrun(cv->waiters);
}
release(&cv->lock);
}
struct condvar {
char name[MAXNAME];
struct spinlock lock;
struct proc *waiters;
void *chan; // If non-zero, sleeping on chan
};
......@@ -7,6 +7,7 @@
#include "param.h"
#include "traps.h"
#include "spinlock.h"
#include "condvar.h"
#include "fs.h"
#include "file.h"
#include "mmu.h"
......@@ -173,6 +174,7 @@ consputc(int c)
#define INPUT_BUF 128
struct {
struct spinlock lock;
struct condvar cv;
char buf[INPUT_BUF];
uint r; // Read index
uint w; // Write index
......@@ -212,7 +214,7 @@ consoleintr(int (*getc)(void))
consputc(c);
if(c == '\n' || c == C('D') || input.e == input.r+INPUT_BUF){
input.w = input.e;
wakeup(&input.r);
cv_wakeup(&input.cv);
}
}
break;
......@@ -237,7 +239,7 @@ consoleread(struct inode *ip, char *dst, int n)
ilock(ip);
return -1;
}
sleep(&input.r, &input.lock);
cv_sleep(&input.cv, &input.lock);
}
c = input.buf[input.r++ % INPUT_BUF];
if(c == C('D')){ // EOF
......@@ -279,6 +281,7 @@ consoleinit(void)
{
initlock(&cons.lock, "console");
initlock(&input.lock, "input");
initlock(&input.cv.lock, "input");
devsw[CONSOLE].write = consolewrite;
devsw[CONSOLE].read = consoleread;
......
......@@ -5,6 +5,7 @@ struct inode;
struct pipe;
struct proc;
struct spinlock;
struct condvar;
struct stat;
// bio.c
......@@ -13,6 +14,10 @@ struct buf* bread(uint, uint);
void brelse(struct buf*);
void bwrite(struct buf*);
// condvar.c
void cv_sleep(struct condvar *cv, struct spinlock*);
void cv_wakeup(struct condvar *cv);
// console.c
void consoleinit(void);
void cprintf(char*, ...);
......@@ -93,7 +98,9 @@ int pipewrite(struct pipe*, char*, int);
//PAGEBREAK: 16
// proc.c
void addrun(struct proc *);
struct proc* copyproc(struct proc*);
void delrun(struct proc*);
void exit(void);
int fork(void);
int growproc(int);
......@@ -103,11 +110,11 @@ void procdump(int);
void procdumpall(void);
void scheduler(void) __attribute__((noreturn));
void sched(void);
void sleep(void*, struct spinlock*);
void userinit(void);
int wait(void);
void wakeup(void*);
void yield(void);
void wakeup(void*);
void sleep(void*, struct spinlock*);
// swtch.S
void swtch(struct context**, struct context*);
......
......@@ -2,6 +2,7 @@
#include "param.h"
#include "mmu.h"
#include "spinlock.h"
#include "condvar.h"
#include "proc.h"
#include "defs.h"
#include "x86.h"
......
......@@ -16,6 +16,7 @@
#include "stat.h"
#include "mmu.h"
#include "spinlock.h"
#include "condvar.h"
#include "proc.h"
#include "buf.h"
#include "fs.h"
......
......@@ -5,6 +5,7 @@
#include "param.h"
#include "mmu.h"
#include "spinlock.h"
#include "condvar.h"
#include "proc.h"
#include "x86.h"
#include "traps.h"
......@@ -48,8 +49,8 @@ ideinit(void)
initlock(&idelock, "ide");
picenable(IRQ_IDE);
// ioapicenable(IRQ_IDE, ncpu - 1);
ioapicenable(IRQ_IDE, 0);
ioapicenable(IRQ_IDE, ncpu - 1);
// ioapicenable(IRQ_IDE, 0);
idewait(0);
// Check if disk 1 is present
......@@ -109,7 +110,7 @@ ideintr(void)
// Wake process waiting for this buf.
b->flags |= B_VALID;
b->flags &= ~B_DIRTY;
wakeup(b);
cv_wakeup(&b->cv);
// Start disk on next buf in queue.
if(idequeue != 0)
......@@ -149,7 +150,7 @@ iderw(struct buf *b)
// Wait for request to finish.
// Assuming will not sleep too long: ignore proc->killed.
while((b->flags & (B_VALID|B_DIRTY)) != B_VALID){
sleep(b, &idelock);
cv_sleep(&b->cv, &idelock);
}
release(&idelock);
......
......@@ -7,6 +7,7 @@
#include "param.h"
#include "mmu.h"
#include "spinlock.h"
#include "condvar.h"
#include "proc.h"
#include "kalloc.h"
......
......@@ -3,6 +3,7 @@
#include "param.h"
#include "mmu.h"
#include "spinlock.h"
#include "condvar.h"
#include "proc.h"
#include "x86.h"
......
......@@ -9,6 +9,7 @@
#include "x86.h"
#include "mmu.h"
#include "spinlock.h"
#include "condvar.h"
#include "proc.h"
struct cpu cpus[NCPU];
......
......@@ -3,6 +3,7 @@
#include "param.h"
#include "mmu.h"
#include "spinlock.h"
#include "condvar.h"
#include "proc.h"
#include "fs.h"
#include "file.h"
......
......@@ -4,12 +4,12 @@
#include "mmu.h"
#include "x86.h"
#include "spinlock.h"
#include "condvar.h"
#include "proc.h"
struct ptable ptables[NCPU];
struct runq runqs[NCPU];
struct condvar condvars[NPROC];
struct spinlock lock_condvars;
struct condtab condtabs[NCPU];
static struct proc *initproc;
int nextpid = 1;
......@@ -31,14 +31,21 @@ pinit(void)
for (i = 0; i < NPROC; i++) {
initlock(&ptables[c].proc[i].lock, ptables[c].proc[i].name);
initlock(&ptables[c].proc[i].cv.lock, ptables[c].proc[i].name);
}
runqs[c].name[0] = (char) (c + '0');
safestrcpy(runqs[c].name+1, "runq", MAXNAME-1);
initlock(&runqs[c].lock, runqs[c].name);
condtabs[c].name[0] = (char) (c + '0');
safestrcpy(condtabs[c].name+1, "condtab", MAXNAME-1);
initlock(&condtabs[c].lock, condtabs[c].name);
for (i = 0; i < NPROC; i++) {
initlock(&condtabs[c].condtab[i].lock, condtabs[c].condtab[i].name);
}
}
initlock(&lock_condvars, "condvar");
}
//PAGEBREAK: 32
......@@ -105,10 +112,11 @@ addrun1(struct runq *rq, struct proc *p)
rq->runq = p;
}
static void
void
addrun(struct proc *p)
{
acquire(&runq->lock);
cprintf("%d: addrun %d\n", cpunum(), p->pid);
addrun1(runq, p);
release(&runq->lock);
}
......@@ -136,10 +144,11 @@ delrun1(struct runq *rq, struct proc *proc)
}
void
delrun(struct proc *proc)
delrun(struct proc *p)
{
acquire(&runq->lock);
delrun1(runq, proc);
cprintf("%d: delrun %d\n", cpunum(), p->pid);
delrun1(runq, p);
release(&runq->lock);
}
......@@ -272,15 +281,15 @@ exit(void)
release(&ptables[c].lock);
}
acquire(&proc->lock);
// Parent might be sleeping in wait().
wakeup(proc->parent);
cv_wakeup(&proc->parent->cv);
if (wakeupinit)
wakeup(initproc);
cv_wakeup(&initproc->cv);
delrun1(runq, proc);
acquire(&proc->lock);
delrun1(runq, proc); // XXX get lock on runq
// Jump into the scheduler, never to return.
proc->state = ZOMBIE;
......@@ -333,7 +342,7 @@ wait(void)
}
// Wait for children to exit. (See wakeup1 call in proc_exit.)
sleep(proc, &proc->lock);
cv_sleep(&proc->cv, &proc->lock);
release(&proc->lock);
}
......@@ -475,83 +484,7 @@ forkret(void)
// Return to "caller", actually trapret (see allocproc).
}
// Atomically release lock and sleep on chan.
// Reacquires lock when awakened.
void
sleep(void *chan, struct spinlock *lk)
{
int i;
if(proc == 0)
panic("sleep");
if(lk == 0)
panic("sleep without lk");
// Must acquire lock_condvar in order to
// change p->state and then call sched.
// Once we hold lock_condvar, we can be
// guaranteed that we won't miss any wakeup
// (wakeup runs with lock_condvar locked),
// so it's okay to release lk.
acquire(&lock_condvars);
release(lk);
// find a condvar and record sleeper
// XXX should we check if there is a condvar for chan?
for (i = 0; i < NPROC; i++) {
if (condvars[i].chan == 0) {
break;
}
}
if (i == NPROC)
panic("out of condvars");
// add sleeper
condvars[i].chan = chan;
condvars[i].waiters = proc;
// remove from runqueue
acquire(&proc->lock);
proc->state = SLEEPING;
delrun1(runq, proc);
release(&lock_condvars);
sched();
release(&proc->lock);
acquire(&lock_condvars);
// Tidy up.
condvars[i].chan = 0;
// Reacquire original lock.
cprintf("acquire %s\n", lk->name);
acquire(lk);
release(&lock_condvars);
}
// Wake up all processes sleeping on chan.
void
wakeup(void *chan)
{
int c;
acquire(&lock_condvars);
for (c = 0; c < NPROC; c++) {
if (condvars[c].chan == chan) {
addrun(condvars[c].waiters);
goto done;
}
}
// cprintf("wakeup on 0x%x; no chan; lost wakeup?\n", chan);
done:
release(&lock_condvars);
}
// Kill the process with the given pid.
// Process won't exit until it returns
......@@ -635,3 +568,19 @@ procdumpall(void)
procdump(c);
}
}
//// dead code
// Atomically release lock and sleep on chan.
// Reacquires lock when awakened.
void
sleep(void *chan, struct spinlock *lk)
{
panic("sleep");
}
// Wake up all processes sleeping on chan.
void
wakeup(void *chan)
{
}
......@@ -47,8 +47,8 @@ struct proc {
char name[16]; // Process name (debugging)
struct spinlock lock;
struct proc *runq;
struct proc *waiterq;
struct proc *childq;
struct condvar cv;
};
// Process memory is laid out contiguously, low addresses first:
......@@ -73,13 +73,9 @@ struct cpu {
struct ptable *ptable; // The per-core proc table
struct kmem *kmem; // The per-core proc table
struct runq *runq; // The per-core proc table
struct condtab *contab; // The per-core proc table
};
struct condvar {
struct spinlock lock;
struct proc *waiters;
void *chan; // If non-zero, sleeping on chan
};
struct runq {
char name[MAXNAME];
......@@ -94,9 +90,16 @@ struct ptable {
struct proc *runq;
};
struct condtab {
char name[MAXNAME];
struct spinlock lock;
struct condvar condtab[NPROC];
};
extern struct ptable ptables[NCPU];
extern struct cpu cpus[NCPU];
extern struct runq runqs[NCPU];
extern struct condtab condtabs[NCPU];
extern int ncpu;
// Per-CPU variables, holding pointers to the
......@@ -112,3 +115,4 @@ extern struct proc *proc asm("%gs:4"); // cpus[cpunum()].proc
extern struct ptable *ptable asm("%gs:8"); // &ptables[cpunum()]
extern struct kmem *kmem asm("%gs:12"); // &kmems[cpunum()]
extern struct runq *runq asm("%gs:16"); // &runqs[cpunum()]
extern struct condtab *condtab asm("%gs:20"); // &condtabs[cpunum()]
......@@ -6,6 +6,7 @@
#include "x86.h"
#include "mmu.h"
#include "spinlock.h"
#include "condvar.h"
#include "proc.h"
void
......
......@@ -3,6 +3,7 @@
#include "param.h"
#include "mmu.h"
#include "spinlock.h"
#include "condvar.h"
#include "proc.h"
#include "x86.h"
#include "syscall.h"
......
......@@ -4,6 +4,7 @@
#include "stat.h"
#include "mmu.h"
#include "spinlock.h"
#include "condvar.h"
#include "proc.h"
#include "fs.h"
#include "file.h"
......
......@@ -4,6 +4,7 @@
#include "param.h"
#include "mmu.h"
#include "spinlock.h"
#include "condvar.h"
#include "proc.h"
int
......
......@@ -3,6 +3,7 @@
#include "param.h"
#include "mmu.h"
#include "spinlock.h"
#include "condvar.h"
#include "proc.h"
#include "x86.h"
#include "traps.h"
......
......@@ -8,6 +8,7 @@
#include "fs.h"
#include "file.h"
#include "mmu.h"
#include "condvar.h"
#include "proc.h"
#include "x86.h"
......
......@@ -4,6 +4,7 @@
#include "x86.h"
#include "mmu.h"
#include "spinlock.h"
#include "condvar.h"
#include "proc.h"
#include "elf.h"
#include "kalloc.h"
......@@ -49,6 +50,7 @@ seginit(void)
ptable = &ptables[cpunum()];
kmem = &kmems[cpunum()];
runq = &runqs[cpunum()];
condtab = &condtabs[cpunum()];
}
// Return the address of the PTE in page table pgdir
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论