summaryrefslogtreecommitdiff
path: root/bio.c
diff options
context:
space:
mode:
authorFrans Kaashoek <[email protected]>2011-08-29 17:18:40 -0400
committerFrans Kaashoek <[email protected]>2011-08-29 17:18:40 -0400
commit1ddfbbb194e3aa668b33469eb547132a7a7f940a (patch)
tree41ad0ae10ef2743c6e9433e711358dede77ce041 /bio.c
parent22f7db5336cb20c82eb1ffa45c0ef63825442c95 (diff)
downloadxv6-labs-1ddfbbb194e3aa668b33469eb547132a7a7f940a.tar.gz
xv6-labs-1ddfbbb194e3aa668b33469eb547132a7a7f940a.tar.bz2
xv6-labs-1ddfbbb194e3aa668b33469eb547132a7a7f940a.zip
Revert "Introduce and use sleeplocks instead of BUSY flags"
My changes have a race with re-used bufs and the code doesn't seem to get shorter Keep the changes that fixed ip->off race This reverts commit 3a5fa7ed9020eaf8ab843a16d26db7393b2ec072. Conflicts: defs.h file.c file.h
Diffstat (limited to 'bio.c')
-rw-r--r--bio.c45
1 files changed, 22 insertions, 23 deletions
diff --git a/bio.c b/bio.c
index f11328d..6a3968b 100644
--- a/bio.c
+++ b/bio.c
@@ -13,7 +13,9 @@
// * Only one process at a time can use a buffer,
// so do not keep them longer than necessary.
//
-// The implementation uses two state flags internally:
+// The implementation uses three state flags internally:
+// * B_BUSY: the block has been returned from bread
+// and has not been passed back to brelse.
// * B_VALID: the buffer data has been initialized
// with the associated disk block contents.
// * B_DIRTY: the buffer data has been modified
@@ -49,8 +51,6 @@ binit(void)
b->next = bcache.head.next;
b->prev = &bcache.head;
b->dev = -1;
- initlock(&b->lock, "buf");
- initsleeplock(&b->sleeplock);
bcache.head.next->prev = b;
bcache.head.next = b;
}
@@ -58,43 +58,42 @@ binit(void)
// Look through buffer cache for sector on device dev.
// If not found, allocate fresh block.
-// In either case, return sleep-locked buffer.
+// In either case, return locked buffer.
static struct buf*
bget(uint dev, uint sector)
{
struct buf *b;
acquire(&bcache.lock);
+
+ loop:
// Try for cached block.
for(b = bcache.head.next; b != &bcache.head; b = b->next){
- acquire(&b->lock);
if(b->dev == dev && b->sector == sector){
- release(&bcache.lock);
- acquire_sleeplock(&b->sleeplock, &b->lock);
- release(&b->lock);
- return b;
+ if(!(b->flags & B_BUSY)){
+ b->flags |= B_BUSY;
+ release(&bcache.lock);
+ return b;
+ }
+ sleep(b, &bcache.lock);
+ goto loop;
}
- release(&b->lock);
}
// Allocate fresh block.
for(b = bcache.head.prev; b != &bcache.head; b = b->prev){
- acquire(&b->lock);
- if (!acquired_sleeplock(&b->sleeplock)) {
- release(&bcache.lock);
+ if((b->flags & B_BUSY) == 0){
b->dev = dev;
b->sector = sector;
- b->flags = 0;
- acquire_sleeplock(&b->sleeplock, &b->lock);
- release(&b->lock);
+ b->flags = B_BUSY;
+ release(&bcache.lock);
return b;
}
- release(&b->lock);
}
panic("bget: no buffers");
}
-// Return a locked buf with the contents of the indicated disk sector.
+// Return a B_BUSY buf with the contents of the indicated disk sector.
struct buf*
bread(uint dev, uint sector)
{
@@ -110,7 +109,7 @@ bread(uint dev, uint sector)
void
bwrite(struct buf *b)
{
- if(!acquired_sleeplock(&b->sleeplock))
+ if((b->flags & B_BUSY) == 0)
panic("bwrite");
b->flags |= B_DIRTY;
iderw(b);
@@ -120,11 +119,11 @@ bwrite(struct buf *b)
void
brelse(struct buf *b)
{
- if(!acquired_sleeplock(&b->sleeplock))
+ if((b->flags & B_BUSY) == 0)
panic("brelse");
acquire(&bcache.lock);
- acquire(&b->lock);
+
b->next->prev = b->prev;
b->prev->next = b->next;
b->next = bcache.head.next;
@@ -132,8 +131,8 @@ brelse(struct buf *b)
bcache.head.next->prev = b;
bcache.head.next = b;
- release_sleeplock(&b->sleeplock);
- release(&b->lock);
+ b->flags &= ~B_BUSY;
+ wakeup(b);
release(&bcache.lock);
}