struct buf buf[NBUF];
struct spinlock buf_table_lock;
+// linked list of all buffers, through prev/next.
+// bufhead->next is most recently used.
+// bufhead->tail is least recently used.
+struct buf bufhead;
+
void
binit(void)
{
+ struct buf *b;
+
initlock(&buf_table_lock, "buf_table");
+
+ bufhead.prev = &bufhead;
+ bufhead.next = &bufhead;
+ for(b = buf; b < buf+NBUF; b++){
+ b->next = bufhead.next;
+ b->prev = &bufhead;
+ bufhead.next->prev = b;
+ bufhead.next = b;
+ }
}
struct buf *
getblk(uint dev, uint sector)
{
struct buf *b;
- static struct buf *scan = buf;
- int i;
acquire(&buf_table_lock);
while(1){
- for(b = buf; b < buf+NBUF; b++)
+ for(b = bufhead.next; b != &bufhead; b = b->next)
if((b->flags & (B_BUSY|B_VALID)) && b->dev == dev && b->sector == sector)
break;
- if(b < buf+NBUF){
+ if(b != &bufhead){
if(b->flags & B_BUSY){
sleep(buf, &buf_table_lock);
} else {
return b;
}
} else {
- for(i = 0; i < NBUF; i++){
- b = scan++;
- if(scan >= buf+NBUF)
- scan = buf;
+ for(b = bufhead.prev; b != &bufhead; b = b->prev){
if((b->flags & B_BUSY) == 0){
b->flags = B_BUSY;
b->dev = dev;
extern struct spinlock ide_lock;
b = getblk(dev, sector);
- if(b->flags & B_VALID)
+ if(b->flags & B_VALID){
return b;
+ }
acquire(&ide_lock);
c = ide_start_rw(dev & 0xff, sector, b->data, 1, 1);
acquire(&buf_table_lock);
+ b->next->prev = b->prev;
+ b->prev->next = b->next;
+ b->next = bufhead.next;
+ b->prev = &bufhead;
+ bufhead.next->prev = b;
+ bufhead.next = b;
+
b->flags &= ~B_BUSY;
wakeup(buf);
void
unlinkread()
{
- int fd;
+ int fd, fd1;
fd = open("unlinkread", O_CREATE | O_RDWR);
if(fd < 0){
puts("unlink unlinkread failed\n");
exit();
}
+
+ fd1 = open("xxx", O_CREATE | O_RDWR);
+ write(fd1, "yyy", 3);
+ close(fd1);
+
if(read(fd, buf, sizeof(buf)) != 5){
puts("unlinkread read failed");
exit();
}
+ if(buf[0] != 'h'){
+ puts("unlinkread wrong data\n");
+ exit();
+ }
if(write(fd, buf, 10) != 10){
puts("unlinkread write failed\n");
exit();
}
close(fd);
+ unlink("xxx");
puts("unlinkread ok\n");
}
{
puts("usertests starting\n");
- //unlinkread();
+ unlinkread();
createdelete();
twofiles();
sharedfd();