Skip to content

Commit

Permalink
no more recursive locks
Browse files Browse the repository at this point in the history
wakeup1() assumes you hold proc_table_lock
sleep(chan, lock) provides atomic sleep-and-release to wait for condition
ugly code in swtch/scheduler to implement new sleep
fix lots of bugs in pipes, wait, and exit
fix bugs if timer interrupt goes off in schedule()
console locks per line, not per byte
  • Loading branch information
rtm committed Jul 15, 2006
1 parent d9872ff commit 46bbd72
Show file tree
Hide file tree
Showing 15 changed files with 229 additions and 102 deletions.
23 changes: 23 additions & 0 deletions Notes
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,26 @@ nasty hack to allow locks before first process,

race between release and sleep in sys_wait()
race between sys_exit waking up parent and setting state=ZOMBIE
race in pipe code when full/empty

lock order
per-pipe lock
proc_table_lock fd_table_lock kalloc_lock
console_lock

condition variable + mutex that protects it
proc * (for wait()), proc_table_lock
pipe structure, pipe lock

systematic way to test sleep races?
print something at the start of sleep?

do you have to be holding the mutex in order to call wakeup()?

should lock around printf, not putc

device interrupts don't clear FL_IF
so a recursive timer interrupt is possible

the sleep/swtch/schedule code that holds over a lock is ugly

39 changes: 29 additions & 10 deletions console.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
#include "spinlock.h"

struct spinlock console_lock;
int use_printf_lock = 0;
int paniced = 0;
int use_console_lock = 0;

/*
* copy console output to parallel port, which you can tell
Expand All @@ -23,15 +24,18 @@ lpt_putc(int c)
outb(0x378+2, 0x08);
}

void
cons_putc(int c)
static void
real_cons_putc(int c)
{
int crtport = 0x3d4; // io port of CGA
unsigned short *crt = (unsigned short *) 0xB8000; // base of CGA memory
int ind;

if(use_printf_lock)
acquire(&console_lock);
if(paniced){
cli();
while(1)
;
}

lpt_putc(c);

Expand Down Expand Up @@ -63,8 +67,15 @@ cons_putc(int c)
outb(crtport + 1, ind >> 8);
outb(crtport, 15);
outb(crtport + 1, ind);
}

if(use_printf_lock)
void
cons_putc(int c)
{
if(use_console_lock)
acquire(&console_lock);
real_cons_putc(c);
if(use_console_lock)
release(&console_lock);
}

Expand All @@ -91,7 +102,7 @@ printint(int xx, int base, int sgn)

while(i > 0){
i -= 1;
cons_putc(buf[i]);
real_cons_putc(buf[i]);
}
}

Expand All @@ -104,13 +115,16 @@ cprintf(char *fmt, ...)
int i, state = 0, c;
unsigned int *ap = (unsigned int *) &fmt + 1;

if(use_console_lock)
acquire(&console_lock);

for(i = 0; fmt[i]; i++){
c = fmt[i] & 0xff;
if(state == 0){
if(c == '%'){
state = '%';
} else {
cons_putc(c);
real_cons_putc(c);
}
} else if(state == '%'){
if(c == 'd'){
Expand All @@ -120,20 +134,25 @@ cprintf(char *fmt, ...)
printint(*ap, 16, 0);
ap++;
} else if(c == '%'){
cons_putc(c);
real_cons_putc(c);
}
state = 0;
}
}

if(use_console_lock)
release(&console_lock);
}

void
panic(char *s)
{
use_printf_lock = 0;
__asm __volatile("cli");
use_console_lock = 0;
cprintf("panic: ");
cprintf(s, 0);
cprintf("\n", 0);
paniced = 1; // freeze other CPU
while(1)
;
}
5 changes: 4 additions & 1 deletion defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ struct jmpbuf;
void setupsegs(struct proc *);
struct proc * newproc(void);
void swtch(int);
void sleep(void *);
struct spinlock;
void sleep(void *, struct spinlock *);
void wakeup(void *);
void scheduler(void);
void proc_exit(void);
Expand Down Expand Up @@ -65,6 +66,8 @@ int cpu(void);
struct spinlock;
void acquire(struct spinlock * lock);
void release(struct spinlock * lock);
void acquire1(struct spinlock * lock, struct proc *);
void release1(struct spinlock * lock, struct proc *);

// main.c
void load_icode(struct proc *p, uint8_t *binary, unsigned size);
Expand Down
2 changes: 1 addition & 1 deletion ide.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ ide_start_read(uint32_t secno, void *dst, unsigned nsecs)
panic("ide_start_read: nsecs too large");

while ((head + 1) % NREQUEST == tail)
sleep (&disk_channel);
sleep (&disk_channel, 0);

r = &request[head];
r->secno = secno;
Expand Down
4 changes: 2 additions & 2 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ extern char _binary_user1_start[], _binary_user1_size[];
extern char _binary_usertests_start[], _binary_usertests_size[];
extern char _binary_userfs_start[], _binary_userfs_size[];

extern use_printf_lock;
extern int use_console_lock;

int
main()
Expand All @@ -40,7 +40,7 @@ main()

mp_init(); // collect info about this machine

use_printf_lock = 1;
use_console_lock = 1;

cpus[cpu()].clis = 1; // cpu starts as if we had called cli()

Expand Down
19 changes: 12 additions & 7 deletions pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,17 @@ pipe_write(struct pipe *p, char *addr, int n)

for(i = 0; i < n; i++){
while(((p->writep + 1) % PIPESIZE) == p->readp){
if(p->readopen == 0)
if(p->readopen == 0){
release(&p->lock);
return -1;
release(&p->lock);
}
wakeup(&p->readp);
sleep(&p->writep);
acquire(&p->lock);
sleep(&p->writep, &p->lock);
}
p->data[p->writep] = addr[i];
p->writep = (p->writep + 1) % PIPESIZE;
}

release(&p->lock);
wakeup(&p->readp);
return i;
Expand All @@ -101,19 +102,23 @@ pipe_read(struct pipe *p, char *addr, int n)
{
int i;

acquire(&p->lock);

while(p->readp == p->writep){
if(p->writeopen == 0)
if(p->writeopen == 0){
release(&p->lock);
return 0;
sleep(&p->readp);
}
sleep(&p->readp, &p->lock);
}

acquire(&p->lock);
for(i = 0; i < n; i++){
if(p->readp == p->writep)
break;
addr[i] = p->data[p->readp];
p->readp = (p->readp + 1) % PIPESIZE;
}

release(&p->lock);
wakeup(&p->writep);
return i;
Expand Down
Loading

0 comments on commit 46bbd72

Please sign in to comment.