Move retry loop/sleep/wakeup in bio.c into sleeping locks
This commit is contained in:
		
							parent
							
								
									6670d3b5e0
								
							
						
					
					
						commit
						2adb7c21dc
					
				
					 3 changed files with 31 additions and 28 deletions
				
			
		
							
								
								
									
										56
									
								
								bio.c
									
										
									
									
									
								
							
							
						
						
									
										56
									
								
								bio.c
									
										
									
									
									
								
							|  | @ -49,7 +49,6 @@ binit(void) | ||||||
|   for(b = bcache.buf; b < bcache.buf+NBUF; b++){ |   for(b = bcache.buf; b < bcache.buf+NBUF; b++){ | ||||||
|     b->next = bcache.head.next; |     b->next = bcache.head.next; | ||||||
|     b->prev = &bcache.head; |     b->prev = &bcache.head; | ||||||
|     b->dev = -1; |  | ||||||
|     initsleeplock(&b->lock, "buffer"); |     initsleeplock(&b->lock, "buffer"); | ||||||
|     bcache.head.next->prev = b; |     bcache.head.next->prev = b; | ||||||
|     bcache.head.next = b; |     bcache.head.next = b; | ||||||
|  | @ -66,33 +65,33 @@ bget(uint dev, uint blockno) | ||||||
| 
 | 
 | ||||||
|   acquire(&bcache.lock); |   acquire(&bcache.lock); | ||||||
| 
 | 
 | ||||||
|   //cprintf("bget %d\n", blockno);
 |   // cprintf("bget %d\n", blockno);
 | ||||||
|  loop: |    | ||||||
|   // Is the block already cached?
 |   // Is the block already cached?
 | ||||||
|   for(b = bcache.head.next; b != &bcache.head; b = b->next){ |   for(b = bcache.head.next; b != &bcache.head; b = b->next){ | ||||||
|     if(b->dev == dev && b->blockno == blockno){ |     if(b->dev == dev && b->blockno == blockno){ | ||||||
|       if(!holdingsleep(&b->lock)) { |       //cprintf("bget %d; get sleep lock for buffer %p\n", blockno, b - bcache.buf);
 | ||||||
|         acquiresleep(&b->lock); |       b->refcnt++; | ||||||
|         //cprintf("return buffer %p for blk %d\n", b - bcache.buf, blockno);
 |       release(&bcache.lock); | ||||||
|         release(&bcache.lock); |       acquiresleep(&b->lock); | ||||||
|         return b; |       //cprintf("bget: return buffer %p for blk %d\n", b - bcache.buf, blockno);
 | ||||||
|       } |       return b; | ||||||
|       sleep(b, &bcache.lock); |  | ||||||
|       goto loop; |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // Not cached; recycle some non-locked and clean buffer.
 |   // Not cached; recycle some unused buffer and clean buffer
 | ||||||
|   // "clean" because B_DIRTY and not locked means log.c
 |   // "clean" because B_DIRTY and not locked means log.c
 | ||||||
|   // hasn't yet committed the changes to the buffer.
 |   // hasn't yet committed the changes to the buffer.
 | ||||||
|   for(b = bcache.head.prev; b != &bcache.head; b = b->prev){ |   for(b = bcache.head.prev; b != &bcache.head; b = b->prev){ | ||||||
|     if(!holdingsleep(&b->lock) && (b->flags & B_DIRTY) == 0){ |     if(b->refcnt == 0 && (b->flags & B_DIRTY) == 0) { | ||||||
|  |       // cprintf("bget %d; use %p for %d\n", b - bcache.buf, blockno);
 | ||||||
|       b->dev = dev; |       b->dev = dev; | ||||||
|       b->blockno = blockno; |       b->blockno = blockno; | ||||||
|       b->flags = 0;  // XXX
 |       b->flags = 0; | ||||||
|       acquiresleep(&b->lock); |       b->refcnt = 1; | ||||||
|       //cprintf("return buffer %p for blk %d\n", b - bcache.buf, blockno);
 |  | ||||||
|       release(&bcache.lock); |       release(&bcache.lock); | ||||||
|  |       acquiresleep(&b->lock); | ||||||
|  |       // cprintf("bget: return buffer %p for blk %d\n", b - bcache.buf, blockno);
 | ||||||
|       return b; |       return b; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  | @ -116,7 +115,7 @@ bread(uint dev, uint blockno) | ||||||
| void | void | ||||||
| bwrite(struct buf *b) | bwrite(struct buf *b) | ||||||
| { | { | ||||||
|   if(b->lock.locked == 0) |   if(!holdingsleep(&b->lock)) | ||||||
|     panic("bwrite"); |     panic("bwrite"); | ||||||
|   b->flags |= B_DIRTY; |   b->flags |= B_DIRTY; | ||||||
|   iderw(b); |   iderw(b); | ||||||
|  | @ -127,20 +126,23 @@ bwrite(struct buf *b) | ||||||
| void | void | ||||||
| brelse(struct buf *b) | brelse(struct buf *b) | ||||||
| { | { | ||||||
|   if(b->lock.locked == 0) |   if(!holdingsleep(&b->lock)) | ||||||
|     panic("brelse"); |     panic("brelse"); | ||||||
| 
 | 
 | ||||||
|   acquire(&bcache.lock); |  | ||||||
| 
 |  | ||||||
|   b->next->prev = b->prev; |  | ||||||
|   b->prev->next = b->next; |  | ||||||
|   b->next = bcache.head.next; |  | ||||||
|   b->prev = &bcache.head; |  | ||||||
|   bcache.head.next->prev = b; |  | ||||||
|   bcache.head.next = b; |  | ||||||
|   releasesleep(&b->lock); |   releasesleep(&b->lock); | ||||||
|   wakeup(b); |  | ||||||
| 
 | 
 | ||||||
|  |   acquire(&bcache.lock); | ||||||
|  |   b->refcnt--; | ||||||
|  |   if (b->refcnt == 0) { | ||||||
|  |     // no one is waiting for it.
 | ||||||
|  |     b->next->prev = b->prev; | ||||||
|  |     b->prev->next = b->next; | ||||||
|  |     b->next = bcache.head.next; | ||||||
|  |     b->prev = &bcache.head; | ||||||
|  |     bcache.head.next->prev = b; | ||||||
|  |     bcache.head.next = b; | ||||||
|  |   } | ||||||
|  |    | ||||||
|   release(&bcache.lock); |   release(&bcache.lock); | ||||||
| } | } | ||||||
| //PAGEBREAK!
 | //PAGEBREAK!
 | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								buf.h
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								buf.h
									
										
									
									
									
								
							|  | @ -3,6 +3,7 @@ struct buf { | ||||||
|   uint dev; |   uint dev; | ||||||
|   uint blockno; |   uint blockno; | ||||||
|   struct sleeplock lock; |   struct sleeplock lock; | ||||||
|  |   uint refcnt; | ||||||
|   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
 | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								defs.h
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								defs.h
									
										
									
									
									
								
							|  | @ -131,7 +131,7 @@ void            popcli(void); | ||||||
| 
 | 
 | ||||||
| // sleeplock.c
 | // sleeplock.c
 | ||||||
| void            acquiresleep(struct sleeplock*); | void            acquiresleep(struct sleeplock*); | ||||||
| void            releasesleep(struct sleeplock*); | void             releasesleep(struct sleeplock*); | ||||||
| int             holdingsleep(struct sleeplock*); | int             holdingsleep(struct sleeplock*); | ||||||
| void            initsleeplock(struct sleeplock*, char*); | void            initsleeplock(struct sleeplock*, char*); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Frans Kaashoek
						Frans Kaashoek