Changeset 56789125 in mainline
- Timestamp:
- 2006-05-22T09:36:48Z (19 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 8182031
- Parents:
- 040542aa
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
generic/src/mm/as.c
r040542aa r56789125 93 93 static as_area_t *find_area_and_lock(as_t *as, __address va); 94 94 static bool check_area_conflicts(as_t *as, __address va, size_t size, as_area_t *avoid_area); 95 int used_space_insert(as_area_t *a, __address page, count_t count);96 int used_space_remove(as_area_t *a, __address page, count_t count);95 static int used_space_insert(as_area_t *a, __address page, count_t count); 96 static int used_space_remove(as_area_t *a, __address page, count_t count); 97 97 98 98 /** Initialize address space subsystem. */ … … 245 245 246 246 if (pages < area->pages) { 247 int i; 247 bool cond; 248 __address start_free = area->base + pages*PAGE_SIZE; 248 249 249 250 /* … … 251 252 * No need to check for overlaps. 252 253 */ 253 for (i = pages; i < area->pages; i++) { 254 pte_t *pte; 254 255 /* 256 * Remove frames belonging to used space starting from 257 * the highest addresses downwards until an overlap with 258 * the resized address space area is found. Note that this 259 * is also the right way to remove part of the used_space 260 * B+tree leaf list. 261 */ 262 for (cond = true; cond;) { 263 btree_node_t *node; 264 265 ASSERT(!list_empty(&area->used_space.leaf_head)); 266 node = list_get_instance(area->used_space.leaf_head.prev, btree_node_t, leaf_link); 267 if ((cond = (bool) node->keys)) { 268 __address b = node->key[node->keys - 1]; 269 count_t c = (count_t) node->value[node->keys - 1]; 270 int i = 0; 255 271 256 /* 257 * Releasing physical memory. 258 * This depends on the fact that the memory was allocated using frame_alloc(). 259 */ 260 page_table_lock(as, false); 261 pte = page_mapping_find(as, area->base + i*PAGE_SIZE); 262 if (pte && PTE_VALID(pte)) { 263 __address frame; 264 265 ASSERT(PTE_PRESENT(pte)); 266 frame = PTE_GET_FRAME(pte); 267 page_mapping_remove(as, area->base + i*PAGE_SIZE); 268 page_table_unlock(as, false); 269 270 frame_free(ADDR2PFN(frame)); 271 } else { 272 page_table_unlock(as, false); 272 if (overlaps(b, c*PAGE_SIZE, area->base, pages*PAGE_SIZE)) { 273 274 if (b + c*PAGE_SIZE <= start_free) { 275 /* 276 * The whole interval fits completely 277 * in the resized address space area. 278 */ 279 break; 280 } 281 282 /* 283 * Part of the interval corresponding to b and c 284 * overlaps with the resized address space area. 285 */ 286 287 cond = false; /* we are almost done */ 288 i = (start_free - b) >> PAGE_WIDTH; 289 if (!used_space_remove(area, start_free, c - i)) 290 panic("Could not remove used space."); 291 } else { 292 /* 293 * The interval of used space can be completely removed. 294 */ 295 if (!used_space_remove(area, b, c)) 296 panic("Could not remove used space.\n"); 297 } 298 299 for (; i < c; i++) { 300 pte_t *pte; 301 302 page_table_lock(as, false); 303 pte = page_mapping_find(as, b + i*PAGE_SIZE); 304 ASSERT(pte && PTE_VALID(pte) && PTE_PRESENT(pte)); 305 frame_free(ADDR2PFN(PTE_GET_FRAME(pte))); 306 page_mapping_remove(as, b + i*PAGE_SIZE); 307 page_table_unlock(as, false); 308 } 273 309 } 274 310 } … … 313 349 __address base; 314 350 ipl_t ipl; 315 int i;316 351 317 352 ipl = interrupts_disable(); … … 325 360 } 326 361 327 base = area->base; 328 for (i = 0; i < area->pages; i++) {329 pte_t *pte;330 362 base = area->base; 363 if (!(area->flags & AS_AREA_DEVICE)) { 364 bool cond; 365 331 366 /* 332 367 * Releasing physical memory. … … 334 369 * areas backing frame_alloc()'ed memory. 335 370 */ 336 page_table_lock(as, false); 337 pte = page_mapping_find(as, area->base + i*PAGE_SIZE); 338 if (pte && PTE_VALID(pte)) { 339 ASSERT(PTE_PRESENT(pte)); 340 page_mapping_remove(as, area->base + i*PAGE_SIZE); 341 if (area->flags & AS_AREA_DEVICE) { 342 __address frame; 343 frame = PTE_GET_FRAME(pte); 344 frame_free(ADDR2PFN(frame)); 371 372 /* 373 * Visit only the pages mapped by used_space B+tree. 374 * Note that we must be very careful when walking the tree 375 * leaf list and removing used space as the leaf list changes 376 * unpredictibly after each remove. The solution is to actually 377 * not walk the tree at all, but to remove items from the head 378 * of the leaf list until there are some keys left. 379 */ 380 for (cond = true; cond;) { 381 btree_node_t *node; 382 383 ASSERT(!list_empty(&area->used_space.leaf_head)); 384 node = list_get_instance(area->used_space.leaf_head.next, btree_node_t, leaf_link); 385 if ((cond = (bool) node->keys)) { 386 __address b = node->key[0]; 387 count_t i; 388 pte_t *pte; 389 390 for (i = 0; i < (count_t) node->value[0]; i++) { 391 page_table_lock(as, false); 392 pte = page_mapping_find(as, b + i*PAGE_SIZE); 393 ASSERT(pte && PTE_VALID(pte) && PTE_PRESENT(pte)); 394 frame_free(ADDR2PFN(PTE_GET_FRAME(pte))); 395 page_mapping_remove(as, b + i*PAGE_SIZE); 396 page_table_unlock(as, false); 397 } 398 if (!used_space_remove(area, b, i)) 399 panic("Could not remove used space.\n"); 345 400 } 346 page_table_unlock(as, false); 347 } else { 348 page_table_unlock(as, false); 349 } 350 } 401 } 402 } 403 btree_destroy(&area->used_space); 404 351 405 /* 352 406 * Invalidate TLB's. … … 419 473 mutex_unlock(&src_area->lock); 420 474 mutex_unlock(&src_as->lock); 421 422 475 423 476 if (src_size != acc_size) { … … 513 566 area = find_area_and_lock(as, page); 514 567 if (!area) { 515 panic(" page not part of any as_area\n");568 panic("Page not part of any as_area.\n"); 516 569 } 517 570 518 571 page_mapping_insert(as, page, frame, get_area_flags(area)); 572 if (!used_space_insert(area, page, 1)) 573 panic("Could not insert used space.\n"); 519 574 520 575 mutex_unlock(&area->lock); … … 606 661 */ 607 662 page_mapping_insert(AS, page, frame, get_area_flags(area)); 663 if (!used_space_insert(area, ALIGN_DOWN(page, PAGE_SIZE), 1)) 664 panic("Could not insert used space.\n"); 608 665 page_table_unlock(AS, false); 609 666 … … 997 1054 } else if ((page == left_pg + left_cnt*PAGE_SIZE) && (page + count*PAGE_SIZE == right_pg)) { 998 1055 /* The interval can be added by merging the two already present intervals. */ 999 node->value[node->keys - 1] += (count_t)count + right_cnt;1056 node->value[node->keys - 1] += count + right_cnt; 1000 1057 btree_remove(&a->used_space, right_pg, leaf); 1001 1058 return 1; 1002 1059 } else if (page == left_pg + left_cnt*PAGE_SIZE) { 1003 1060 /* The interval can be added by simply growing the left interval. */ 1004 node->value[node->keys - 1] += (count_t)count;1061 node->value[node->keys - 1] += count; 1005 1062 return 1; 1006 1063 } else if (page + count*PAGE_SIZE == right_pg) { … … 1009 1066 * interval down and increasing its size accordingly. 1010 1067 */ 1011 leaf->value[0] += (count_t)count;1068 leaf->value[0] += count; 1012 1069 leaf->key[0] = page; 1013 1070 return 1; … … 1038 1095 */ 1039 1096 leaf->key[0] = page; 1040 leaf->value[0] += (count_t)count;1097 leaf->value[0] += count; 1041 1098 return 1; 1042 1099 } else { … … 1071 1128 } else if ((page == left_pg + left_cnt*PAGE_SIZE) && (page + count*PAGE_SIZE == right_pg)) { 1072 1129 /* The interval can be added by merging the two already present intervals. */ 1073 leaf->value[leaf->keys - 1] += (count_t)count + right_cnt;1130 leaf->value[leaf->keys - 1] += count + right_cnt; 1074 1131 btree_remove(&a->used_space, right_pg, node); 1075 1132 return 1; 1076 1133 } else if (page == left_pg + left_cnt*PAGE_SIZE) { 1077 1134 /* The interval can be added by simply growing the left interval. */ 1078 leaf->value[leaf->keys - 1] += (count_t)count;1135 leaf->value[leaf->keys - 1] += count; 1079 1136 return 1; 1080 1137 } else if (page + count*PAGE_SIZE == right_pg) { … … 1083 1140 * interval down and increasing its size accordingly. 1084 1141 */ 1085 node->value[0] += (count_t)count;1142 node->value[0] += count; 1086 1143 node->key[0] = page; 1087 1144 return 1; … … 1104 1161 1105 1162 if (overlaps(page, count*PAGE_SIZE, left_pg, left_cnt*PAGE_SIZE)) { 1106 /* The interval intersects with the right interval. */1163 /* The interval intersects with the left interval. */ 1107 1164 return 0; 1108 1165 } else if (left_pg + left_cnt*PAGE_SIZE == page) { 1109 1166 /* The interval can be added by growing the left interval. */ 1110 leaf->value[leaf->keys - 1] += (count_t)count;1167 leaf->value[leaf->keys - 1] += count; 1111 1168 return 1; 1112 1169 } else { … … 1142 1199 } else if ((page == left_pg + left_cnt*PAGE_SIZE) && (page + count*PAGE_SIZE == right_pg)) { 1143 1200 /* The interval can be added by merging the two already present intervals. */ 1144 leaf->value[i - 1] += (count_t)count + right_cnt;1201 leaf->value[i - 1] += count + right_cnt; 1145 1202 btree_remove(&a->used_space, right_pg, leaf); 1146 1203 return 1; 1147 1204 } else if (page == left_pg + left_cnt*PAGE_SIZE) { 1148 1205 /* The interval can be added by simply growing the left interval. */ 1149 leaf->value[i - 1] += (count_t)count;1206 leaf->value[i - 1] += count; 1150 1207 return 1; 1151 1208 } else if (page + count*PAGE_SIZE == right_pg) { … … 1154 1211 * interval down and increasing its size accordingly. 1155 1212 */ 1156 leaf->value[i] += (count_t)count;1213 leaf->value[i] += count; 1157 1214 leaf->key[i] = page; 1158 1215 return 1; … … 1199 1256 } else if (count == pages) { 1200 1257 btree_remove(&a->used_space, page, leaf); 1258 return 1; 1201 1259 } else { 1202 1260 /* … … 1207 1265 if (leaf->key[i] == page) { 1208 1266 leaf->key[i] += count*PAGE_SIZE; 1209 leaf->value[i] -= (count_t)count;1267 leaf->value[i] -= count; 1210 1268 return 1; 1211 1269 } … … 1227 1285 * updating the size of the bigger interval. 1228 1286 */ 1229 node->value[node->keys - 1] -= (count_t)count;1287 node->value[node->keys - 1] -= count; 1230 1288 return 1; 1231 1289 } else if (page + count*PAGE_SIZE < left_pg + left_cnt*PAGE_SIZE) { 1232 count_t new_cnt = (left_pg + left_cnt*PAGE_SIZE) - (page + count*PAGE_SIZE);1290 count_t new_cnt; 1233 1291 1234 1292 /* … … 1238 1296 * also inserting a new interval. 1239 1297 */ 1240 node->value[node->keys - 1] -= (count_t) count + new_cnt; 1298 new_cnt = ((left_pg + left_cnt*PAGE_SIZE) - (page + count*PAGE_SIZE)) >> PAGE_WIDTH; 1299 node->value[node->keys - 1] -= count + new_cnt; 1241 1300 btree_insert(&a->used_space, page + count*PAGE_SIZE, (void *) new_cnt, leaf); 1242 1301 return 1; … … 1259 1318 * of the bigger interval. 1260 1319 */ 1261 leaf->value[leaf->keys - 1] -= (count_t)count;1320 leaf->value[leaf->keys - 1] -= count; 1262 1321 return 1; 1263 1322 } else if (page + count*PAGE_SIZE < left_pg + left_cnt*PAGE_SIZE) { 1264 count_t new_cnt = (left_pg + left_cnt*PAGE_SIZE) - (page + count*PAGE_SIZE);1323 count_t new_cnt; 1265 1324 1266 1325 /* … … 1270 1329 * also inserting a new interval. 1271 1330 */ 1272 leaf->value[leaf->keys - 1] -= (count_t) count + new_cnt; 1331 new_cnt = ((left_pg + left_cnt*PAGE_SIZE) - (page + count*PAGE_SIZE)) >> PAGE_WIDTH; 1332 leaf->value[leaf->keys - 1] -= count + new_cnt; 1273 1333 btree_insert(&a->used_space, page + count*PAGE_SIZE, (void *) new_cnt, leaf); 1274 1334 return 1; … … 1297 1357 * of the bigger interval. 1298 1358 */ 1299 leaf->value[i - 1] -= (count_t)count;1359 leaf->value[i - 1] -= count; 1300 1360 return 1; 1301 1361 } else if (page + count*PAGE_SIZE < left_pg + left_cnt*PAGE_SIZE) { 1302 count_t new_cnt = (left_pg + left_cnt*PAGE_SIZE) - (page + count*PAGE_SIZE);1362 count_t new_cnt; 1303 1363 1304 1364 /* … … 1308 1368 * also inserting a new interval. 1309 1369 */ 1310 leaf->value[i - 1] -= (count_t) count + new_cnt; 1370 new_cnt = ((left_pg + left_cnt*PAGE_SIZE) - (page + count*PAGE_SIZE)) >> PAGE_WIDTH; 1371 leaf->value[i - 1] -= count + new_cnt; 1311 1372 btree_insert(&a->used_space, page + count*PAGE_SIZE, (void *) new_cnt, leaf); 1312 1373 return 1;
Note:
See TracChangeset
for help on using the changeset viewer.