diff options
| author | inmarket <inmarket@ugfx.org> | 2016-12-12 20:01:27 +1000 | 
|---|---|---|
| committer | inmarket <inmarket@ugfx.org> | 2016-12-12 20:01:27 +1000 | 
| commit | f495b49f53e3286c1dfa5e5d00aecd1048ebccbe (patch) | |
| tree | eee00d76362b790133c87ca59ad7fa38be127b07 /src | |
| parent | bc7a2b05c1e3e69c93a1381a343d32e18907c782 (diff) | |
| download | uGFX-f495b49f53e3286c1dfa5e5d00aecd1048ebccbe.tar.gz uGFX-f495b49f53e3286c1dfa5e5d00aecd1048ebccbe.tar.bz2 uGFX-f495b49f53e3286c1dfa5e5d00aecd1048ebccbe.zip | |
Update the Raw32 heap allocator to remove a memory merging bug.
The new code has less allocation overhead but memory blocks are now not tracked while allocated.
Diffstat (limited to 'src')
| -rw-r--r-- | src/gos/gos_x_heap.c | 112 | 
1 files changed, 50 insertions, 62 deletions
| diff --git a/src/gos/gos_x_heap.c b/src/gos/gos_x_heap.c index 7e79d1c6..813d0199 100644 --- a/src/gos/gos_x_heap.c +++ b/src/gos/gos_x_heap.c @@ -34,7 +34,6 @@  	// Slot structure - user memory follows  	typedef struct memslot { -		struct memslot *next;		// The next memslot  		size_t			sz;			// Includes the size of this memslot.  		} memslot; @@ -48,13 +47,10 @@  	#define Ptr2Slot(p)			((memslot *)(p) - 1)  	#define Slot2Ptr(pslot)		((pslot)+1) -	static memslot *			firstSlot; -	static memslot *			lastSlot;  	static memslot *			freeSlots;  	static char					heap[GFX_OS_HEAP_SIZE];  	void _gosHeapInit(void) { -		lastSlot = 0;  		gfxAddHeapBlock(heap, GFX_OS_HEAP_SIZE);  	} @@ -62,18 +58,12 @@  		if (sz < sizeof(memslot)+sizeof(freeslot))  			return; -		if (lastSlot) -			lastSlot->next = (memslot *)ptr; -		else -			firstSlot = lastSlot = freeSlots = (memslot *)ptr; - -		lastSlot->next = 0; -		lastSlot->sz = sz; -		NextFree(lastSlot) = 0; +		((memslot *)ptr)->sz = sz; +		gfxFree(Slot2Ptr((memslot *)ptr));  	}  	void *gfxAlloc(size_t sz) { -		register memslot *prev, *p, *new; +		register memslot *prev, *p, *pnew;  		if (!sz) return 0;  		sz = GetSlotSize(sz); @@ -81,23 +71,22 @@  			// Loop till we have a block big enough  			if (p->sz < sz)  				continue; +				  			// Can we save some memory by splitting this block?  			if (p->sz >= sz + sizeof(memslot)+sizeof(freeslot)) { -				new = (memslot *)((char *)p + sz); -				new->next = p->next; -				p->next = new; -				new->sz = p->sz - sz; +				pnew = (memslot *)((char *)p + sz); +				pnew->sz = p->sz - sz;  				p->sz = sz; -				if (lastSlot == p) -					lastSlot = new; -				NextFree(new) = NextFree(p); -				NextFree(p) = new; +				NextFree(pnew) = NextFree(p); +				NextFree(p) = pnew;  			} +			  			// Remove it from the free list  			if (prev)  				NextFree(prev) = NextFree(p);  			else  				freeSlots = NextFree(p); +				  			// Return the result found  			return Slot2Ptr(p);  		} @@ -106,7 +95,7 @@  	}  	void *gfxRealloc(void *ptr, size_t oldsz, size_t sz) { -		register memslot *prev, *p, *new; +		register memslot *prev, *p, *pfree;  		(void) oldsz;  		if (!ptr) @@ -120,19 +109,14 @@  		sz = GetSlotSize(sz);  		// If the next slot is free (and contiguous) merge it into this one -		if ((char *)p + p->sz == (char *)p->next) { -			for (prev = 0, new = freeSlots; new != 0; prev = new, new = NextFree(new)) { -				if (new == p->next) { -					p->next = new->next; -					p->sz += new->sz; -					if (prev) -						NextFree(prev) = NextFree(new); -					else -						freeSlots = NextFree(new); -					if (lastSlot == new) -						lastSlot = p; -					break; -				} +		for (prev = 0, pfree = freeSlots; pfree != 0; prev = pfree, pfree = NextFree(pfree)) { +			if (pfree == (memslot *)((char *)p + p->sz)) { +				p->sz += pfree->sz; +				if (prev) +					NextFree(prev) = NextFree(pfree); +				else +					freeSlots = NextFree(pfree); +				break;  			}  		} @@ -140,50 +124,54 @@  		if (sz < p->sz) {  			// Can we save some memory by splitting this block?  			if (p->sz >= sz + sizeof(memslot)+sizeof(freeslot)) { -				new = (memslot *)((char *)p + sz); -				new->next = p->next; -				p->next = new; -				new->sz = p->sz - sz; +				pfree = (memslot *)((char *)p + sz); +				pfree->sz = p->sz - sz;  				p->sz = sz; -				if (lastSlot == p) -					lastSlot = new; -				NextFree(new) = freeSlots; -				freeSlots = new; +				NextFree(pfree) = freeSlots; +				freeSlots = pfree;  			}  			return Slot2Ptr(p);  		}  		// We need to do this the hard way -		new = gfxAlloc(sz); -		if (new) +		pfree = gfxAlloc(sz); +		if (pfree)  			return 0; -		memcpy(new, ptr, p->sz - sizeof(memslot)); +		memcpy(pfree, ptr, p->sz - sizeof(memslot));  		gfxFree(ptr); -		return new; +		return pfree;  	}  	void gfxFree(void *ptr) { -		register memslot *prev, *p, *new; +		register memslot *prev, *p, *pfree;  		if (!ptr)  			return;  		p = Ptr2Slot(ptr); -		// If the next slot is free (and contiguous) merge it into this one -		if ((char *)p + p->sz == (char *)p->next) { -			for (prev = 0, new = freeSlots; new != 0; prev = new, new = NextFree(new)) { -				if (new == p->next) { -					p->next = new->next; -					p->sz += new->sz; -					if (prev) -						NextFree(prev) = NextFree(new); -					else -						freeSlots = NextFree(new); -					if (lastSlot == new) -						lastSlot = p; -					break; -				} +		// Find a free slot that is contiguous precceding and merge it into us +		for (prev = 0, pfree = freeSlots; pfree != 0; prev = pfree, pfree = NextFree(pfree)) { +			if (p == (memslot *)((char *)pfree + pfree->sz)) { +				pfree->sz += p->sz; +				if (prev) +					NextFree(prev) = NextFree(pfree); +				else +					freeSlots = NextFree(pfree); +				p = pfree; +				break; +			} +		} +		 +		// Find a free slot that is contiguous after and merge it into this one +		for (prev = 0, pfree = freeSlots; pfree != 0; prev = pfree, pfree = NextFree(pfree)) { +			if (pfree == (memslot *)((char *)p + p->sz)) { +				p->sz += pfree->sz; +				if (prev) +					NextFree(prev) = NextFree(pfree); +				else +					freeSlots = NextFree(pfree); +				break;  			}  		} | 
