summaryrefslogtreecommitdiff
path: root/bio.c
diff options
context:
space:
mode:
authorFrans Kaashoek <[email protected]>2016-09-11 17:24:04 -0400
committerFrans Kaashoek <[email protected]>2016-09-11 17:24:04 -0400
commit6670d3b5e084d9d900d2ea13e624e72e1e28f84c (patch)
tree5ad8eb3dc3ba247c7dbe45ee082d1900853fd1e1 /bio.c
parent551c2f3576d34e4749a1165af07d90e21ad528be (diff)
downloadxv6-labs-6670d3b5e084d9d900d2ea13e624e72e1e28f84c.tar.gz
xv6-labs-6670d3b5e084d9d900d2ea13e624e72e1e28f84c.tar.bz2
xv6-labs-6670d3b5e084d9d900d2ea13e624e72e1e28f84c.zip
Straight replacement of B_BUSY with a sleeping lock.
Diffstat (limited to 'bio.c')
-rw-r--r--bio.c37
1 files changed, 20 insertions, 17 deletions
diff --git a/bio.c b/bio.c
index 6c19a64..67f85e0 100644
--- a/bio.c
+++ b/bio.c
@@ -13,9 +13,7 @@
// * Only one process at a time can use a buffer,
// so do not keep them longer than necessary.
//
-// The implementation uses three state flags internally:
-// * B_BUSY: the block has been returned from bread
-// and has not been passed back to brelse.
+// The implementation uses two state flags internally:
// * B_VALID: the buffer data has been read from the disk.
// * B_DIRTY: the buffer data has been modified
// and needs to be written to disk.
@@ -24,6 +22,7 @@
#include "defs.h"
#include "param.h"
#include "spinlock.h"
+#include "sleeplock.h"
#include "fs.h"
#include "buf.h"
@@ -51,6 +50,7 @@ binit(void)
b->next = bcache.head.next;
b->prev = &bcache.head;
b->dev = -1;
+ initsleeplock(&b->lock, "buffer");
bcache.head.next->prev = b;
bcache.head.next = b;
}
@@ -58,7 +58,7 @@ binit(void)
// Look through buffer cache for block on device dev.
// If not found, allocate a buffer.
-// In either case, return B_BUSY buffer.
+// In either case, return locked buffer.
static struct buf*
bget(uint dev, uint blockno)
{
@@ -66,12 +66,14 @@ bget(uint dev, uint blockno)
acquire(&bcache.lock);
+ //cprintf("bget %d\n", blockno);
loop:
// Is the block already cached?
for(b = bcache.head.next; b != &bcache.head; b = b->next){
if(b->dev == dev && b->blockno == blockno){
- if(!(b->flags & B_BUSY)){
- b->flags |= B_BUSY;
+ if(!holdingsleep(&b->lock)) {
+ acquiresleep(&b->lock);
+ //cprintf("return buffer %p for blk %d\n", b - bcache.buf, blockno);
release(&bcache.lock);
return b;
}
@@ -80,14 +82,16 @@ bget(uint dev, uint blockno)
}
}
- // Not cached; recycle some non-busy and clean buffer.
- // "clean" because B_DIRTY and !B_BUSY means log.c
+ // Not cached; recycle some non-locked and clean buffer.
+ // "clean" because B_DIRTY and not locked means log.c
// hasn't yet committed the changes to the buffer.
for(b = bcache.head.prev; b != &bcache.head; b = b->prev){
- if((b->flags & B_BUSY) == 0 && (b->flags & B_DIRTY) == 0){
+ if(!holdingsleep(&b->lock) && (b->flags & B_DIRTY) == 0){
b->dev = dev;
b->blockno = blockno;
- b->flags = B_BUSY;
+ b->flags = 0; // XXX
+ acquiresleep(&b->lock);
+ //cprintf("return buffer %p for blk %d\n", b - bcache.buf, blockno);
release(&bcache.lock);
return b;
}
@@ -95,7 +99,7 @@ bget(uint dev, uint blockno)
panic("bget: no buffers");
}
-// Return a B_BUSY buf with the contents of the indicated block.
+// Return a locked buf with the contents of the indicated block.
struct buf*
bread(uint dev, uint blockno)
{
@@ -108,22 +112,22 @@ bread(uint dev, uint blockno)
return b;
}
-// Write b's contents to disk. Must be B_BUSY.
+// Write b's contents to disk. Must be locked.
void
bwrite(struct buf *b)
{
- if((b->flags & B_BUSY) == 0)
+ if(b->lock.locked == 0)
panic("bwrite");
b->flags |= B_DIRTY;
iderw(b);
}
-// Release a B_BUSY buffer.
+// Release a locked buffer.
// Move to the head of the MRU list.
void
brelse(struct buf *b)
{
- if((b->flags & B_BUSY) == 0)
+ if(b->lock.locked == 0)
panic("brelse");
acquire(&bcache.lock);
@@ -134,8 +138,7 @@ brelse(struct buf *b)
b->prev = &bcache.head;
bcache.head.next->prev = b;
bcache.head.next = b;
-
- b->flags &= ~B_BUSY;
+ releasesleep(&b->lock);
wakeup(b);
release(&bcache.lock);