123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- #include "u.h"
- #include "../port/lib.h"
- #include "mem.h"
- #include "dat.h"
- #include "fns.h"
- typedef struct Map Map;
- struct Map {
- uint32_t size;
- uint32_t addr;
- };
- typedef struct RMap RMap;
- struct RMap {
- char* name;
- Map* map;
- Map* mapend;
- Lock Lock;
- };
- void
- rmapfree(RMap* rmap, uintptr_t addr, uint size)
- {
- Map *mp;
- uint t;
- if(size == 0)
- return;
- lock(&rmap->Lock);
- 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%lX, %u\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->Lock);
- }
- uintptr_t
- rmapalloc(RMap* rmap, uintptr_t addr, uint size, int align)
- {
- Map *mp;
- uint32_t maddr, oaddr;
- lock(&rmap->Lock);
- 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->Lock);
- if(oaddr != maddr)
- rmapfree(rmap, oaddr, maddr-oaddr);
- return maddr;
- }
- unlock(&rmap->Lock);
- return 0;
- }
|