@@ -1503,15 +1503,9 @@ static void memory_region_finalize(Object *obj)
* and cause an infinite loop.
*/
mr->enabled = false;
- memory_region_transaction_begin();
- while (!QTAILQ_EMPTY(&mr->subregions)) {
- MemoryRegion *subregion = QTAILQ_FIRST(&mr->subregions);
- memory_region_del_subregion(mr, subregion);
- }
- memory_region_transaction_commit();
-
+ assert(QTAILQ_EMPTY(&mr->subregions));
mr->destructor(mr);
- memory_region_clear_coalescing(m
+ assert(QTAILQ_EMPTY(&mr->coalesced));
g_free((char *)mr->name);
g_free(mr->ioeventfds);
}
Then let us take a look at flatview_unref, memory_region_unref may call any QOM finalize through
Object_unref(mr->owner), that's your concern, I got it. It is way too complicated to look at each QOM
object release callbacks and each QOM property release callbacks. I gave up this path.
How about fall back to synchronize_rcu?
As for address space, the RCU read lock is used to protect PhysPageMap, but not the regular MemoryRegions,
because that are not allocated in PhysPageMap build. Subpage MemoryRegion is an exception, because that is
allocated in PhysPageMap build.
The MemoryRegions returned from address_space_translate are regular MemoryRegions, so
address_space_write_continue and address_space_read_continue don't need RCU read lock.
Below patch reclaim address space in synchronized way, it reduces heap size from ~12MB to ~3MB.
You need to apply this patch with above patch. And when address_space_dispatch_free is called
it already holds the global lock, we don't need to acquire the global lock in address_space_dispatch_free.
Please review this patch.
Thanks,
Anthony
@@ -347,6 +347,7 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
tlb_add_large_page(env, vaddr, size);
}
+ rcu_read_lock();
sz = size;
section = address_space_translate_for_iotlb(cpu, asidx, paddr, &xlat, &sz);
assert(sz >= TARGET_PAGE_SIZE);
@@ -406,6 +407,7 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
} else {
te->addr_write = -1;
}
+ rcu_read_unlock();
}
/* Add a new TLB entry, but without specifying the memory
@@ -455,7 +455,7 @@ IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpace *as, hwaddr addr,
IOMMUTLBEntry iotlb = {0};
MemoryRegionSection *section;
MemoryRegion *mr;
-
+ rcu_read_lock();
for (;;) {
AddressSpaceDispatch *d = atomic_rcu_read(&as->dispatch);
section = address_space_lookup_region(d, addr, false);
@@ -477,7 +477,7 @@ IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpace *as, hwaddr addr,
| (addr & iotlb.addr_mask));
as = iotlb.target_as;
}
-
+ rcu_read_unlock();
return iotlb;
}
@@ -490,6 +490,7 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr,
MemoryRegionSection *section;
MemoryRegion *mr;
+ rcu_read_lock();
for (;;) {
AddressSpaceDispatch *d = atomic_rcu_read(&as->dispatch);
section = address_space_translate_internal(d, addr, &addr, plen, true);
@@ -517,6 +518,7 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr,
}
*xlat = addr;
+ rcu_read_unlock();
return mr;
}
@@ -2413,7 +2415,8 @@ static void mem_commit(MemoryListener *listener)
atomic_rcu_set(&as->dispatch, next);
if (cur) {
- call_rcu(cur, address_space_dispatch_free, rcu);
+ synchronize_rcu();
+ address_space_dispatch_free(cur);
}
}
@@ -2459,7 +2462,8 @@ void address_space_destroy_dispatch(AddressSpace *as)
atomic_rcu_set(&as->dispatch, NULL);
if (d) {
- call_rcu(d, address_space_dispatch_free, rcu);
+ synchronize_rcu();
+ address_space_dispatch_free(d);
}
}
@@ -2686,12 +2690,10 @@ MemTxResult address_space_write(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
MemTxResult result = MEMTX_OK;
if (len > 0) {
- rcu_read_lock();
l = len;
mr = address_space_translate(as, addr, &addr1, &l, true);
result = address_space_write_continue(as, addr, attrs, buf, len,
addr1, l, mr);
- rcu_read_unlock();
}
return result;
@@ -2776,12 +2778,10 @@ MemTxResult address_space_read_full(AddressSpace *as, hwaddr addr,
MemTxResult result = MEMTX_OK;
if (len > 0) {
- rcu_read_lock();
l = len;
mr = address_space_translate(as, addr, &addr1, &l, false);
result = address_space_read_continue(as, addr, attrs, buf, len,
addr1, l, mr);
- rcu_read_unlock();
}
return result;
@@ -914,8 +914,6 @@ void vhost_device_iotlb_miss(struct vhost_dev *dev, uint64_t iova, int write)
IOMMUTLBEntry iotlb;
uint64_t uaddr, len;
- rcu_read_lock();
-
iotlb = address_space_get_iotlb_entry(dev->vdev->dma_as,
iova, write);
if (iotlb.target_as != NULL) {
@@ -936,7 +934,7 @@ void vhost_device_iotlb_miss(struct vhost_dev *dev, uint64_t iova, int write)
}
}
out:
- rcu_read_unlock();
+ return;
}
static int vhost_virtqueue_start(struct vhost_dev *dev,