]> Devi Nivas Git - cs3210-lab0.git/commitdiff
Move retry loop/sleep/wakeup in bio.c into sleeping locks
authorFrans Kaashoek <kaashoek@mit.edu>
Mon, 12 Sep 2016 00:17:22 +0000 (20:17 -0400)
committerFrans Kaashoek <kaashoek@mit.edu>
Mon, 12 Sep 2016 00:17:22 +0000 (20:17 -0400)
bio.c
buf.h
defs.h

diff --git a/bio.c b/bio.c
index 67f85e0d410c52699341eac9885c41babee6a2a9..90dbcdc18a9b16e143e08aa1c1656d4668a3f74c 100644 (file)
--- a/bio.c
+++ b/bio.c
@@ -49,7 +49,6 @@ binit(void)
   for(b = bcache.buf; b < bcache.buf+NBUF; b++){
     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;
@@ -66,33 +65,33 @@ bget(uint dev, uint blockno)
 
   acquire(&bcache.lock);
 
-  //cprintf("bget %d\n", blockno);
- loop:
+  // cprintf("bget %d\n", blockno);
+  
   // Is the block already cached?
   for(b = bcache.head.next; b != &bcache.head; b = b->next){
     if(b->dev == dev && b->blockno == blockno){
-      if(!holdingsleep(&b->lock)) {
-        acquiresleep(&b->lock);
-        //cprintf("return buffer %p for blk %d\n", b - bcache.buf, blockno);
-        release(&bcache.lock);
-        return b;
-      }
-      sleep(b, &bcache.lock);
-      goto loop;
+      //cprintf("bget %d; get sleep lock for buffer %p\n", blockno, b - bcache.buf);
+      b->refcnt++;
+      release(&bcache.lock);
+      acquiresleep(&b->lock);
+      //cprintf("bget: return buffer %p for blk %d\n", b - bcache.buf, blockno);
+      return b;
     }
   }
 
-  // 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
   // hasn't yet committed the changes to the buffer.
   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->blockno = blockno;
-      b->flags = 0;  // XXX
-      acquiresleep(&b->lock);
-      //cprintf("return buffer %p for blk %d\n", b - bcache.buf, blockno);
+      b->flags = 0;
+      b->refcnt = 1;
       release(&bcache.lock);
+      acquiresleep(&b->lock);
+      // cprintf("bget: return buffer %p for blk %d\n", b - bcache.buf, blockno);
       return b;
     }
   }
@@ -116,7 +115,7 @@ bread(uint dev, uint blockno)
 void
 bwrite(struct buf *b)
 {
-  if(b->lock.locked == 0)
+  if(!holdingsleep(&b->lock))
     panic("bwrite");
   b->flags |= B_DIRTY;
   iderw(b);
@@ -127,20 +126,23 @@ bwrite(struct buf *b)
 void
 brelse(struct buf *b)
 {
-  if(b->lock.locked == 0)
+  if(!holdingsleep(&b->lock))
     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);
-  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);
 }
 //PAGEBREAK!
diff --git a/buf.h b/buf.h
index 0745be50919e4aa81d87891bfebcd8d9c6f482bd..3266495cf3d9841760c2a23209342005404c2520 100644 (file)
--- a/buf.h
+++ b/buf.h
@@ -3,6 +3,7 @@ struct buf {
   uint dev;
   uint blockno;
   struct sleeplock lock;
+  uint refcnt;
   struct buf *prev; // LRU cache list
   struct buf *next;
   struct buf *qnext; // disk queue
diff --git a/defs.h b/defs.h
index 300c75c664bdf49d374a2aa70c3173676c777c70..8f01b1fa1795213fcf2c5ae4e4780d0b70c3c23a 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -131,7 +131,7 @@ void            popcli(void);
 
 // sleeplock.c
 void            acquiresleep(struct sleeplock*);
-void            releasesleep(struct sleeplock*);
+void             releasesleep(struct sleeplock*);
 int             holdingsleep(struct sleeplock*);
 void            initsleeplock(struct sleeplock*, char*);