diff options
| author | Frans Kaashoek <kaashoek@mit.edu> | 2016-09-11 17:24:04 -0400 | 
|---|---|---|
| committer | Frans Kaashoek <kaashoek@mit.edu> | 2016-09-11 17:24:04 -0400 | 
| commit | 6670d3b5e084d9d900d2ea13e624e72e1e28f84c (patch) | |
| tree | 5ad8eb3dc3ba247c7dbe45ee082d1900853fd1e1 | |
| parent | 551c2f3576d34e4749a1165af07d90e21ad528be (diff) | |
| download | xv6-labs-6670d3b5e084d9d900d2ea13e624e72e1e28f84c.tar.gz xv6-labs-6670d3b5e084d9d900d2ea13e624e72e1e28f84c.tar.bz2 xv6-labs-6670d3b5e084d9d900d2ea13e624e72e1e28f84c.zip | |
Straight replacement of B_BUSY with a sleeping lock.
| -rw-r--r-- | Makefile | 1 | ||||
| -rw-r--r-- | bio.c | 37 | ||||
| -rw-r--r-- | buf.h | 2 | ||||
| -rw-r--r-- | defs.h | 7 | ||||
| -rw-r--r-- | exec.c | 3 | ||||
| -rw-r--r-- | fs.c | 10 | ||||
| -rw-r--r-- | ide.c | 5 | ||||
| -rw-r--r-- | log.c | 1 | 
8 files changed, 45 insertions, 21 deletions
| @@ -15,6 +15,7 @@ OBJS = \  	picirq.o\  	pipe.o\  	proc.o\ +	sleeplock.o\  	spinlock.o\  	string.o\  	swtch.o\ @@ -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); @@ -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 @@ -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); @@ -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: @@ -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);    } @@ -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) @@ -2,6 +2,7 @@  #include "defs.h"  #include "param.h"  #include "spinlock.h" +#include "sleeplock.h"  #include "fs.h"  #include "buf.h" | 
