]> Devi Nivas Git - cs3210-lab0.git/commitdiff
Straight replacement of B_BUSY with a sleeping lock.
authorFrans Kaashoek <kaashoek@mit.edu>
Sun, 11 Sep 2016 21:24:04 +0000 (17:24 -0400)
committerFrans Kaashoek <kaashoek@mit.edu>
Sun, 11 Sep 2016 21:24:04 +0000 (17:24 -0400)
Makefile
bio.c
buf.h
defs.h
exec.c
fs.c
ide.c
log.c

index a635b649c18e945f76835626da1d013b24eb73c5..84faa486e809c41ff16403ee2125c41ae46f26c6 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -15,6 +15,7 @@ OBJS = \
        picirq.o\
        pipe.o\
        proc.o\
+       sleeplock.o\
        spinlock.o\
        string.o\
        swtch.o\
diff --git a/bio.c b/bio.c
index 6c19a64750ae9f63b1d72be77d080b2ee0e19011..67f85e0d410c52699341eac9885c41babee6a2a9 100644 (file)
--- 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);
diff --git a/buf.h b/buf.h
index f18fd87686e15a2a1abdf77eb10f5fa50145e10a..0745be50919e4aa81d87891bfebcd8d9c6f482bd 100644 (file)
--- a/buf.h
+++ b/buf.h
@@ -2,12 +2,12 @@ struct buf {
   int flags;
   uint dev;
   uint blockno;
+  struct sleeplock lock;
   struct buf *prev; // LRU cache list
   struct buf *next;
   struct buf *qnext; // disk queue
   uchar data[BSIZE];
 };
-#define B_BUSY  0x1  // buffer is locked by some process
 #define B_VALID 0x2  // buffer has been read from disk
 #define B_DIRTY 0x4  // buffer needs to be written to disk
 
diff --git a/defs.h b/defs.h
index 34ed633ac02e2cfbe74d88c234ab24fd6773f5c0..300c75c664bdf49d374a2aa70c3173676c777c70 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -6,6 +6,7 @@ struct pipe;
 struct proc;
 struct rtcdate;
 struct spinlock;
+struct sleeplock;
 struct stat;
 struct superblock;
 
@@ -128,6 +129,12 @@ void            release(struct spinlock*);
 void            pushcli(void);
 void            popcli(void);
 
+// sleeplock.c
+void            acquiresleep(struct sleeplock*);
+void            releasesleep(struct sleeplock*);
+int             holdingsleep(struct sleeplock*);
+void            initsleeplock(struct sleeplock*, char*);
+
 // string.c
 int             memcmp(const void*, const void*, uint);
 void*           memmove(void*, const void*, uint);
diff --git a/exec.c b/exec.c
index d56ee1d5f8f9733a051a76b0e74ebb36a867ff2e..e968d2ffa12d30d60d7e12007cbc94d90ec8a9c1 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -19,6 +19,8 @@ exec(char *path, char **argv)
   pde_t *pgdir, *oldpgdir;
 
   begin_op();
+
+  cprintf("exec %s\n", path);
   if((ip = namei(path)) == 0){
     end_op();
     return -1;
@@ -98,6 +100,7 @@ exec(char *path, char **argv)
   proc->tf->esp = sp;
   switchuvm(proc);
   freevm(oldpgdir);
+  cprintf("exec succeeded\n");
   return 0;
 
  bad:
diff --git a/fs.c b/fs.c
index 6887dbc432175e2244798d90b1d0e9abe40b20d6..26a0b3e5791a14229ad822a4aa7191036ee773cf 100644 (file)
--- a/fs.c
+++ b/fs.c
@@ -16,6 +16,7 @@
 #include "mmu.h"
 #include "proc.h"
 #include "spinlock.h"
+#include "sleeplock.h"
 #include "fs.h"
 #include "buf.h"
 #include "file.h"
@@ -167,7 +168,7 @@ iinit(int dev)
   initlock(&icache.lock, "icache");
   readsb(dev, &sb);
   cprintf("sb: size %d nblocks %d ninodes %d nlog %d logstart %d\
         inodestart %d bmap start %d\n", sb.size, sb.nblocks,
+ inodestart %d bmap start %d\n", sb.size, sb.nblocks,
           sb.ninodes, sb.nlog, sb.logstart, sb.inodestart,
           sb.bmapstart);
 }
@@ -455,6 +456,13 @@ readi(struct inode *ip, char *dst, uint off, uint n)
   for(tot=0; tot<n; tot+=m, off+=m, dst+=m){
     bp = bread(ip->dev, bmap(ip, off/BSIZE));
     m = min(n - tot, BSIZE - off%BSIZE);
+    /*
+    cprintf("data off %d:\n", off);
+    for (int j = 0; j < min(m, 10); j++) {
+      cprintf("%x ", bp->data[off%BSIZE+j]);
+    }
+    cprintf("\n");
+    */
     memmove(dst, bp->data + off%BSIZE, m);
     brelse(bp);
   }
diff --git a/ide.c b/ide.c
index 7fad55d24d3e24b99885c2fc7241519e09052cfd..b3112b9ad6038e37859955f97255f509e8845710 100644 (file)
--- a/ide.c
+++ b/ide.c
@@ -9,6 +9,7 @@
 #include "x86.h"
 #include "traps.h"
 #include "spinlock.h"
+#include "sleeplock.h"
 #include "fs.h"
 #include "buf.h"
 
@@ -139,8 +140,8 @@ iderw(struct buf *b)
 {
   struct buf **pp;
 
-  if(!(b->flags & B_BUSY))
-    panic("iderw: buf not busy");
+  if(!holdingsleep(&b->lock))
+    panic("iderw: buf not locked");
   if((b->flags & (B_VALID|B_DIRTY)) == B_VALID)
     panic("iderw: nothing to do");
   if(b->dev != 0 && !havedisk1)
diff --git a/log.c b/log.c
index a2f1b5700a48ee0576208d3842d9590f0036c8d2..9ba3cedba678f5844df67d523d4fdc754c82831e 100644 (file)
--- a/log.c
+++ b/log.c
@@ -2,6 +2,7 @@
 #include "defs.h"
 #include "param.h"
 #include "spinlock.h"
+#include "sleeplock.h"
 #include "fs.h"
 #include "buf.h"