Move retry loop/sleep/wakeup in bio.c into sleeping locks

This commit is contained in:
Frans Kaashoek 2016-09-11 20:17:22 -04:00
parent 6670d3b5e0
commit 2adb7c21dc
3 changed files with 31 additions and 28 deletions

56
bio.c
View file

@ -49,7 +49,6 @@ binit(void)
for(b = bcache.buf; b < bcache.buf+NBUF; b++){ for(b = bcache.buf; b < bcache.buf+NBUF; b++){
b->next = bcache.head.next; b->next = bcache.head.next;
b->prev = &bcache.head; b->prev = &bcache.head;
b->dev = -1;
initsleeplock(&b->lock, "buffer"); initsleeplock(&b->lock, "buffer");
bcache.head.next->prev = b; bcache.head.next->prev = b;
bcache.head.next = b; bcache.head.next = b;
@ -66,33 +65,33 @@ bget(uint dev, uint blockno)
acquire(&bcache.lock); acquire(&bcache.lock);
//cprintf("bget %d\n", blockno); // cprintf("bget %d\n", blockno);
loop:
// Is the block already cached? // Is the block already cached?
for(b = bcache.head.next; b != &bcache.head; b = b->next){ for(b = bcache.head.next; b != &bcache.head; b = b->next){
if(b->dev == dev && b->blockno == blockno){ if(b->dev == dev && b->blockno == blockno){
if(!holdingsleep(&b->lock)) { //cprintf("bget %d; get sleep lock for buffer %p\n", blockno, b - bcache.buf);
acquiresleep(&b->lock); b->refcnt++;
//cprintf("return buffer %p for blk %d\n", b - bcache.buf, blockno); release(&bcache.lock);
release(&bcache.lock); acquiresleep(&b->lock);
return b; //cprintf("bget: return buffer %p for blk %d\n", b - bcache.buf, blockno);
} return b;
sleep(b, &bcache.lock);
goto loop;
} }
} }
// Not cached; recycle some non-locked and clean buffer. // Not cached; recycle some unused buffer and clean buffer
// "clean" because B_DIRTY and not locked means log.c // "clean" because B_DIRTY and not locked means log.c
// hasn't yet committed the changes to the buffer. // hasn't yet committed the changes to the buffer.
for(b = bcache.head.prev; b != &bcache.head; b = b->prev){ for(b = bcache.head.prev; b != &bcache.head; b = b->prev){
if(!holdingsleep(&b->lock) && (b->flags & B_DIRTY) == 0){ if(b->refcnt == 0 && (b->flags & B_DIRTY) == 0) {
// cprintf("bget %d; use %p for %d\n", b - bcache.buf, blockno);
b->dev = dev; b->dev = dev;
b->blockno = blockno; b->blockno = blockno;
b->flags = 0; // XXX b->flags = 0;
acquiresleep(&b->lock); b->refcnt = 1;
//cprintf("return buffer %p for blk %d\n", b - bcache.buf, blockno);
release(&bcache.lock); release(&bcache.lock);
acquiresleep(&b->lock);
// cprintf("bget: return buffer %p for blk %d\n", b - bcache.buf, blockno);
return b; return b;
} }
} }
@ -116,7 +115,7 @@ bread(uint dev, uint blockno)
void void
bwrite(struct buf *b) bwrite(struct buf *b)
{ {
if(b->lock.locked == 0) if(!holdingsleep(&b->lock))
panic("bwrite"); panic("bwrite");
b->flags |= B_DIRTY; b->flags |= B_DIRTY;
iderw(b); iderw(b);
@ -127,20 +126,23 @@ bwrite(struct buf *b)
void void
brelse(struct buf *b) brelse(struct buf *b)
{ {
if(b->lock.locked == 0) if(!holdingsleep(&b->lock))
panic("brelse"); panic("brelse");
acquire(&bcache.lock);
b->next->prev = b->prev;
b->prev->next = b->next;
b->next = bcache.head.next;
b->prev = &bcache.head;
bcache.head.next->prev = b;
bcache.head.next = b;
releasesleep(&b->lock); releasesleep(&b->lock);
wakeup(b);
acquire(&bcache.lock);
b->refcnt--;
if (b->refcnt == 0) {
// no one is waiting for it.
b->next->prev = b->prev;
b->prev->next = b->next;
b->next = bcache.head.next;
b->prev = &bcache.head;
bcache.head.next->prev = b;
bcache.head.next = b;
}
release(&bcache.lock); release(&bcache.lock);
} }
//PAGEBREAK! //PAGEBREAK!

1
buf.h
View file

@ -3,6 +3,7 @@ struct buf {
uint dev; uint dev;
uint blockno; uint blockno;
struct sleeplock lock; struct sleeplock lock;
uint refcnt;
struct buf *prev; // LRU cache list struct buf *prev; // LRU cache list
struct buf *next; struct buf *next;
struct buf *qnext; // disk queue struct buf *qnext; // disk queue

2
defs.h
View file

@ -131,7 +131,7 @@ void popcli(void);
// sleeplock.c // sleeplock.c
void acquiresleep(struct sleeplock*); void acquiresleep(struct sleeplock*);
void releasesleep(struct sleeplock*); void releasesleep(struct sleeplock*);
int holdingsleep(struct sleeplock*); int holdingsleep(struct sleeplock*);
void initsleeplock(struct sleeplock*, char*); void initsleeplock(struct sleeplock*, char*);