Skip to content

Commit

Permalink
Straight replacement of B_BUSY with a sleeping lock.
Browse files Browse the repository at this point in the history
  • Loading branch information
kaashoek committed Sep 11, 2016
1 parent 551c2f3 commit 6670d3b
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 21 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ OBJS = \
picirq.o\
pipe.o\
proc.o\
sleeplock.o\
spinlock.o\
string.o\
swtch.o\
Expand Down
37 changes: 20 additions & 17 deletions bio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -24,6 +22,7 @@
#include "defs.h"
#include "param.h"
#include "spinlock.h"
#include "sleeplock.h"
#include "fs.h"
#include "buf.h"

Expand Down Expand Up @@ -51,27 +50,30 @@ 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;
}
}

// 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)
{
struct buf *b;

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;
}
Expand All @@ -80,22 +82,24 @@ 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;
}
}
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)
{
Expand All @@ -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);
Expand All @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion buf.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

7 changes: 7 additions & 0 deletions defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ struct pipe;
struct proc;
struct rtcdate;
struct spinlock;
struct sleeplock;
struct stat;
struct superblock;

Expand Down Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -98,6 +100,7 @@ exec(char *path, char **argv)
proc->tf->esp = sp;
switchuvm(proc);
freevm(oldpgdir);
cprintf("exec succeeded\n");
return 0;

bad:
Expand Down
10 changes: 9 additions & 1 deletion fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand Down
5 changes: 3 additions & 2 deletions ide.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "x86.h"
#include "traps.h"
#include "spinlock.h"
#include "sleeplock.h"
#include "fs.h"
#include "buf.h"

Expand Down Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions log.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "defs.h"
#include "param.h"
#include "spinlock.h"
#include "sleeplock.h"
#include "fs.h"
#include "buf.h"

Expand Down

0 comments on commit 6670d3b

Please sign in to comment.