Changeset View
Standalone View
sys/vm/vm_page.c
Show First 20 Lines • Show All 2,403 Lines • ▼ Show 20 Lines | again: | ||||
if (vm_domain_allocate(vmd, req, 1)) { | if (vm_domain_allocate(vmd, req, 1)) { | ||||
vm_domain_free_lock(vmd); | vm_domain_free_lock(vmd); | ||||
if (freelist == VM_NFREELIST) | if (freelist == VM_NFREELIST) | ||||
m = vm_phys_alloc_pages(domain, VM_FREEPOOL_DIRECT, 0); | m = vm_phys_alloc_pages(domain, VM_FREEPOOL_DIRECT, 0); | ||||
else | else | ||||
m = vm_phys_alloc_freelist_pages(domain, freelist, | m = vm_phys_alloc_freelist_pages(domain, freelist, | ||||
VM_FREEPOOL_DIRECT, 0); | VM_FREEPOOL_DIRECT, 0); | ||||
vm_domain_free_unlock(vmd); | vm_domain_free_unlock(vmd); | ||||
if (m == NULL) | if (m == NULL) { | ||||
vm_domain_freecnt_inc(vmd, 1); | vm_domain_freecnt_inc(vmd, 1); | ||||
#if VM_NRESERVLEVEL > 0 | |||||
if (freelist == VM_NFREELIST && | |||||
markj: I'm not sure how best to handle the `freelist != VM_NFREELIST` case here. It doesn't… | |||||
Not Done Inline ActionsIn fact, e.g. on amd64 I think VM_FREELIST_DMA32 could get more uses than it has now. For instance, pmap_page_alloc_below_4g() might use that instead of contig(). Similarly, busdma_bounce probably would be (better) served by allocations from freelist. Both of them do not need a run of pages. kib: In fact, e.g. on amd64 I think VM_FREELIST_DMA32 could get more uses than it has now. For… | |||||
Done Inline ActionsI will change the diff to only reclaim reservations if freelist == VM_NFREELIST then, but if vm_page_alloc_freelist() develops more users then some other solution is needed to avoid spurious allocation failures on amd64. Why would using vm_page_alloc_freelist() be an improvement for busdma, aside from simplifying the calling code? markj: I will change the diff to only reclaim reservations if `freelist == VM_NFREELIST` then, but if… | |||||
Not Done Inline Actions
I did not rechecked it, but isn't alloc_contig() iterates over segments that fit into the low,high interval, while alloc_freelist() takes the page directly from the freelist. I.e. it is O(1) vs. O(n)? kib: > Why would using vm_page_alloc_freelist() be an improvement for busdma, aside from simplifying… | |||||
Done Inline ActionsYes, that is true, though in practice I suspect it would not make much of a difference: alloc_contig will iterate over vm_phys segments looking for one that is in range. Since the vm_phys segments are sorted, it will visit the ones below 4GB first. Segments never cross the DMA32 boundary, so if allocating a single page, alloc_contig can check the segment free lists quickly, since any free page will satisfy the allocation. O(n) here really means O(num segments below 4G). markj: Yes, that is true, though in practice I suspect it would not make much of a difference… | |||||
Not Done Inline ActionsI would go as far as to claim that this split at 4G is rather useless, if not the DMA32. More, it is not obvious that the split is not wrong: IMO less segments we have, easier for VM is to operate. More, I would say that requirements of quite old hardware like usb 2.0/1.1 controllers should be satisfied with IOMMU and not by hacks in VM subsystem. But this is just a grumbling, I do not believe that we can realistically switch to this 'modern' approach. kib: I would go as far as to claim that this split at 4G is rather useless, if not the DMA32. More… | |||||
vm_reserv_reclaim_inactive(domain)) | |||||
goto again; | |||||
#endif | |||||
} | } | ||||
} | |||||
if (m == NULL) { | if (m == NULL) { | ||||
if (vm_domain_alloc_fail(vmd, NULL, req)) | if (vm_domain_alloc_fail(vmd, NULL, req)) | ||||
goto again; | goto again; | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
found: | found: | ||||
vm_page_dequeue(m); | vm_page_dequeue(m); | ||||
▲ Show 20 Lines • Show All 112 Lines • ▼ Show 20 Lines | if (vm_domain_allocate(vmd, req, npages)) { | ||||
* allocate them from the free page queues. | * allocate them from the free page queues. | ||||
*/ | */ | ||||
vm_domain_free_lock(vmd); | vm_domain_free_lock(vmd); | ||||
m_ret = vm_phys_alloc_contig(domain, npages, low, high, | m_ret = vm_phys_alloc_contig(domain, npages, low, high, | ||||
alignment, boundary); | alignment, boundary); | ||||
vm_domain_free_unlock(vmd); | vm_domain_free_unlock(vmd); | ||||
if (m_ret == NULL) { | if (m_ret == NULL) { | ||||
vm_domain_freecnt_inc(vmd, npages); | vm_domain_freecnt_inc(vmd, npages); | ||||
#if VM_NRESERVLEVEL > 0 | |||||
if (vm_reserv_reclaim_contig(domain, npages, low, | |||||
high, alignment, boundary)) | |||||
goto again; | |||||
#endif | |||||
} | } | ||||
} | } | ||||
if (m_ret == NULL) { | if (m_ret == NULL) { | ||||
if (vm_domain_alloc_fail(vmd, NULL, req)) | if (vm_domain_alloc_fail(vmd, NULL, req)) | ||||
goto again; | goto again; | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 3,102 Lines • Show Last 20 Lines |
I'm not sure how best to handle the freelist != VM_NFREELIST case here. It doesn't necessarily make sense to break reservations to satisfy vm_page_alloc_freelist(), and the old implementation didn't do that at all. OTOH, VM_NRESERVLEVEL is 0 on mips, and vm_page_alloc_freelist() is only used on mips.