Mercurial > hg > CbC > CbC_xv6
comparison src/bio.c @ 0:83c23a36980d
Init
author | Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 26 May 2017 23:11:05 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:83c23a36980d |
---|---|
1 // Buffer cache. | |
2 // | |
3 // The buffer cache is a linked list of buf structures holding | |
4 // cached copies of disk block contents. Caching disk blocks | |
5 // in memory reduces the number of disk reads and also provides | |
6 // a synchronization point for disk blocks used by multiple processes. | |
7 // | |
8 // Interface: | |
9 // * To get a buffer for a particular disk block, call bread. | |
10 // * After changing buffer data, call bwrite to write it to disk. | |
11 // * When done with the buffer, call brelse. | |
12 // * Do not use the buffer after calling brelse. | |
13 // * Only one process at a time can use a buffer, | |
14 // so do not keep them longer than necessary. | |
15 // | |
16 // The implementation uses three state flags internally: | |
17 // * B_BUSY: the block has been returned from bread | |
18 // and has not been passed back to brelse. | |
19 // * B_VALID: the buffer data has been read from the disk. | |
20 // * B_DIRTY: the buffer data has been modified | |
21 // and needs to be written to disk. | |
22 | |
23 #include "types.h" | |
24 #include "defs.h" | |
25 #include "param.h" | |
26 #include "spinlock.h" | |
27 #include "buf.h" | |
28 | |
29 struct { | |
30 struct spinlock lock; | |
31 struct buf buf[NBUF]; | |
32 | |
33 // Linked list of all buffers, through prev/next. | |
34 // head.next is most recently used. | |
35 struct buf head; | |
36 } bcache; | |
37 | |
38 void binit (void) | |
39 { | |
40 struct buf *b; | |
41 | |
42 initlock(&bcache.lock, "bcache"); | |
43 | |
44 //PAGEBREAK! | |
45 // Create linked list of buffers | |
46 bcache.head.prev = &bcache.head; | |
47 bcache.head.next = &bcache.head; | |
48 | |
49 for (b = bcache.buf; b < bcache.buf + NBUF; b++) { | |
50 b->next = bcache.head.next; | |
51 b->prev = &bcache.head; | |
52 b->dev = -1; | |
53 bcache.head.next->prev = b; | |
54 bcache.head.next = b; | |
55 } | |
56 } | |
57 | |
58 // Look through buffer cache for sector on device dev. | |
59 // If not found, allocate fresh block. | |
60 // In either case, return B_BUSY buffer. | |
61 static struct buf* bget (uint dev, uint sector) | |
62 { | |
63 struct buf *b; | |
64 | |
65 acquire(&bcache.lock); | |
66 | |
67 loop: | |
68 // Is the sector already cached? | |
69 for (b = bcache.head.next; b != &bcache.head; b = b->next) { | |
70 if (b->dev == dev && b->sector == sector) { | |
71 if (!(b->flags & B_BUSY)) { | |
72 b->flags |= B_BUSY; | |
73 release(&bcache.lock); | |
74 return b; | |
75 } | |
76 | |
77 sleep(b, &bcache.lock); | |
78 goto loop; | |
79 } | |
80 } | |
81 | |
82 // Not cached; recycle some non-busy and clean buffer. | |
83 for (b = bcache.head.prev; b != &bcache.head; b = b->prev) { | |
84 if ((b->flags & B_BUSY) == 0 && (b->flags & B_DIRTY) == 0) { | |
85 b->dev = dev; | |
86 b->sector = sector; | |
87 b->flags = B_BUSY; | |
88 release(&bcache.lock); | |
89 return b; | |
90 } | |
91 } | |
92 | |
93 panic("bget: no buffers"); | |
94 } | |
95 | |
96 // Return a B_BUSY buf with the contents of the indicated disk sector. | |
97 struct buf* bread (uint dev, uint sector) | |
98 { | |
99 struct buf *b; | |
100 | |
101 b = bget(dev, sector); | |
102 | |
103 if (!(b->flags & B_VALID)) { | |
104 iderw(b); | |
105 } | |
106 | |
107 return b; | |
108 } | |
109 | |
110 // Write b's contents to disk. Must be B_BUSY. | |
111 void bwrite (struct buf *b) | |
112 { | |
113 if ((b->flags & B_BUSY) == 0) { | |
114 panic("bwrite"); | |
115 } | |
116 | |
117 b->flags |= B_DIRTY; | |
118 iderw(b); | |
119 } | |
120 | |
121 // Release a B_BUSY buffer. | |
122 // Move to the head of the MRU list. | |
123 void brelse (struct buf *b) | |
124 { | |
125 if ((b->flags & B_BUSY) == 0) { | |
126 panic("brelse"); | |
127 } | |
128 | |
129 acquire(&bcache.lock); | |
130 | |
131 b->next->prev = b->prev; | |
132 b->prev->next = b->next; | |
133 b->next = bcache.head.next; | |
134 b->prev = &bcache.head; | |
135 bcache.head.next->prev = b; | |
136 bcache.head.next = b; | |
137 | |
138 b->flags &= ~B_BUSY; | |
139 wakeup(b); | |
140 | |
141 release(&bcache.lock); | |
142 } | |
143 |