#include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" void rmapfree(RMap* rmap, uintptr addr, uint size) { Map *mp; uint t; if(size == 0) return; lock(rmap); for(mp = rmap->map; mp->addr <= addr && mp->size; mp++) ; if(mp > rmap->map && (mp-1)->addr+(mp-1)->size == addr){ (mp-1)->size += size; if(addr+size == mp->addr){ (mp-1)->size += mp->size; while(mp->size){ mp++; (mp-1)->addr = mp->addr; (mp-1)->size = mp->size; } } }else{ if(addr+size == mp->addr && mp->size){ mp->addr -= size; mp->size += size; }else{ do{ if(mp >= rmap->mapend){ print("mapfree: %s: losing 0x%luX, %ud\n", rmap->name, addr, size); break; } t = mp->addr; mp->addr = addr; addr = t; t = mp->size; mp->size = size; mp++; }while((size = t) != 0); } } unlock(rmap); } uintptr rmapalloc(RMap* rmap, uintptr addr, uint size, int align) { Map *mp; ulong maddr, oaddr; lock(rmap); for(mp = rmap->map; mp->size; mp++){ maddr = mp->addr; if(addr){ /* * A specific address range has been given: * if the current map entry is greater then * the address is not in the map; * if the current map entry does not overlap * the beginning of the requested range then * continue on to the next map entry; * if the current map entry does not entirely * contain the requested range then the range * is not in the map. */ if(maddr > addr) break; if(mp->size < addr - maddr) /* maddr+mp->size < addr, but no overflow */ continue; if(addr - maddr > mp->size - size) /* addr+size > maddr+mp->size, but no overflow */ break; maddr = addr; } if(align > 0) maddr = ((maddr+align-1)/align)*align; if(mp->addr+mp->size-maddr < size) continue; oaddr = mp->addr; mp->addr = maddr+size; mp->size -= maddr-oaddr+size; if(mp->size == 0){ do{ mp++; (mp-1)->addr = mp->addr; }while((mp-1)->size = mp->size); } unlock(rmap); if(oaddr != maddr) rmapfree(rmap, oaddr, maddr-oaddr); return maddr; } unlock(rmap); return 0; }