[fib_algo][dxr] Merge adjacent empty range table chunks.

MFC after:	3 days
This commit is contained in:
Marko Zec 2021-09-20 06:30:45 +02:00
parent 5a01dea7e8
commit 2ac039f7be

View File

@ -418,14 +418,15 @@ chunk_ref(struct dxr_aux *da, uint32_t chunk)
fdesc->base = cdp->cd_base; fdesc->base = cdp->cd_base;
da->rtbl_top -= size; da->rtbl_top -= size;
da->unused_chunks_cnt--; da->unused_chunks_cnt--;
if (cdp->cd_max_size > size + 1) { if (cdp->cd_max_size > size) {
/* Split the range in two, need a new descriptor */ /* Split the range in two, need a new descriptor */
empty_cdp = uma_zalloc(chunk_zone, M_NOWAIT); empty_cdp = uma_zalloc(chunk_zone, M_NOWAIT);
if (empty_cdp == NULL) if (empty_cdp == NULL)
return (1); return (1);
empty_cdp->cd_cur_size = 0;
empty_cdp->cd_max_size = cdp->cd_max_size - size; empty_cdp->cd_max_size = cdp->cd_max_size - size;
empty_cdp->cd_base = cdp->cd_base + size; empty_cdp->cd_base = cdp->cd_base + size;
LIST_INSERT_AFTER(cdp, empty_cdp, cd_all_le); LIST_INSERT_BEFORE(cdp, empty_cdp, cd_all_le);
LIST_INSERT_AFTER(cdp, empty_cdp, cd_hash_le); LIST_INSERT_AFTER(cdp, empty_cdp, cd_hash_le);
da->all_chunks_cnt++; da->all_chunks_cnt++;
da->unused_chunks_cnt++; da->unused_chunks_cnt++;
@ -433,7 +434,7 @@ chunk_ref(struct dxr_aux *da, uint32_t chunk)
} }
LIST_REMOVE(cdp, cd_hash_le); LIST_REMOVE(cdp, cd_hash_le);
} else { } else {
/* Alloc a new descriptor */ /* Alloc a new descriptor at the top of the heap*/
cdp = uma_zalloc(chunk_zone, M_NOWAIT); cdp = uma_zalloc(chunk_zone, M_NOWAIT);
if (cdp == NULL) if (cdp == NULL)
return (1); return (1);
@ -441,6 +442,8 @@ chunk_ref(struct dxr_aux *da, uint32_t chunk)
cdp->cd_base = fdesc->base; cdp->cd_base = fdesc->base;
LIST_INSERT_HEAD(&da->all_chunks, cdp, cd_all_le); LIST_INSERT_HEAD(&da->all_chunks, cdp, cd_all_le);
da->all_chunks_cnt++; da->all_chunks_cnt++;
KASSERT(cdp->cd_base + cdp->cd_max_size == da->rtbl_top,
("dxr: %s %d", __FUNCTION__, __LINE__));
} }
cdp->cd_hash = hash; cdp->cd_hash = hash;
@ -473,12 +476,12 @@ static void
chunk_unref(struct dxr_aux *da, uint32_t chunk) chunk_unref(struct dxr_aux *da, uint32_t chunk)
{ {
struct direct_entry *fdesc = &da->direct_tbl[chunk]; struct direct_entry *fdesc = &da->direct_tbl[chunk];
struct chunk_desc *cdp; struct chunk_desc *cdp, *cdp2;
uint32_t base = fdesc->base; uint32_t base = fdesc->base;
uint32_t size = chunk_size(da, fdesc); uint32_t size = chunk_size(da, fdesc);
uint32_t hash = chunk_hash(da, fdesc); uint32_t hash = chunk_hash(da, fdesc);
/* Find an existing descriptor */ /* Find the corresponding descriptor */
LIST_FOREACH(cdp, &da->chunk_hashtbl[hash & CHUNK_HASH_MASK], LIST_FOREACH(cdp, &da->chunk_hashtbl[hash & CHUNK_HASH_MASK],
cd_hash_le) cd_hash_le)
if (cdp->cd_hash == hash && cdp->cd_cur_size == size && if (cdp->cd_hash == hash && cdp->cd_cur_size == size &&
@ -492,23 +495,50 @@ chunk_unref(struct dxr_aux *da, uint32_t chunk)
LIST_REMOVE(cdp, cd_hash_le); LIST_REMOVE(cdp, cd_hash_le);
da->unused_chunks_cnt++; da->unused_chunks_cnt++;
if (cdp->cd_base + cdp->cd_max_size != da->rtbl_top) { cdp->cd_cur_size = 0;
LIST_INSERT_HEAD(&da->unused_chunks, cdp, cd_hash_le);
return; /* Attempt to merge with the preceding chunk, if empty */
cdp2 = LIST_NEXT(cdp, cd_all_le);
if (cdp2 != NULL && cdp2->cd_cur_size == 0) {
KASSERT(cdp2->cd_base + cdp2->cd_max_size == cdp->cd_base,
("dxr: %s %d", __FUNCTION__, __LINE__));
LIST_REMOVE(cdp, cd_all_le);
da->all_chunks_cnt--;
LIST_REMOVE(cdp2, cd_hash_le);
da->unused_chunks_cnt--;
cdp2->cd_max_size += cdp->cd_max_size;
uma_zfree(chunk_zone, cdp);
cdp = cdp2;
} }
do { /* Attempt to merge with the subsequent chunk, if empty */
cdp2 = LIST_PREV(cdp, &da->all_chunks, chunk_desc, cd_all_le);
if (cdp2 != NULL && cdp2->cd_cur_size == 0) {
KASSERT(cdp->cd_base + cdp->cd_max_size == cdp2->cd_base,
("dxr: %s %d", __FUNCTION__, __LINE__));
LIST_REMOVE(cdp, cd_all_le);
da->all_chunks_cnt--;
LIST_REMOVE(cdp2, cd_hash_le);
da->unused_chunks_cnt--;
cdp2->cd_max_size += cdp->cd_max_size;
cdp2->cd_base = cdp->cd_base;
uma_zfree(chunk_zone, cdp);
cdp = cdp2;
}
if (cdp->cd_base + cdp->cd_max_size == da->rtbl_top) {
/* Free the chunk on the top of the range heap, trim the heap */
KASSERT(cdp == LIST_FIRST(&da->all_chunks),
("dxr: %s %d", __FUNCTION__, __LINE__));
da->all_chunks_cnt--; da->all_chunks_cnt--;
da->unused_chunks_cnt--; da->unused_chunks_cnt--;
da->rtbl_top -= cdp->cd_max_size; da->rtbl_top -= cdp->cd_max_size;
LIST_REMOVE(cdp, cd_all_le); LIST_REMOVE(cdp, cd_all_le);
uma_zfree(chunk_zone, cdp); uma_zfree(chunk_zone, cdp);
LIST_FOREACH(cdp, &da->unused_chunks, cd_hash_le) return;
if (cdp->cd_base + cdp->cd_max_size == da->rtbl_top) { }
LIST_REMOVE(cdp, cd_hash_le);
break; LIST_INSERT_HEAD(&da->unused_chunks, cdp, cd_hash_le);
}
} while (cdp != NULL);
} }
#ifdef DXR2 #ifdef DXR2