Rev 3191 | Rev 4344 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 3191 | Rev 3211 | ||
|---|---|---|---|
| Line 198... | Line 198... | ||
| 198 | interrupts_restore(ipl); |
198 | interrupts_restore(ipl); |
| 199 | 199 | ||
| 200 | return i; |
200 | return i; |
| 201 | } |
201 | } |
| 202 | 202 | ||
| 203 | /** |
- | |
| 204 | * Try to find a zone where can we find the frame. |
203 | /** Try to find a zone where can we find the frame. |
| 205 | * |
204 | * |
| 206 | * Assume interrupts are disabled. |
205 | * Assume interrupts are disabled. |
| 207 | * |
206 | * |
| 208 | * @param frame Frame number contained in zone. |
207 | * @param frame Frame number contained in zone. |
| 209 | * @param pzone If not null, it is used as zone hint. Zone index is |
208 | * @param pzone If not null, it is used as zone hint. Zone index is |
| Line 235... | Line 234... | ||
| 235 | spinlock_unlock(&z->lock); |
234 | spinlock_unlock(&z->lock); |
| 236 | 235 | ||
| 237 | i++; |
236 | i++; |
| 238 | if (i >= zones.count) |
237 | if (i >= zones.count) |
| 239 | i = 0; |
238 | i = 0; |
| 240 | } while(i != hint); |
239 | } while (i != hint); |
| 241 | 240 | ||
| 242 | spinlock_unlock(&zones.lock); |
241 | spinlock_unlock(&zones.lock); |
| 243 | return NULL; |
242 | return NULL; |
| 244 | } |
243 | } |
| 245 | 244 | ||
| Line 252... | Line 251... | ||
| 252 | /** Find and lock zone that can allocate order frames. |
251 | /** Find and lock zone that can allocate order frames. |
| 253 | * |
252 | * |
| 254 | * Assume interrupts are disabled. |
253 | * Assume interrupts are disabled. |
| 255 | * |
254 | * |
| 256 | * @param order Size (2^order) of free space we are trying to find. |
255 | * @param order Size (2^order) of free space we are trying to find. |
| - | 256 | * @param flags Required flags of the target zone. |
|
| 257 | * @param pzone Pointer to preferred zone or NULL, on return contains |
257 | * @param pzone Pointer to preferred zone or NULL, on return contains |
| 258 | * zone number. |
258 | * zone number. |
| 259 | */ |
259 | */ |
| - | 260 | static zone_t * |
|
| 260 | static zone_t *find_free_zone_and_lock(uint8_t order, unsigned int *pzone) |
261 | find_free_zone_and_lock(uint8_t order, int flags, unsigned int *pzone) |
| 261 | { |
262 | { |
| 262 | unsigned int i; |
263 | unsigned int i; |
| 263 | zone_t *z; |
264 | zone_t *z; |
| 264 | unsigned int hint = pzone ? *pzone : 0; |
265 | unsigned int hint = pzone ? *pzone : 0; |
| 265 | 266 | ||
| - | 267 | /* Mask off flags that are not applicable. */ |
|
| - | 268 | flags &= FRAME_LOW_4_GiB; |
|
| - | 269 | ||
| 266 | spinlock_lock(&zones.lock); |
270 | spinlock_lock(&zones.lock); |
| 267 | if (hint >= zones.count) |
271 | if (hint >= zones.count) |
| 268 | hint = 0; |
272 | hint = 0; |
| 269 | i = hint; |
273 | i = hint; |
| 270 | do { |
274 | do { |
| 271 | z = zones.info[i]; |
275 | z = zones.info[i]; |
| 272 | 276 | ||
| 273 | spinlock_lock(&z->lock); |
277 | spinlock_lock(&z->lock); |
| 274 | 278 | ||
| - | 279 | /* |
|
| - | 280 | * Check whether the zone meets the search criteria. |
|
| - | 281 | */ |
|
| - | 282 | if ((z->flags & flags) == flags) { |
|
| - | 283 | /* |
|
| 275 | /* Check if the zone has 2^order frames area available */ |
284 | * Check if the zone has 2^order frames area available. |
| - | 285 | */ |
|
| 276 | if (zone_can_alloc(z, order)) { |
286 | if (zone_can_alloc(z, order)) { |
| 277 | spinlock_unlock(&zones.lock); |
287 | spinlock_unlock(&zones.lock); |
| 278 | if (pzone) |
288 | if (pzone) |
| 279 | *pzone = i; |
289 | *pzone = i; |
| 280 | return z; |
290 | return z; |
| - | 291 | } |
|
| 281 | } |
292 | } |
| 282 | spinlock_unlock(&z->lock); |
293 | spinlock_unlock(&z->lock); |
| 283 | if (++i >= zones.count) |
294 | if (++i >= zones.count) |
| 284 | i = 0; |
295 | i = 0; |
| 285 | } while(i != hint); |
296 | } while (i != hint); |
| 286 | spinlock_unlock(&zones.lock); |
297 | spinlock_unlock(&zones.lock); |
| 287 | return NULL; |
298 | return NULL; |
| 288 | } |
299 | } |
| 289 | 300 | ||
| 290 | /**************************/ |
301 | /**************************/ |
| Line 316... | Line 327... | ||
| 316 | } |
327 | } |
| 317 | } while(index-- > 0); |
328 | } while(index-- > 0); |
| 318 | return NULL; |
329 | return NULL; |
| 319 | } |
330 | } |
| 320 | 331 | ||
| 321 | static void zone_buddy_print_id(buddy_system_t *b, link_t *block) |
- | |
| 322 | { |
- | |
| 323 | frame_t *frame; |
- | |
| 324 | zone_t *zone; |
- | |
| 325 | index_t index; |
- | |
| 326 | - | ||
| 327 | frame = list_get_instance(block, frame_t, buddy_link); |
- | |
| 328 | zone = (zone_t *) b->data; |
- | |
| 329 | index = frame_index(zone, frame); |
- | |
| 330 | printf("%" PRIi, index); |
- | |
| 331 | } |
- | |
| 332 | - | ||
| 333 | /** Buddy system find_buddy implementation. |
332 | /** Buddy system find_buddy implementation. |
| 334 | * |
333 | * |
| 335 | * @param b Buddy system. |
334 | * @param b Buddy system. |
| 336 | * @param block Block for which buddy should be found. |
335 | * @param block Block for which buddy should be found. |
| 337 | * |
336 | * |
| Line 467... | Line 466... | ||
| 467 | .coalesce = zone_buddy_coalesce, |
466 | .coalesce = zone_buddy_coalesce, |
| 468 | .set_order = zone_buddy_set_order, |
467 | .set_order = zone_buddy_set_order, |
| 469 | .get_order = zone_buddy_get_order, |
468 | .get_order = zone_buddy_get_order, |
| 470 | .mark_busy = zone_buddy_mark_busy, |
469 | .mark_busy = zone_buddy_mark_busy, |
| 471 | .mark_available = zone_buddy_mark_available, |
470 | .mark_available = zone_buddy_mark_available, |
| 472 | .find_block = zone_buddy_find_block, |
471 | .find_block = zone_buddy_find_block |
| 473 | .print_id = zone_buddy_print_id |
- | |
| 474 | }; |
472 | }; |
| 475 | 473 | ||
| 476 | /******************/ |
474 | /******************/ |
| 477 | /* Zone functions */ |
475 | /* Zone functions */ |
| 478 | /******************/ |
476 | /******************/ |
| Line 821... | Line 819... | ||
| 821 | uint8_t max_order; |
819 | uint8_t max_order; |
| 822 | 820 | ||
| 823 | spinlock_initialize(&z->lock, "zone_lock"); |
821 | spinlock_initialize(&z->lock, "zone_lock"); |
| 824 | z->base = start; |
822 | z->base = start; |
| 825 | z->count = count; |
823 | z->count = count; |
| - | 824 | ||
| - | 825 | /* Mask off flags that are calculated automatically. */ |
|
| - | 826 | flags &= ~FRAME_LOW_4_GiB; |
|
| - | 827 | /* Determine calculated flags. */ |
|
| - | 828 | if (z->base + count < (1ULL << (32 - FRAME_WIDTH))) /* 4 GiB */ |
|
| - | 829 | flags |= FRAME_LOW_4_GiB; |
|
| - | 830 | ||
| 826 | z->flags = flags; |
831 | z->flags = flags; |
| - | 832 | ||
| 827 | z->free_count = count; |
833 | z->free_count = count; |
| 828 | z->busy_count = 0; |
834 | z->busy_count = 0; |
| 829 | 835 | ||
| 830 | /* |
836 | /* |
| 831 | * Compute order for buddy system, initialize |
837 | * Compute order for buddy system, initialize |
| Line 993... | Line 999... | ||
| 993 | ipl = interrupts_disable(); |
999 | ipl = interrupts_disable(); |
| 994 | 1000 | ||
| 995 | /* |
1001 | /* |
| 996 | * First, find suitable frame zone. |
1002 | * First, find suitable frame zone. |
| 997 | */ |
1003 | */ |
| 998 | zone = find_free_zone_and_lock(order, pzone); |
1004 | zone = find_free_zone_and_lock(order, flags, pzone); |
| 999 | 1005 | ||
| 1000 | /* If no memory, reclaim some slab memory, |
1006 | /* If no memory, reclaim some slab memory, |
| 1001 | if it does not help, reclaim all */ |
1007 | if it does not help, reclaim all */ |
| 1002 | if (!zone && !(flags & FRAME_NO_RECLAIM)) { |
1008 | if (!zone && !(flags & FRAME_NO_RECLAIM)) { |
| 1003 | freed = slab_reclaim(0); |
1009 | freed = slab_reclaim(0); |
| 1004 | if (freed) |
1010 | if (freed) |
| 1005 | zone = find_free_zone_and_lock(order, pzone); |
1011 | zone = find_free_zone_and_lock(order, flags, pzone); |
| 1006 | if (!zone) { |
1012 | if (!zone) { |
| 1007 | freed = slab_reclaim(SLAB_RECLAIM_ALL); |
1013 | freed = slab_reclaim(SLAB_RECLAIM_ALL); |
| 1008 | if (freed) |
1014 | if (freed) |
| 1009 | zone = find_free_zone_and_lock(order, pzone); |
1015 | zone = find_free_zone_and_lock(order, flags, |
| - | 1016 | pzone); |
|
| 1010 | } |
1017 | } |
| 1011 | } |
1018 | } |
| 1012 | if (!zone) { |
1019 | if (!zone) { |
| 1013 | /* |
1020 | /* |
| 1014 | * Sleep until some frames are available again. |
1021 | * Sleep until some frames are available again. |
| Line 1212... | Line 1219... | ||
| 1212 | { |
1219 | { |
| 1213 | zone_t *zone = NULL; |
1220 | zone_t *zone = NULL; |
| 1214 | unsigned int i; |
1221 | unsigned int i; |
| 1215 | ipl_t ipl; |
1222 | ipl_t ipl; |
| 1216 | 1223 | ||
| 1217 | ipl = interrupts_disable(); |
- | |
| 1218 | spinlock_lock(&zones.lock); |
- | |
| 1219 | - | ||
| 1220 | #ifdef __32_BITS__ |
1224 | #ifdef __32_BITS__ |
| 1221 | printf("# base address free frames busy frames\n"); |
1225 | printf("# base address free frames busy frames\n"); |
| 1222 | printf("-- ------------ ------------ ------------\n"); |
1226 | printf("-- ------------ ------------ ------------\n"); |
| 1223 | #endif |
1227 | #endif |
| 1224 | 1228 | ||
| 1225 | #ifdef __64_BITS__ |
1229 | #ifdef __64_BITS__ |
| 1226 | printf("# base address free frames busy frames\n"); |
1230 | printf("# base address free frames busy frames\n"); |
| 1227 | printf("-- -------------------- ------------ ------------\n"); |
1231 | printf("-- -------------------- ------------ ------------\n"); |
| 1228 | #endif |
1232 | #endif |
| 1229 | 1233 | ||
| - | 1234 | /* |
|
| - | 1235 | * Because printing may require allocation of memory, we may not hold |
|
| - | 1236 | * the frame allocator locks when printing zone statistics. Therefore, |
|
| - | 1237 | * we simply gather the statistics under the protection of the locks and |
|
| - | 1238 | * print the statistics when the locks have been released. |
|
| - | 1239 | * |
|
| - | 1240 | * When someone adds/removes zones while we are printing the statistics, |
|
| - | 1241 | * we may end up with inaccurate output (e.g. a zone being skipped from |
|
| - | 1242 | * the listing). |
|
| - | 1243 | */ |
|
| - | 1244 | ||
| 1230 | for (i = 0; i < zones.count; i++) { |
1245 | for (i = 0; ; i++) { |
| - | 1246 | uintptr_t base; |
|
| - | 1247 | count_t free_count; |
|
| - | 1248 | count_t busy_count; |
|
| - | 1249 | ||
| - | 1250 | ipl = interrupts_disable(); |
|
| - | 1251 | spinlock_lock(&zones.lock); |
|
| - | 1252 | ||
| - | 1253 | if (i >= zones.count) { |
|
| - | 1254 | spinlock_unlock(&zones.lock); |
|
| - | 1255 | interrupts_restore(ipl); |
|
| - | 1256 | break; |
|
| - | 1257 | } |
|
| - | 1258 | ||
| 1231 | zone = zones.info[i]; |
1259 | zone = zones.info[i]; |
| 1232 | spinlock_lock(&zone->lock); |
1260 | spinlock_lock(&zone->lock); |
| 1233 | 1261 | ||
| - | 1262 | base = PFN2ADDR(zone->base); |
|
| - | 1263 | free_count = zone->free_count; |
|
| - | 1264 | busy_count = zone->busy_count; |
|
| - | 1265 | ||
| - | 1266 | spinlock_unlock(&zone->lock); |
|
| - | 1267 | ||
| - | 1268 | spinlock_unlock(&zones.lock); |
|
| - | 1269 | interrupts_restore(ipl); |
|
| - | 1270 | ||
| 1234 | #ifdef __32_BITS__ |
1271 | #ifdef __32_BITS__ |
| 1235 | printf("%-2u %10p %12" PRIc " %12" PRIc "\n", |
1272 | printf("%-2u %10p %12" PRIc " %12" PRIc "\n", i, base, |
| 1236 | i, PFN2ADDR(zone->base), zone->free_count, |
- | |
| 1237 | zone->busy_count); |
1273 | free_count, busy_count); |
| 1238 | #endif |
1274 | #endif |
| 1239 | 1275 | ||
| 1240 | #ifdef __64_BITS__ |
1276 | #ifdef __64_BITS__ |
| 1241 | printf("%-2u %18p %12" PRIc " %12" PRIc "\n", i, |
1277 | printf("%-2u %18p %12" PRIc " %12" PRIc "\n", i, base, |
| 1242 | PFN2ADDR(zone->base), zone->free_count, zone->busy_count); |
1278 | free_count, busy_count); |
| 1243 | #endif |
1279 | #endif |
| 1244 | 1280 | ||
| 1245 | spinlock_unlock(&zone->lock); |
- | |
| 1246 | } |
1281 | } |
| 1247 | - | ||
| 1248 | spinlock_unlock(&zones.lock); |
- | |
| 1249 | interrupts_restore(ipl); |
- | |
| 1250 | } |
1282 | } |
| 1251 | 1283 | ||
| 1252 | /** Prints zone details. |
1284 | /** Prints zone details. |
| 1253 | * |
1285 | * |
| 1254 | * @param num Zone base address or zone number. |
1286 | * @param num Zone base address or zone number. |
| Line 1256... | Line 1288... | ||
| 1256 | void zone_print_one(unsigned int num) |
1288 | void zone_print_one(unsigned int num) |
| 1257 | { |
1289 | { |
| 1258 | zone_t *zone = NULL; |
1290 | zone_t *zone = NULL; |
| 1259 | ipl_t ipl; |
1291 | ipl_t ipl; |
| 1260 | unsigned int i; |
1292 | unsigned int i; |
| - | 1293 | uintptr_t base; |
|
| - | 1294 | count_t count; |
|
| - | 1295 | count_t busy_count; |
|
| - | 1296 | count_t free_count; |
|
| 1261 | 1297 | ||
| 1262 | ipl = interrupts_disable(); |
1298 | ipl = interrupts_disable(); |
| 1263 | spinlock_lock(&zones.lock); |
1299 | spinlock_lock(&zones.lock); |
| 1264 | 1300 | ||
| 1265 | for (i = 0; i < zones.count; i++) { |
1301 | for (i = 0; i < zones.count; i++) { |
| Line 1267... | Line 1303... | ||
| 1267 | zone = zones.info[i]; |
1303 | zone = zones.info[i]; |
| 1268 | break; |
1304 | break; |
| 1269 | } |
1305 | } |
| 1270 | } |
1306 | } |
| 1271 | if (!zone) { |
1307 | if (!zone) { |
| - | 1308 | spinlock_unlock(&zones.lock); |
|
| - | 1309 | interrupts_restore(ipl); |
|
| 1272 | printf("Zone not found.\n"); |
1310 | printf("Zone not found.\n"); |
| 1273 | goto out; |
1311 | return; |
| 1274 | } |
1312 | } |
| 1275 | 1313 | ||
| 1276 | spinlock_lock(&zone->lock); |
1314 | spinlock_lock(&zone->lock); |
| 1277 | printf("Memory zone information\n"); |
- | |
| 1278 | printf("Zone base address: %p\n", PFN2ADDR(zone->base)); |
1315 | base = PFN2ADDR(zone->base); |
| 1279 | printf("Zone size: %" PRIc " frames (%" PRIs " KB)\n", zone->count, |
- | |
| 1280 | SIZE2KB(FRAMES2SIZE(zone->count))); |
1316 | count = zone->count; |
| 1281 | printf("Allocated space: %" PRIc " frames (%" PRIs " KB)\n", |
- | |
| 1282 | zone->busy_count, SIZE2KB(FRAMES2SIZE(zone->busy_count))); |
1317 | busy_count = zone->busy_count; |
| 1283 | printf("Available space: %" PRIc " frames (%" PRIs " KB)\n", |
- | |
| 1284 | zone->free_count, SIZE2KB(FRAMES2SIZE(zone->free_count))); |
1318 | free_count = zone->free_count; |
| 1285 | buddy_system_structure_print(zone->buddy_system, FRAME_SIZE); |
- | |
| 1286 | spinlock_unlock(&zone->lock); |
1319 | spinlock_unlock(&zone->lock); |
| 1287 | - | ||
| 1288 | out: |
- | |
| 1289 | spinlock_unlock(&zones.lock); |
1320 | spinlock_unlock(&zones.lock); |
| 1290 | interrupts_restore(ipl); |
1321 | interrupts_restore(ipl); |
| - | 1322 | ||
| - | 1323 | printf("Zone base address: %p\n", base); |
|
| - | 1324 | printf("Zone size: %" PRIc " frames (%" PRIs " KiB)\n", count, |
|
| - | 1325 | SIZE2KB(FRAMES2SIZE(count))); |
|
| - | 1326 | printf("Allocated space: %" PRIc " frames (%" PRIs " KiB)\n", |
|
| - | 1327 | busy_count, SIZE2KB(FRAMES2SIZE(busy_count))); |
|
| - | 1328 | printf("Available space: %" PRIc " frames (%" PRIs " KiB)\n", |
|
| - | 1329 | free_count, SIZE2KB(FRAMES2SIZE(free_count))); |
|
| 1291 | } |
1330 | } |
| 1292 | 1331 | ||
| 1293 | /** @} |
1332 | /** @} |
| 1294 | */ |
1333 | */ |
| 1295 | 1334 | ||