Rev 759 | Rev 768 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 759 | Rev 762 | ||
---|---|---|---|
Line 74... | Line 74... | ||
74 | } |
74 | } |
75 | 75 | ||
76 | frame_arch_init(); |
76 | frame_arch_init(); |
77 | } |
77 | } |
78 | 78 | ||
- | 79 | /** |
|
- | 80 | * Find AND LOCK zone that can allocate order frames |
|
- | 81 | * |
|
- | 82 | * Assume zone_head_lock is locked. |
|
- | 83 | */ |
|
- | 84 | static zone_t * find_free_zone(__u8 order) |
|
- | 85 | { |
|
- | 86 | link_t *cur; |
|
- | 87 | zone_t *z; |
|
- | 88 | ||
- | 89 | for (cur = zone_head.next; cur != &zone_head;cur = cur->next) { |
|
- | 90 | z = list_get_instance(cur, zone_t, link); |
|
- | 91 | ||
- | 92 | spinlock_lock(&z->lock); |
|
- | 93 | ||
- | 94 | /* Check if the zone has 2^order frames area available */ |
|
- | 95 | if (buddy_system_can_alloc(z->buddy_system, order)) |
|
- | 96 | return z; |
|
- | 97 | ||
- | 98 | spinlock_unlock(&z->lock); |
|
- | 99 | } |
|
- | 100 | return NULL; |
|
- | 101 | } |
|
- | 102 | ||
79 | /** Allocate power-of-two frames of physical memory. |
103 | /** Allocate power-of-two frames of physical memory. |
80 | * |
104 | * |
81 | * @param flags Flags for host zone selection and address processing. |
105 | * @param flags Flags for host zone selection and address processing. |
82 | * @param order Allocate exactly 2^order frames. |
106 | * @param order Allocate exactly 2^order frames. |
- | 107 | * @param pzone Pointer to preferred zone pointer, on output it changes |
|
- | 108 | * to the zone that the frame was really allocated to |
|
83 | * |
109 | * |
84 | * @return Allocated frame. |
110 | * @return Allocated frame. |
85 | */ |
111 | */ |
86 | __address frame_alloc(int flags, __u8 order, int * status) |
112 | __address frame_alloc(int flags, __u8 order, int * status, zone_t **pzone) |
87 | { |
113 | { |
88 | ipl_t ipl; |
114 | ipl_t ipl; |
89 | link_t *cur, *tmp; |
115 | link_t *tmp; |
90 | zone_t *z; |
- | |
91 | zone_t *zone = NULL; |
116 | zone_t *zone = NULL; |
92 | frame_t *frame = NULL; |
117 | frame_t *frame = NULL; |
93 | __address v; |
118 | __address v; |
94 | 119 | ||
95 | loop: |
120 | loop: |
Line 97... | Line 122... | ||
97 | spinlock_lock(&zone_head_lock); |
122 | spinlock_lock(&zone_head_lock); |
98 | 123 | ||
99 | /* |
124 | /* |
100 | * First, find suitable frame zone. |
125 | * First, find suitable frame zone. |
101 | */ |
126 | */ |
102 | for (cur = zone_head.next; cur != &zone_head; cur = cur->next) { |
- | |
103 | z = list_get_instance(cur, zone_t, link); |
127 | if (pzone && *pzone) { |
104 | - | ||
105 | spinlock_lock(&z->lock); |
128 | spinlock_lock(&(*pzone)->lock); |
106 | - | ||
107 | /* Check if the zone has 2^order frames area available */ |
- | |
108 | if (buddy_system_can_alloc(z->buddy_system, order)) { |
129 | if (!buddy_system_can_alloc((*pzone)->buddy_system, order)) |
109 | zone = z; |
130 | spinlock_unlock(&(*pzone)->lock); |
110 | break; |
- | |
111 | } |
131 | else |
112 | - | ||
113 | spinlock_unlock(&z->lock); |
132 | zone = *pzone; |
114 | } |
133 | } |
- | 134 | if (!zone) { |
|
- | 135 | zone = find_free_zone(order); |
|
- | 136 | /* If no memory, reclaim some slab memory, |
|
- | 137 | if it does not help, reclaim all */ |
|
- | 138 | if (!zone && !(flags & FRAME_NO_RECLAIM)) |
|
- | 139 | if (slab_reclaim(0) || slab_reclaim(SLAB_RECLAIM_ALL)) |
|
- | 140 | zone = find_free_zone(order); |
|
115 | 141 | } |
|
- | 142 | ||
116 | if (!zone) { |
143 | if (!zone) { |
117 | if (flags & FRAME_PANIC) |
144 | if (flags & FRAME_PANIC) |
118 | panic("Can't allocate frame.\n"); |
145 | panic("Can't allocate frame.\n"); |
119 | 146 | ||
120 | /* |
147 | /* |
Line 159... | Line 186... | ||
159 | 186 | ||
160 | if (flags & FRAME_ATOMIC) { |
187 | if (flags & FRAME_ATOMIC) { |
161 | ASSERT(status != NULL); |
188 | ASSERT(status != NULL); |
162 | *status = FRAME_OK; |
189 | *status = FRAME_OK; |
163 | } |
190 | } |
- | 191 | if (pzone) |
|
- | 192 | *pzone = zone; |
|
164 | return v; |
193 | return v; |
165 | } |
194 | } |
166 | 195 | ||
- | 196 | /** Convert address to zone pointer |
|
- | 197 | * |
|
- | 198 | * Assume zone_head_lock is held |
|
- | 199 | * |
|
- | 200 | * @param addr Physical address |
|
- | 201 | * @param lock If true, lock the zone |
|
- | 202 | */ |
|
- | 203 | static zone_t * addr2zone(__address addr, int lock) |
|
- | 204 | { |
|
- | 205 | link_t *cur; |
|
- | 206 | zone_t *z = NULL; |
|
- | 207 | ||
- | 208 | for (cur = zone_head.next; cur != &zone_head; cur = cur->next) { |
|
- | 209 | z = list_get_instance(cur, zone_t, link); |
|
- | 210 | ||
- | 211 | spinlock_lock(&z->lock); |
|
- | 212 | ||
- | 213 | /* |
|
- | 214 | * Check if addr belongs to z. |
|
- | 215 | */ |
|
- | 216 | if ((addr >= z->base) && (addr <= z->base + (z->free_count + z->busy_count) * FRAME_SIZE)) { |
|
- | 217 | if (!lock) |
|
- | 218 | spinlock_unlock(&z->lock); |
|
- | 219 | return z; |
|
- | 220 | } |
|
- | 221 | ||
- | 222 | spinlock_unlock(&z->lock); |
|
- | 223 | } |
|
- | 224 | ||
- | 225 | panic("Cannot find addr2zone: 0x%X", addr); |
|
- | 226 | } |
|
- | 227 | ||
- | 228 | /** Return frame_t structure corresponding to address |
|
- | 229 | * |
|
- | 230 | * |
|
- | 231 | */ |
|
- | 232 | frame_t * frame_addr2frame(__address addr) |
|
- | 233 | { |
|
- | 234 | ipl_t ipl; |
|
- | 235 | frame_t *frame; |
|
- | 236 | zone_t *zone; |
|
- | 237 | ||
- | 238 | if (IS_KA(addr)) |
|
- | 239 | addr = KA2PA(addr); |
|
- | 240 | ||
- | 241 | /* Disable interrupts to avoid deadlocks with interrupt handlers */ |
|
- | 242 | ipl = interrupts_disable(); |
|
- | 243 | spinlock_lock(&zone_head_lock); |
|
- | 244 | ||
- | 245 | zone = addr2zone(addr,0); |
|
- | 246 | frame = ADDR2FRAME(zone, addr); |
|
- | 247 | ||
- | 248 | spinlock_unlock(&zone_head_lock); |
|
- | 249 | interrupts_restore(ipl); |
|
- | 250 | ||
- | 251 | return frame; |
|
- | 252 | } |
|
- | 253 | ||
- | 254 | ||
167 | /** Free a frame. |
255 | /** Free a frame. |
168 | * |
256 | * |
169 | * Find respective frame structrue for supplied addr. |
257 | * Find respective frame structrue for supplied addr. |
170 | * Decrement frame reference count. |
258 | * Decrement frame reference count. |
171 | * If it drops to zero, move the frame structure to free list. |
259 | * If it drops to zero, move the frame structure to free list. |
Line 173... | Line 261... | ||
173 | * @param addr Address of the frame to be freed. It must be a multiple of FRAME_SIZE. |
261 | * @param addr Address of the frame to be freed. It must be a multiple of FRAME_SIZE. |
174 | */ |
262 | */ |
175 | void frame_free(__address addr) |
263 | void frame_free(__address addr) |
176 | { |
264 | { |
177 | ipl_t ipl; |
265 | ipl_t ipl; |
178 | link_t *cur; |
- | |
179 | zone_t *z; |
266 | zone_t *zone; |
180 | zone_t *zone = NULL; |
- | |
181 | frame_t *frame; |
267 | frame_t *frame; |
182 | int order; |
268 | int order; |
183 | 269 | ||
184 | ASSERT(addr % FRAME_SIZE == 0); |
270 | ASSERT(addr % FRAME_SIZE == 0); |
185 | 271 | ||
- | 272 | if (IS_KA(addr)) |
|
- | 273 | addr = KA2PA(addr); |
|
- | 274 | ||
186 | ipl = interrupts_disable(); |
275 | ipl = interrupts_disable(); |
187 | spinlock_lock(&zone_head_lock); |
276 | spinlock_lock(&zone_head_lock); |
188 | 277 | ||
189 | /* |
278 | /* |
190 | * First, find host frame zone for addr. |
279 | * First, find host frame zone for addr. |
191 | */ |
280 | */ |
192 | for (cur = zone_head.next; cur != &zone_head; cur = cur->next) { |
281 | zone = addr2zone(addr, 1); /* This locks the zone automatically */ |
193 | z = list_get_instance(cur, zone_t, link); |
- | |
194 | - | ||
195 | spinlock_lock(&z->lock); |
- | |
196 | - | ||
197 | if (IS_KA(addr)) |
- | |
198 | addr = KA2PA(addr); |
- | |
199 | - | ||
200 | /* |
- | |
201 | * Check if addr belongs to z. |
- | |
202 | */ |
- | |
203 | if ((addr >= z->base) && (addr <= z->base + (z->free_count + z->busy_count) * FRAME_SIZE)) { |
- | |
204 | zone = z; |
- | |
205 | break; |
- | |
206 | } |
- | |
207 | - | ||
208 | spinlock_unlock(&z->lock); |
- | |
209 | } |
- | |
210 | - | ||
211 | ASSERT(zone != NULL); |
- | |
212 | 282 | ||
213 | frame = ADDR2FRAME(zone, addr); |
283 | frame = ADDR2FRAME(zone, addr); |
214 | 284 | ||
215 | /* remember frame order */ |
285 | /* remember frame order */ |
216 | order = frame->buddy_order; |
286 | order = frame->buddy_order; |