Merge close VR with same ressource mapped

This commit is contained in:
Mathieu Maret 2024-02-11 15:31:35 +01:00
parent 607fcc7121
commit 026618a730
1 changed files with 46 additions and 14 deletions

View File

@ -317,6 +317,17 @@ free_ppage:
return -1;
}
static struct uAddrVirtualReg *uAddrSpaceMergeVr(struct uAddrVirtualReg *prev,
struct uAddrVirtualReg *next)
{
if (prev && next && prev->addr + prev->size == next->addr && prev->right == next->right &&
prev->res == next->res && prev->flags == next->flags && prev->offset == next->offset) {
prev->size += next->size;
return next;
} else
return NULL;
}
int uAddrSpaceMmap(struct uAddrSpace *as, uaddr_t *uaddr, size_t size, uint32_t rights,
uint32_t flags, struct mappedRessource *res, uint32_t offset )
{
@ -363,27 +374,48 @@ int uAddrSpaceMmap(struct uAddrSpace *as, uaddr_t *uaddr, size_t size, uint32_t
reg->right = rights;
reg->res = res;
reg->offset = offset;
// TODO merge it with prev/next one
// keep the AddrSpace list sorted
struct uAddrVirtualReg *prev = findVirtualRegionBeforeAddr(as, hint_uaddr);
if (prev)
list_insert_after_named(as->listVirtualReg, prev, reg, prevInAddrSpace,
nextInAddrSpace);
else
bool_t regIsNew = TRUE;
if (prev) {
struct uAddrVirtualReg *toFree = uAddrSpaceMergeVr(prev, reg);
if (toFree) {
pr_devel("Merge VR with prev\n");
reg = prev;
regIsNew = FALSE;
free(toFree);
}
toFree = uAddrSpaceMergeVr(reg, prev->nextInAddrSpace);
if (toFree) {
pr_devel("Merge VR with next\n");
regIsNew = FALSE;
if (toFree->res && toFree->res->ops && toFree->res->ops->close)
toFree->res->ops->close(toFree);
list_delete_named(as->listVirtualReg, toFree, prevInAddrSpace, nextInAddrSpace);
list_delete_named(toFree->res->listVirtualReg, toFree, prevInMappedRes,
nextInMappedRes);
free(toFree);
}
if (regIsNew)
list_insert_after_named(as->listVirtualReg, prev, reg, prevInAddrSpace,
nextInAddrSpace);
} else
list_add_tail_named(as->listVirtualReg, reg, prevInAddrSpace, nextInAddrSpace);
list_add_tail_named(reg->res->listVirtualReg, reg, prevInMappedRes, nextInMappedRes);
if (res->onResMapped) {
int cbret = res->onResMapped(reg);
if (cbret) {
pr_devel("Call back failed on ressource mmaped\n");
ret = uAddrSpaceUnmap(as, reg->addr, reg->size);
if (regIsNew) {
list_add_tail_named(reg->res->listVirtualReg, reg, prevInMappedRes, nextInMappedRes);
if (res->onResMapped) {
int cbret = res->onResMapped(reg);
if (cbret) {
pr_devel("Call back failed on ressource mmaped\n");
ret = uAddrSpaceUnmap(as, reg->addr, reg->size);
}
}
}
if (res->ops->open)
res->ops->open(reg);
if (res->ops->open)
res->ops->open(reg);
}
*uaddr = hint_uaddr;