126 lines
		
	
	
	
		
			2.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			126 lines
		
	
	
	
		
			2.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "types.h"
 | |
| #include "param.h"
 | |
| #include "x86.h"
 | |
| #include "mmu.h"
 | |
| #include "proc.h"
 | |
| #include "defs.h"
 | |
| #include "spinlock.h"
 | |
| #include "buf.h"
 | |
| 
 | |
| 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;
 | |
| 
 | |
|   acquire(&buf_table_lock);
 | |
| 
 | |
|   while(1){
 | |
|     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 != &bufhead){
 | |
|       if(b->flags & B_BUSY){
 | |
|         sleep(buf, &buf_table_lock);
 | |
|       } else {
 | |
|         b->flags |= B_BUSY;
 | |
|         release(&buf_table_lock);
 | |
|         return b;
 | |
|       }
 | |
|     } else {
 | |
|       for(b = bufhead.prev; b != &bufhead; b = b->prev){
 | |
|         if((b->flags & B_BUSY) == 0){
 | |
|           b->flags = B_BUSY;
 | |
|           b->dev = dev;
 | |
|           b->sector = sector;
 | |
|           release(&buf_table_lock);
 | |
|           return b;
 | |
|         }
 | |
|       }
 | |
|       panic("getblk: no buffers");
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| struct buf *
 | |
| bread(uint dev, uint sector)
 | |
| {
 | |
|   void *c;
 | |
|   struct buf *b;
 | |
|   extern struct spinlock ide_lock;
 | |
| 
 | |
|   b = getblk(dev, sector);
 | |
|   if(b->flags & B_VALID){
 | |
|     return b;
 | |
|   }
 | |
| 
 | |
|   acquire(&ide_lock);
 | |
|   c = ide_start_rw(dev & 0xff, sector, b->data, 1, 1);
 | |
|   sleep (c, &ide_lock);
 | |
|   ide_finish(c);
 | |
|   b->flags |= B_VALID;
 | |
|   release(&ide_lock);
 | |
| 
 | |
|   return b;
 | |
| }
 | |
| 
 | |
| void
 | |
| bwrite(struct buf *b, uint sector)
 | |
| {
 | |
|   void *c;
 | |
|   extern struct spinlock ide_lock;
 | |
| 
 | |
|   acquire(&ide_lock);
 | |
|   c = ide_start_rw(b->dev & 0xff, sector, b->data, 1, 0);
 | |
|   sleep (c, &ide_lock);
 | |
|   ide_finish(c);
 | |
|   b->flags |= B_VALID;
 | |
|   release(&ide_lock);
 | |
| }
 | |
| 
 | |
| void
 | |
| brelse(struct buf *b)
 | |
| {
 | |
|   if((b->flags & B_BUSY) == 0)
 | |
|     panic("brelse");
 | |
|   
 | |
|   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);
 | |
| 
 | |
|   release(&buf_table_lock);
 | |
| }
 | |
| 
 | 
