diff options
| author | Frans Kaashoek <kaashoek@Frans-Kaashoeks-MacBook-Pro.local> | 2011-08-26 10:08:29 -0400 | 
|---|---|---|
| committer | Frans Kaashoek <kaashoek@Frans-Kaashoeks-MacBook-Pro.local> | 2011-08-26 10:08:29 -0400 | 
| commit | 3a5fa7ed9020eaf8ab843a16d26db7393b2ec072 (patch) | |
| tree | bfa4ad4ae03d7d21796bacaa7eab8e3d3e4ab365 /bio.c | |
| parent | 8a9b6dbd4468f6312f1d07226a623879f970bd4b (diff) | |
| download | xv6-labs-3a5fa7ed9020eaf8ab843a16d26db7393b2ec072.tar.gz xv6-labs-3a5fa7ed9020eaf8ab843a16d26db7393b2ec072.tar.bz2 xv6-labs-3a5fa7ed9020eaf8ab843a16d26db7393b2ec072.zip | |
Introduce and use sleeplocks instead of BUSY flags
Remove I_BUSY, B_BUSY, and intrans defs and usages
One spinlock per buf to avoid ugly loop in bget
fix race in filewrite (don't update f->off after releasing lock)
Diffstat (limited to 'bio.c')
| -rw-r--r-- | bio.c | 45 | 
1 files changed, 23 insertions, 22 deletions
| @@ -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 initialized  //     with the associated disk block contents.  // * B_DIRTY: the buffer data has been modified @@ -51,6 +49,8 @@ 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,42 +58,43 @@ binit(void)  // Look through buffer cache for sector on device dev.  // If not found, allocate fresh block. -// In either case, return locked buffer. +// In either case, return sleep-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){ -      if(!(b->flags & B_BUSY)){ -        b->flags |= B_BUSY; -        release(&bcache.lock); -        return b; -      } -      sleep(b, &bcache.lock); -      goto loop; +      release(&bcache.lock); +      acquire_sleeplock(&b->sleeplock, &b->lock); +      release(&b->lock); +      return b;      } +    release(&b->lock);    }    // Allocate fresh block.    for(b = bcache.head.prev; b != &bcache.head; b = b->prev){ -    if((b->flags & B_BUSY) == 0){ +    acquire(&b->lock); +    if (!acquired_sleeplock(&b->sleeplock)) { +      release(&bcache.lock);        b->dev = dev;        b->sector = sector; -      b->flags = B_BUSY; -      release(&bcache.lock); +      b->flags = 0; +      acquire_sleeplock(&b->sleeplock, &b->lock); +      release(&b->lock);        return b;      } +    release(&b->lock);    }    panic("bget: no buffers");  } -// Return a B_BUSY buf with the contents of the indicated disk sector. +// Return a locked buf with the contents of the indicated disk sector.  struct buf*  bread(uint dev, uint sector)  { @@ -109,7 +110,7 @@ bread(uint dev, uint sector)  void  bwrite(struct buf *b)  { -  if((b->flags & B_BUSY) == 0) +  if(!acquired_sleeplock(&b->sleeplock))      panic("bwrite");    b->flags |= B_DIRTY;    iderw(b); @@ -119,11 +120,11 @@ bwrite(struct buf *b)  void  brelse(struct buf *b)  { -  if((b->flags & B_BUSY) == 0) +  if(!acquired_sleeplock(&b->sleeplock))      panic("brelse");    acquire(&bcache.lock); - +  acquire(&b->lock);    b->next->prev = b->prev;    b->prev->next = b->next;    b->next = bcache.head.next; @@ -131,8 +132,8 @@ brelse(struct buf *b)    bcache.head.next->prev = b;    bcache.head.next = b; -  b->flags &= ~B_BUSY; -  wakeup(b); +  release_sleeplock(&b->sleeplock); +  release(&b->lock);    release(&bcache.lock);  } | 
