Move retry loop/sleep/wakeup in bio.c into sleeping locks
This commit is contained in:
parent
6670d3b5e0
commit
2adb7c21dc
56
bio.c
56
bio.c
|
@ -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
1
buf.h
|
@ -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
2
defs.h
|
@ -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*);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue