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; 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, int uAddrSpaceMmap(struct uAddrSpace *as, uaddr_t *uaddr, size_t size, uint32_t rights,
uint32_t flags, struct mappedRessource *res, uint32_t offset ) 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->right = rights;
reg->res = res; reg->res = res;
reg->offset = offset; reg->offset = offset;
// TODO merge it with prev/next one
// keep the AddrSpace list sorted // keep the AddrSpace list sorted
struct uAddrVirtualReg *prev = findVirtualRegionBeforeAddr(as, hint_uaddr); struct uAddrVirtualReg *prev = findVirtualRegionBeforeAddr(as, hint_uaddr);
if (prev) bool_t regIsNew = TRUE;
list_insert_after_named(as->listVirtualReg, prev, reg, prevInAddrSpace, if (prev) {
nextInAddrSpace); struct uAddrVirtualReg *toFree = uAddrSpaceMergeVr(prev, reg);
else 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(as->listVirtualReg, reg, prevInAddrSpace, nextInAddrSpace);
list_add_tail_named(reg->res->listVirtualReg, reg, prevInMappedRes, nextInMappedRes); if (regIsNew) {
if (res->onResMapped) { list_add_tail_named(reg->res->listVirtualReg, reg, prevInMappedRes, nextInMappedRes);
int cbret = res->onResMapped(reg); if (res->onResMapped) {
if (cbret) { int cbret = res->onResMapped(reg);
pr_devel("Call back failed on ressource mmaped\n"); if (cbret) {
ret = uAddrSpaceUnmap(as, reg->addr, reg->size); pr_devel("Call back failed on ressource mmaped\n");
ret = uAddrSpaceUnmap(as, reg->addr, reg->size);
}
} }
}
if (res->ops->open) if (res->ops->open)
res->ops->open(reg); res->ops->open(reg);
}
*uaddr = hint_uaddr; *uaddr = hint_uaddr;