Another attempt at the bio.c comment.
Rename B_WRITE to B_DIRTY and then let ide.c maintain the B_VALID and B_DIRTY flags.
This commit is contained in:
parent
efc12b8e61
commit
d003d232fc
3 changed files with 36 additions and 39 deletions
48
bio.c
48
bio.c
|
@ -1,27 +1,25 @@
|
||||||
// Buffer cache.
|
// Buffer cache.
|
||||||
//
|
//
|
||||||
// The buffer cache is a linked list of buf structures
|
// The buffer cache is a linked list of buf structures holding
|
||||||
// holding cached copies of disk block contents.
|
// cached copies of disk block contents. Caching disk blocks
|
||||||
// Each buf has two state bits B_BUSY and B_VALID.
|
// in memory reduces the number of disk reads and also provides
|
||||||
// If B_BUSY is set, it means that some code is currently
|
// a synchronization point for disk blocks used by multiple processes.
|
||||||
// using buf, so other code is not allowed to use it.
|
|
||||||
// To wait for a buffer that is B_BUSY, sleep on buf.
|
|
||||||
// (See bget below.)
|
|
||||||
//
|
//
|
||||||
// If B_VALID is set, it means that the sector in b->data is
|
// Interface:
|
||||||
// the same as on the disk. If B_VALID is not set, the contents
|
// * To get a buffer for a particular disk block, call bread.
|
||||||
// of buf must be initialized, often by calling bread,
|
// * After changing buffer data, call bwrite to flush it to disk.
|
||||||
// before being used.
|
// * When done with the buffer, call brelse.
|
||||||
|
// * Do not use the buffer after calling brelse.
|
||||||
|
// * Only one process at a time can use a buffer,
|
||||||
|
// so do not keep them longer than necessary.
|
||||||
//
|
//
|
||||||
// After making changes to a buf's memory, call bwrite to flush
|
// The implementation uses three state flags internally:
|
||||||
// the changes out to disk, to keep the disk and memory copies
|
// * B_BUSY: the block has been returned from bread
|
||||||
// in sync.
|
// and has not been passed back to brelse.
|
||||||
//
|
// * B_VALID: the buffer data has been initialized
|
||||||
// When finished with a buffer, call brelse to release the buffer
|
// with the associated disk block contents.
|
||||||
// (i.e., clear B_BUSY), so that others can access it.
|
// * B_DIRTY: the buffer data has been modified
|
||||||
//
|
// and needs to be written to disk.
|
||||||
// Bufs that are not B_BUSY are fair game for reuse for other
|
|
||||||
// disk blocks. It is not allowed to use a buf after calling brelse.
|
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "param.h"
|
#include "param.h"
|
||||||
|
@ -103,13 +101,8 @@ bread(uint dev, uint sector)
|
||||||
struct buf *b;
|
struct buf *b;
|
||||||
|
|
||||||
b = bget(dev, sector);
|
b = bget(dev, sector);
|
||||||
if(b->flags & B_VALID)
|
if(!(b->flags & B_VALID))
|
||||||
return b;
|
|
||||||
|
|
||||||
b->flags &= ~B_WRITE;
|
|
||||||
ide_rw(b);
|
ide_rw(b);
|
||||||
b->flags |= B_VALID;
|
|
||||||
|
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,9 +112,8 @@ bwrite(struct buf *b)
|
||||||
{
|
{
|
||||||
if((b->flags & B_BUSY) == 0)
|
if((b->flags & B_BUSY) == 0)
|
||||||
panic("bwrite");
|
panic("bwrite");
|
||||||
b->flags |= B_WRITE;
|
b->flags |= B_DIRTY;
|
||||||
ide_rw(b);
|
ide_rw(b);
|
||||||
b->flags |= B_VALID;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release the buffer buf.
|
// Release the buffer buf.
|
||||||
|
|
6
buf.h
6
buf.h
|
@ -5,9 +5,9 @@ struct buf {
|
||||||
struct buf *prev; // LRU cache list
|
struct buf *prev; // LRU cache list
|
||||||
struct buf *next;
|
struct buf *next;
|
||||||
struct buf *qnext; // disk queue
|
struct buf *qnext; // disk queue
|
||||||
int done;
|
|
||||||
uchar data[512];
|
uchar data[512];
|
||||||
};
|
};
|
||||||
#define B_BUSY 0x1 // buffer is locked by some process
|
#define B_BUSY 0x1 // buffer is locked by some process
|
||||||
#define B_VALID 0x2 // buffer contains the data of the sector
|
#define B_VALID 0x2 // buffer has been read from disk
|
||||||
#define B_WRITE 0x4 // asking device driver to write, else read
|
#define B_DIRTY 0x4 // buffer needs to be written to disk
|
||||||
|
|
||||||
|
|
17
ide.c
17
ide.c
|
@ -78,7 +78,7 @@ ide_start_request(struct buf *b)
|
||||||
outb(0x1f4, (b->sector >> 8) & 0xff);
|
outb(0x1f4, (b->sector >> 8) & 0xff);
|
||||||
outb(0x1f5, (b->sector >> 16) & 0xff);
|
outb(0x1f5, (b->sector >> 16) & 0xff);
|
||||||
outb(0x1f6, 0xE0 | ((b->dev&1)<<4) | ((b->sector>>24)&0x0f));
|
outb(0x1f6, 0xE0 | ((b->dev&1)<<4) | ((b->sector>>24)&0x0f));
|
||||||
if(b->flags & B_WRITE){
|
if(b->flags & B_DIRTY){
|
||||||
outb(0x1f7, IDE_CMD_WRITE);
|
outb(0x1f7, IDE_CMD_WRITE);
|
||||||
outsl(0x1f0, b->data, 512/4);
|
outsl(0x1f0, b->data, 512/4);
|
||||||
}else{
|
}else{
|
||||||
|
@ -100,11 +100,12 @@ ide_intr(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read data if needed.
|
// Read data if needed.
|
||||||
if((b->flags & B_WRITE) == 0 && ide_wait_ready(1) >= 0)
|
if(!(b->flags & B_DIRTY) && ide_wait_ready(1) >= 0)
|
||||||
insl(0x1f0, b->data, 512/4);
|
insl(0x1f0, b->data, 512/4);
|
||||||
|
|
||||||
// Wake process waiting for this buf.
|
// Wake process waiting for this buf.
|
||||||
b->done = 1;
|
b->flags |= B_VALID;
|
||||||
|
b->flags &= ~B_DIRTY;
|
||||||
wakeup(b);
|
wakeup(b);
|
||||||
|
|
||||||
// Start disk on next buf in queue.
|
// Start disk on next buf in queue.
|
||||||
|
@ -115,7 +116,9 @@ ide_intr(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
//PAGEBREAK!
|
//PAGEBREAK!
|
||||||
// Queue a disk operation and wait for it to finish.
|
// Sync buf with disk.
|
||||||
|
// If B_DIRTY is set, write buf to disk, clear B_DIRTY, set B_VALID.
|
||||||
|
// Else if B_VALID is not set, read buf from disk, set B_VALID.
|
||||||
void
|
void
|
||||||
ide_rw(struct buf *b)
|
ide_rw(struct buf *b)
|
||||||
{
|
{
|
||||||
|
@ -123,13 +126,14 @@ ide_rw(struct buf *b)
|
||||||
|
|
||||||
if(!(b->flags & B_BUSY))
|
if(!(b->flags & B_BUSY))
|
||||||
panic("ide_rw: buf not busy");
|
panic("ide_rw: buf not busy");
|
||||||
|
if((b->flags & (B_VALID|B_DIRTY)) == B_VALID)
|
||||||
|
panic("ide_rw: nothing to do");
|
||||||
if(b->dev != 0 && !disk_1_present)
|
if(b->dev != 0 && !disk_1_present)
|
||||||
panic("ide disk 1 not present");
|
panic("ide disk 1 not present");
|
||||||
|
|
||||||
acquire(&ide_lock);
|
acquire(&ide_lock);
|
||||||
|
|
||||||
// Append b to ide_queue.
|
// Append b to ide_queue.
|
||||||
b->done = 0;
|
|
||||||
b->qnext = 0;
|
b->qnext = 0;
|
||||||
for(pp=&ide_queue; *pp; pp=&(*pp)->qnext)
|
for(pp=&ide_queue; *pp; pp=&(*pp)->qnext)
|
||||||
;
|
;
|
||||||
|
@ -140,7 +144,8 @@ ide_rw(struct buf *b)
|
||||||
ide_start_request(b);
|
ide_start_request(b);
|
||||||
|
|
||||||
// Wait for request to finish.
|
// Wait for request to finish.
|
||||||
while(!b->done)
|
while((b->flags & (B_VALID|B_DIRTY)) != B_VALID)
|
||||||
sleep(b, &ide_lock);
|
sleep(b, &ide_lock);
|
||||||
|
|
||||||
release(&ide_lock);
|
release(&ide_lock);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue