* Install new virtual address region into address space * The pvarea will be set to the varea where new virt memory installed which can * be a newly created or existed one. * * Note: caller must hold the aspace lock */
| 508 | * Note: caller must hold the aspace lock |
| 509 | */ |
| 510 | static int _varea_install(rt_aspace_t aspace, rt_varea_t *pvarea, |
| 511 | rt_mm_va_hint_t hint, struct _mapping_property *prop, |
| 512 | void **pva) |
| 513 | { |
| 514 | void *alloc_va; |
| 515 | int err = RT_EOK; |
| 516 | |
| 517 | if (hint->flags & MMF_MAP_FIXED) |
| 518 | { |
| 519 | alloc_va = hint->prefer; |
| 520 | err = _unmap_range_locked(aspace, alloc_va, hint->map_size); |
| 521 | if (err != RT_EOK) |
| 522 | { |
| 523 | /* Note: MAP_FIXED must failed if unable to unmap existing mapping */ |
| 524 | LOG_I("%s: unmap range failed in %p with size 0x%lx, error=%d", __func__, alloc_va, hint->map_size, err); |
| 525 | } |
| 526 | } |
| 527 | else |
| 528 | { |
| 529 | alloc_va = |
| 530 | _find_free(aspace, hint->prefer, hint->map_size, hint->limit_start, |
| 531 | hint->limit_range_size, hint->flags); |
| 532 | if (alloc_va == RT_NULL) |
| 533 | err = -RT_ENOSPC; |
| 534 | } |
| 535 | |
| 536 | if (alloc_va != RT_NULL) |
| 537 | { |
| 538 | /* TODO: fix to private mapping directly */ |
| 539 | if (!_try_expand_and_merge_okay(aspace, pvarea, alloc_va, hint, prop)) |
| 540 | { |
| 541 | err = _insert_new_varea(aspace, pvarea, alloc_va, hint); |
| 542 | |
| 543 | if (err == RT_EOK) |
| 544 | _varea_post_install(*pvarea, aspace, prop->attr, prop->flags, |
| 545 | prop->mem_obj, prop->offset); |
| 546 | } |
| 547 | |
| 548 | if (err == RT_EOK) |
| 549 | { |
| 550 | RT_ASSERT(*pvarea); |
| 551 | *pva = alloc_va; |
| 552 | } |
| 553 | } |
| 554 | |
| 555 | return err; |
| 556 | } |
| 557 | |
| 558 | /** |
| 559 | * restore context modified by varea install |
no test coverage detected