fixed more bugs in xma
This commit is contained in:
		
							
								
								
									
										213
									
								
								hawk/lib/xma.c
									
									
									
									
									
								
							
							
						
						
									
										213
									
								
								hawk/lib/xma.c
									
									
									
									
									
								
							| @ -1,7 +1,7 @@ | |||||||
| /* | /* | ||||||
|  * $Id$ |  * $Id$ | ||||||
|  * |  * | ||||||
|     Copyright (c) 2006-2020 Chung, Hyung-Hwan. All rights reserved. |     Copyright (c) 2014-2019 Chung, Hyung-Hwan. All rights reserved. | ||||||
|  |  | ||||||
|     Redistribution and use in source and binary forms, with or without |     Redistribution and use in source and binary forms, with or without | ||||||
|     modification, are permitted provided that the following conditions |     modification, are permitted provided that the following conditions | ||||||
| @ -27,11 +27,31 @@ | |||||||
| #include <hawk-xma.h> | #include <hawk-xma.h> | ||||||
| #include "hawk-prv.h" | #include "hawk-prv.h" | ||||||
|  |  | ||||||
|  | /* set ALIGN to twice the pointer size to prevent unaligned memory access by | ||||||
|  |  * instructions dealing with data larger than the system word size. e.g. movaps on x86_64  | ||||||
|  |  *  | ||||||
|  |  * in the following run, movaps tries to write to the address 0x7fffea722f78. | ||||||
|  |  * since the instruction deals with 16-byte aligned data only, it triggered  | ||||||
|  |  * the general protection error. | ||||||
|  |  * | ||||||
|  | $ gdb ~/xxx/bin/hawk | ||||||
|  | Program received signal SIGSEGV, Segmentation fault. | ||||||
|  | 0x000000000042156a in set_global (rtx=rtx@entry=0x7fffea718ff8, idx=idx@entry=2, | ||||||
|  |     var=var@entry=0x0, val=val@entry=0x1, assign=assign@entry=0) at ../../../lib/run.c:358 | ||||||
|  | 358				rtx->gbl.fnr = lv; | ||||||
|  | (gdb) print &rtx->gbl.fnr | ||||||
|  | $1 = (hawk_int_t *) 0x7fffea722f78 | ||||||
|  | (gdb) disp /i 0x42156a | ||||||
|  | 1: x/i 0x42156a | ||||||
|  | => 0x42156a <set_global+874>:	movaps %xmm2,0x9f80(%rbp) | ||||||
|  | */ | ||||||
|  | #define ALIGN (HAWK_SIZEOF_VOID_P * 2) /* this must be a power of 2 */ | ||||||
|  |  | ||||||
| #define ALIGN HAWK_SIZEOF(hawk_oow_t) /* this must be a power of 2 */ | #define MBLKHDRSIZE (HAWK_SIZEOF(hawk_xma_mblk_t)) | ||||||
| #define MBLKHDRSIZE HAWK_SIZEOF(hawk_xma_mblk_t) | #define MINALLOCSIZE (HAWK_SIZEOF(hawk_xma_fblk_t) - HAWK_SIZEOF(hawk_xma_mblk_t)) | ||||||
| #define MINALLOCSIZE (ALIGN + ALIGN) /* as large as the free links in hawk_xma_fblk_t */ | #define FBLKMINSIZE (MBLKHDRSIZE + MINALLOCSIZE) /* or HAWK_SIZEOF(hawk_xma_fblk_t) - need space for the free links when the block is freeed */ | ||||||
| #define MINBLKLEN HAWK_SIZEOF(hawk_xma_fblk_t) /* need space for the free links when the block is freeed */ |  | ||||||
|  | /* NOTE: you must ensure that FBLKMINSIZE is equal to ALIGN or multiples of ALIGN */ | ||||||
|  |  | ||||||
| #define SYS_TO_USR(b) ((hawk_uint8_t*)(b) + MBLKHDRSIZE) | #define SYS_TO_USR(b) ((hawk_uint8_t*)(b) + MBLKHDRSIZE) | ||||||
| #define USR_TO_SYS(b) ((hawk_uint8_t*)(b) - MBLKHDRSIZE) | #define USR_TO_SYS(b) ((hawk_uint8_t*)(b) - MBLKHDRSIZE) | ||||||
| @ -52,6 +72,14 @@ | |||||||
| struct hawk_xma_mblk_t | struct hawk_xma_mblk_t | ||||||
| { | { | ||||||
| 	hawk_oow_t prev_size; | 	hawk_oow_t prev_size; | ||||||
|  |  | ||||||
|  | 	/* the block size is shifted by 1 bit and the maximum value is | ||||||
|  | 	 * offset by 1 bit because of the 'free' bit-field. | ||||||
|  | 	 * i could keep 'size' without shifting with bit manipulation | ||||||
|  | 	 * because the actual size is aligned and the last bit will | ||||||
|  | 	 * never be 1. i don't think there is a practical use case where | ||||||
|  | 	 * you need to allocate a huge chunk covering the entire | ||||||
|  | 	 * address space of your machine. */ | ||||||
| 	hawk_oow_t free: 1; | 	hawk_oow_t free: 1; | ||||||
| 	hawk_oow_t size: HAWK_XMA_SIZE_BITS;/**< block size */ | 	hawk_oow_t size: HAWK_XMA_SIZE_BITS;/**< block size */ | ||||||
| }; | }; | ||||||
| @ -67,12 +95,18 @@ struct hawk_xma_fblk_t | |||||||
| 	hawk_xma_fblk_t* free_next; /**< link to the next free block */ | 	hawk_xma_fblk_t* free_next; /**< link to the next free block */ | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | /*#define VERIFY*/ | ||||||
| #if defined(VERIFY) | #if defined(VERIFY) | ||||||
| static void DBG_VERIFY (hawk_xma_t* xma, const char* desc) | static void DBG_VERIFY (hawk_xma_t* xma, const char* desc) | ||||||
| { | { | ||||||
| 	hawk_xma_mblk_t* tmp, * next; | 	hawk_xma_mblk_t* tmp, * next; | ||||||
| 	hawk_oow_t cnt; | 	hawk_oow_t cnt; | ||||||
| 	for (tmp = (hawk_xma_mblk_t*)xma->start, cnt = 0; (hawk_uint8_t*)tmp < xma->end; tmp = next, cnt++) | 	hawk_oow_t fsum, asum;  | ||||||
|  | #if defined(HAWK_XMA_ENABLE_STAT) | ||||||
|  | 	hawk_oow_t isum; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	for (tmp = (hawk_xma_mblk_t*)xma->start, cnt = 0, fsum = 0, asum = 0; (hawk_uint8_t*)tmp < xma->end; tmp = next, cnt++) | ||||||
| 	{ | 	{ | ||||||
| 		next = next_mblk(tmp); | 		next = next_mblk(tmp); | ||||||
|  |  | ||||||
| @ -84,7 +118,18 @@ static void DBG_VERIFY (hawk_xma_t* xma, const char* desc) | |||||||
| 		{ | 		{ | ||||||
| 			HAWK_ASSERT (next->prev_size == tmp->size); | 			HAWK_ASSERT (next->prev_size == tmp->size); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		if (tmp->free) fsum += tmp->size; | ||||||
|  | 		else asum += tmp->size; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | #if defined(HAWK_XMA_ENABLE_STAT) | ||||||
|  | 	isum = (xma->stat.nfree + xma->stat.nused) * MBLKHDRSIZE; | ||||||
|  | 	HAWK_ASSERT (asum == xma->stat.alloc); | ||||||
|  | 	HAWK_ASSERT (fsum == xma->stat.avail); | ||||||
|  | 	HAWK_ASSERT (isum == xma->stat.total - (xma->stat.alloc + xma->stat.avail)); | ||||||
|  | 	HAWK_ASSERT (asum + fsum + isum == xma->stat.total); | ||||||
|  | #endif | ||||||
| } | } | ||||||
| #else | #else | ||||||
| #define DBG_VERIFY(xma, desc) | #define DBG_VERIFY(xma, desc) | ||||||
| @ -144,6 +189,7 @@ static HAWK_INLINE hawk_oow_t getxfi (hawk_xma_t* xma, hawk_oow_t size) | |||||||
| 	return xfi; | 	return xfi; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| hawk_xma_t* hawk_xma_open (hawk_mmgr_t* mmgr, hawk_oow_t xtnsize, void* zoneptr, hawk_oow_t zonesize) | hawk_xma_t* hawk_xma_open (hawk_mmgr_t* mmgr, hawk_oow_t xtnsize, void* zoneptr, hawk_oow_t zonesize) | ||||||
| { | { | ||||||
| 	hawk_xma_t* xma; | 	hawk_xma_t* xma; | ||||||
| @ -169,7 +215,7 @@ void hawk_xma_close (hawk_xma_t* xma) | |||||||
|  |  | ||||||
| int hawk_xma_init (hawk_xma_t* xma, hawk_mmgr_t* mmgr, void* zoneptr, hawk_oow_t zonesize) | int hawk_xma_init (hawk_xma_t* xma, hawk_mmgr_t* mmgr, void* zoneptr, hawk_oow_t zonesize) | ||||||
| { | { | ||||||
| 	hawk_xma_fblk_t* free; | 	hawk_xma_fblk_t* first; | ||||||
| 	hawk_oow_t xfi; | 	hawk_oow_t xfi; | ||||||
| 	int internal = 0; | 	int internal = 0; | ||||||
|  |  | ||||||
| @ -179,7 +225,7 @@ int hawk_xma_init (hawk_xma_t* xma, hawk_mmgr_t* mmgr, void* zoneptr, hawk_oow_t | |||||||
| 		zonesize = HAWK_ALIGN_POW2(zonesize, ALIGN); | 		zonesize = HAWK_ALIGN_POW2(zonesize, ALIGN); | ||||||
|  |  | ||||||
| 		/* adjust 'zonesize' to be large enough to hold a single smallest block */ | 		/* adjust 'zonesize' to be large enough to hold a single smallest block */ | ||||||
| 		if (zonesize < MINBLKLEN) zonesize = MINBLKLEN; | 		if (zonesize < FBLKMINSIZE) zonesize = FBLKMINSIZE; | ||||||
|  |  | ||||||
| 		zoneptr = HAWK_MMGR_ALLOC(mmgr, zonesize); | 		zoneptr = HAWK_MMGR_ALLOC(mmgr, zonesize); | ||||||
| 		if (HAWK_UNLIKELY(!zoneptr)) return -1; | 		if (HAWK_UNLIKELY(!zoneptr)) return -1; | ||||||
| @ -187,14 +233,14 @@ int hawk_xma_init (hawk_xma_t* xma, hawk_mmgr_t* mmgr, void* zoneptr, hawk_oow_t | |||||||
| 		internal = 1; | 		internal = 1; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	free = (hawk_xma_fblk_t*)zoneptr; | 	first = (hawk_xma_fblk_t*)zoneptr; | ||||||
|  |  | ||||||
| 	/* initialize the header part of the free chunk. the entire zone is a single free block */ | 	/* initialize the header part of the free chunk. the entire zone is a single free block */ | ||||||
| 	free->prev_size = 0; | 	first->prev_size = 0; | ||||||
| 	free->free = 1; | 	first->free = 1; | ||||||
| 	free->size = zonesize - MBLKHDRSIZE; /* size excluding the block header */ | 	first->size = zonesize - MBLKHDRSIZE; /* size excluding the block header */ | ||||||
| 	free->free_prev = HAWK_NULL; | 	first->free_prev = HAWK_NULL; | ||||||
| 	free->free_next = HAWK_NULL; | 	first->free_next = HAWK_NULL; | ||||||
|  |  | ||||||
| 	HAWK_MEMSET (xma, 0, HAWK_SIZEOF(*xma)); | 	HAWK_MEMSET (xma, 0, HAWK_SIZEOF(*xma)); | ||||||
| 	xma->_mmgr = mmgr; | 	xma->_mmgr = mmgr; | ||||||
| @ -203,13 +249,13 @@ int hawk_xma_init (hawk_xma_t* xma, hawk_mmgr_t* mmgr, void* zoneptr, hawk_oow_t | |||||||
| 	/* at this point, the 'free' chunk is a only block available */ | 	/* at this point, the 'free' chunk is a only block available */ | ||||||
|  |  | ||||||
| 	/* get the free block index */ | 	/* get the free block index */ | ||||||
| 	xfi = getxfi(xma, free->size); | 	xfi = getxfi(xma, first->size); | ||||||
| 	/* locate it into an apporopriate slot */ | 	/* locate it into an apporopriate slot */ | ||||||
| 	xma->xfree[xfi] = free;  | 	xma->xfree[xfi] = first;  | ||||||
| 	/* let it be the head, which is natural with only a block */ | 	/* let it be the head, which is natural with only a block */ | ||||||
| 	xma->start = (hawk_uint8_t*)free; | 	xma->start = (hawk_uint8_t*)first; | ||||||
| 	xma->end = xma->start + zonesize; | 	xma->end = xma->start + zonesize; | ||||||
| 	xma->internal = internal; | 	xma->internal = 1; | ||||||
|  |  | ||||||
| 	/* initialize some statistical variables */ | 	/* initialize some statistical variables */ | ||||||
| #if defined(HAWK_XMA_ENABLE_STAT) | #if defined(HAWK_XMA_ENABLE_STAT) | ||||||
| @ -267,6 +313,7 @@ static HAWK_INLINE void detach_from_freelist (hawk_xma_t* xma, hawk_xma_fblk_t* | |||||||
| 	{ | 	{ | ||||||
| 		/* the previous item does not exist. the block is the first | 		/* the previous item does not exist. the block is the first | ||||||
|  		 * item in the free list. */ |  		 * item in the free list. */ | ||||||
|  |  | ||||||
| 		hawk_oow_t xfi = getxfi(xma, b->size); | 		hawk_oow_t xfi = getxfi(xma, b->size); | ||||||
| 		HAWK_ASSERT (b == xma->xfree[xfi]); | 		HAWK_ASSERT (b == xma->xfree[xfi]); | ||||||
| 		/* let's update the free list head */ | 		/* let's update the free list head */ | ||||||
| @ -291,7 +338,7 @@ static hawk_xma_fblk_t* alloc_from_freelist (hawk_xma_t* xma, hawk_oow_t xfi, ha | |||||||
| 			detach_from_freelist (xma, cand); | 			detach_from_freelist (xma, cand); | ||||||
|  |  | ||||||
| 			rem = cand->size - size; | 			rem = cand->size - size; | ||||||
| 			if (rem >= MINBLKLEN) | 			if (rem >= FBLKMINSIZE) | ||||||
| 			{ | 			{ | ||||||
| 				hawk_xma_mblk_t* y, * z; | 				hawk_xma_mblk_t* y, * z; | ||||||
|  |  | ||||||
| @ -299,10 +346,10 @@ static hawk_xma_fblk_t* alloc_from_freelist (hawk_xma_t* xma, hawk_oow_t xfi, ha | |||||||
| 				 * another block. let's split it  | 				 * another block. let's split it  | ||||||
| 				 */ | 				 */ | ||||||
|  |  | ||||||
| 				/* shrink the size of the 'free' block */ | 				/* shrink the size of the 'cand' block */ | ||||||
| 				cand->size = size; | 				cand->size = size; | ||||||
|  |  | ||||||
| 				/* let 'y' point to the remaining part */ | 				/* let 'tmp' point to the remaining part */ | ||||||
| 				y = next_mblk(cand); /* get the next adjacent block */ | 				y = next_mblk(cand); /* get the next adjacent block */ | ||||||
|  |  | ||||||
| 				/* initialize some fields */ | 				/* initialize some fields */ | ||||||
| @ -350,7 +397,7 @@ static hawk_xma_fblk_t* alloc_from_freelist (hawk_xma_t* xma, hawk_oow_t xfi, ha | |||||||
|  |  | ||||||
| void* hawk_xma_alloc (hawk_xma_t* xma, hawk_oow_t size) | void* hawk_xma_alloc (hawk_xma_t* xma, hawk_oow_t size) | ||||||
| { | { | ||||||
| 	hawk_xma_fblk_t* free; | 	hawk_xma_fblk_t* cand; | ||||||
| 	hawk_oow_t xfi; | 	hawk_oow_t xfi; | ||||||
|  |  | ||||||
| 	DBG_VERIFY (xma, "alloc start"); | 	DBG_VERIFY (xma, "alloc start"); | ||||||
| @ -366,60 +413,60 @@ void* hawk_xma_alloc (hawk_xma_t* xma, hawk_oow_t size) | |||||||
| 	if (xfi < FIXED && xma->xfree[xfi]) | 	if (xfi < FIXED && xma->xfree[xfi]) | ||||||
| 	{ | 	{ | ||||||
| 		/* try the best fit */ | 		/* try the best fit */ | ||||||
| 		free = xma->xfree[xfi]; | 		cand = xma->xfree[xfi]; | ||||||
|  |  | ||||||
| 		HAWK_ASSERT (free->free != 0); | 		HAWK_ASSERT (cand->free != 0); | ||||||
| 		HAWK_ASSERT (free->size == size); | 		HAWK_ASSERT (cand->size == size); | ||||||
|  |  | ||||||
| 		detach_from_freelist (xma, free); | 		detach_from_freelist (xma, cand); | ||||||
| 		free->free = 0; | 		cand->free = 0; | ||||||
|  |  | ||||||
| #if defined(HAWK_XMA_ENABLE_STAT) | #if defined(HAWK_XMA_ENABLE_STAT) | ||||||
| 		xma->stat.nfree--; | 		xma->stat.nfree--; | ||||||
| 		xma->stat.nused++; | 		xma->stat.nused++; | ||||||
| 		xma->stat.alloc += free->size; | 		xma->stat.alloc += cand->size; | ||||||
| 		xma->stat.avail -= free->size; | 		xma->stat.avail -= cand->size; | ||||||
| #endif | #endif | ||||||
| 	} | 	} | ||||||
| 	else if (xfi == XFIMAX(xma)) | 	else if (xfi == XFIMAX(xma)) | ||||||
| 	{ | 	{ | ||||||
| 		/* huge block */ | 		/* huge block */ | ||||||
| 		free = alloc_from_freelist(xma, XFIMAX(xma), size); | 		cand = alloc_from_freelist(xma, XFIMAX(xma), size); | ||||||
| 		if (!free) return HAWK_NULL; | 		if (!cand) return HAWK_NULL; | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| 		if (xfi >= FIXED) | 		if (xfi >= FIXED) | ||||||
| 		{ | 		{ | ||||||
| 			/* get the block from its own large chain */ | 			/* get the block from its own large chain */ | ||||||
| 			free = alloc_from_freelist(xma, xfi, size); | 			cand = alloc_from_freelist(xma, xfi, size); | ||||||
| 			if (!free) | 			if (!cand) | ||||||
| 			{ | 			{ | ||||||
| 				/* borrow a large block from the huge block chain */ | 				/* borrow a large block from the huge block chain */ | ||||||
| 				free = alloc_from_freelist(xma, XFIMAX(xma), size); | 				cand = alloc_from_freelist(xma, XFIMAX(xma), size); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
| 			/* borrow a small block from the huge block chain */ | 			/* borrow a small block from the huge block chain */ | ||||||
| 			free = alloc_from_freelist(xma, XFIMAX(xma), size); | 			cand = alloc_from_freelist(xma, XFIMAX(xma), size); | ||||||
| 			if (!free) xfi = FIXED - 1; | 			if (!cand) xfi = FIXED - 1; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (!free) | 		if (!cand) | ||||||
| 		{ | 		{ | ||||||
| 			/* try each large block chain left */ | 			/* try each large block chain left */ | ||||||
| 			for (++xfi; xfi < XFIMAX(xma) - 1; xfi++) | 			for (++xfi; xfi < XFIMAX(xma) - 1; xfi++) | ||||||
| 			{ | 			{ | ||||||
| 				free = alloc_from_freelist(xma, xfi, size); | 				cand = alloc_from_freelist(xma, xfi, size); | ||||||
| 				if (free) break; | 				if (cand) break; | ||||||
| 			} | 			} | ||||||
| 			if (!free) return HAWK_NULL; | 			if (!cand) return HAWK_NULL; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	DBG_VERIFY (xma, "alloc end"); | 	DBG_VERIFY (xma, "alloc end"); | ||||||
| 	return SYS_TO_USR(free); | 	return SYS_TO_USR(cand); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void* _realloc_merge (hawk_xma_t* xma, void* b, hawk_oow_t size) | static void* _realloc_merge (hawk_xma_t* xma, void* b, hawk_oow_t size) | ||||||
| @ -438,11 +485,13 @@ static void* _realloc_merge (hawk_xma_t* xma, void* b, hawk_oow_t size) | |||||||
| 		hawk_xma_mblk_t* n; | 		hawk_xma_mblk_t* n; | ||||||
| 		hawk_oow_t rem; | 		hawk_oow_t rem; | ||||||
|  |  | ||||||
| 		req = size - blk->size; | 		req = size - blk->size; /* required size additionally */ | ||||||
|  |  | ||||||
| 		n = next_mblk(blk); | 		n = next_mblk(blk); | ||||||
| 		/* check if the next adjacent block is available */ | 		/* check if the next adjacent block is available */ | ||||||
| 		if ((hawk_uint8_t*)n >= xma->end || !n->free || req > n->size) return HAWK_NULL; /* no! */ | 		if ((hawk_uint8_t*)n >= xma->end || !n->free || req > n->size) return HAWK_NULL; /* no! */ | ||||||
|  | /* TODO: check more blocks if the next block is free but small in size. | ||||||
|  |  *       check the previous adjacent blocks also */ | ||||||
|  |  | ||||||
| 		HAWK_ASSERT (blk->size == n->prev_size); | 		HAWK_ASSERT (blk->size == n->prev_size); | ||||||
|  |  | ||||||
| @ -450,24 +499,24 @@ static void* _realloc_merge (hawk_xma_t* xma, void* b, hawk_oow_t size) | |||||||
| 		detach_from_freelist (xma, (hawk_xma_fblk_t*)n); | 		detach_from_freelist (xma, (hawk_xma_fblk_t*)n); | ||||||
|  |  | ||||||
| 		rem = (MBLKHDRSIZE + n->size) - req; | 		rem = (MBLKHDRSIZE + n->size) - req; | ||||||
| 		if (rem >= MINBLKLEN) | 		if (rem >= FBLKMINSIZE) | ||||||
| 		{ | 		{ | ||||||
| 			/*  | 			/*  | ||||||
| 			 * the remaining part of the next block is large enough  | 			 * the remaining part of the next block is large enough  | ||||||
| 			 * to hold a block. break the next block. | 			 * to hold a block. break the next block. | ||||||
| 			 */ | 			 */ | ||||||
|  |  | ||||||
| 			hawk_xma_mblk_t* tmp; | 			hawk_xma_mblk_t* y, * z; | ||||||
|  |  | ||||||
| 			blk->size += req; | 			blk->size += req; | ||||||
| 			tmp = next_mblk(blk); | 			y = next_mblk(blk); | ||||||
| 			tmp->free = 1; | 			y->free = 1; | ||||||
| 			tmp->size = rem - MBLKHDRSIZE; | 			y->size = rem - MBLKHDRSIZE; | ||||||
| 			tmp->prev_size = blk->size; | 			y->prev_size = blk->size; | ||||||
| 			attach_to_freelist (xma, (hawk_xma_fblk_t*)tmp); | 			attach_to_freelist (xma, (hawk_xma_fblk_t*)y); | ||||||
|  |  | ||||||
| 			n = next_mblk(tmp); | 			z = next_mblk(y); | ||||||
| 			if ((hawk_uint8_t*)n < xma->end) n->prev_size = tmp->size; | 			if ((hawk_uint8_t*)z < xma->end) z->prev_size = y->size; | ||||||
|  |  | ||||||
| #if defined(HAWK_XMA_ENABLE_STAT) | #if defined(HAWK_XMA_ENABLE_STAT) | ||||||
| 			xma->stat.alloc += req; | 			xma->stat.alloc += req; | ||||||
| @ -476,12 +525,14 @@ static void* _realloc_merge (hawk_xma_t* xma, void* b, hawk_oow_t size) | |||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
|  | 			hawk_xma_mblk_t* z; | ||||||
|  |  | ||||||
| 			/* the remaining part of the next block is too small to form an indepent block. | 			/* the remaining part of the next block is too small to form an indepent block. | ||||||
| 			 * utilize the whole block by merging to the resizing block */ | 			 * utilize the whole block by merging to the resizing block */ | ||||||
| 			blk->size += MBLKHDRSIZE + n->size; | 			blk->size += MBLKHDRSIZE + n->size; | ||||||
|  |  | ||||||
| 			n = next_mblk(blk); | 			z = next_mblk(blk); | ||||||
| 			if ((hawk_uint8_t*)n < xma->end) n->prev_size = blk->size; | 			if ((hawk_uint8_t*)z < xma->end) z->prev_size = blk->size; | ||||||
|  |  | ||||||
| #if defined(HAWK_XMA_ENABLE_STAT) | #if defined(HAWK_XMA_ENABLE_STAT) | ||||||
| 			xma->stat.nfree--; | 			xma->stat.nfree--; | ||||||
| @ -494,58 +545,59 @@ static void* _realloc_merge (hawk_xma_t* xma, void* b, hawk_oow_t size) | |||||||
| 	{ | 	{ | ||||||
| 		/* shrink the block */ | 		/* shrink the block */ | ||||||
| 		hawk_oow_t rem = blk->size - size; | 		hawk_oow_t rem = blk->size - size; | ||||||
| 		if (rem >= MINBLKLEN)  | 		if (rem >= FBLKMINSIZE)  | ||||||
| 		{ | 		{ | ||||||
| 			hawk_xma_mblk_t* tmp; |  | ||||||
| 			hawk_xma_mblk_t* n; | 			hawk_xma_mblk_t* n; | ||||||
|  |  | ||||||
| 			n = next_mblk(blk); | 			n = next_mblk(blk); | ||||||
|  |  | ||||||
| 			/* the leftover is large enough to hold a block of minimum size. | 			/* the leftover is large enough to hold a block of minimum size.split the current block */ | ||||||
| 			 * split the current block. let 'tmp' point to the leftover. */ |  | ||||||
| 			if ((hawk_uint8_t*)n < xma->end && n->free) | 			if ((hawk_uint8_t*)n < xma->end && n->free) | ||||||
| 			{ | 			{ | ||||||
| 				/* let the leftover block merge with the next block */ | 				hawk_xma_mblk_t* y, * z; | ||||||
|  |  | ||||||
|  | 				/* make the leftover block merge with the next block */ | ||||||
|  |  | ||||||
| 				detach_from_freelist (xma, (hawk_xma_fblk_t*)n); | 				detach_from_freelist (xma, (hawk_xma_fblk_t*)n); | ||||||
|  |  | ||||||
| 				blk->size = size; | 				blk->size = size; | ||||||
|  |  | ||||||
| 				tmp = next_mblk(blk); | 				y = next_mblk(blk); /* update y to the leftover block with the new block size set above */ | ||||||
| 				tmp->free = 1; | 				y->free = 1; | ||||||
| 				tmp->size = rem + n->size; | 				y->size = rem + n->size; /* add up the adjust block - (rem + MBLKHDRSIZE(n) + n->size) - MBLKHDRSIZE(y) */ | ||||||
| 				tmp->prev_size = blk->size; | 				y->prev_size = blk->size; | ||||||
|  |  | ||||||
| 				/* add 'tmp' to the free list */ | 				/* add 'y' to the free list */ | ||||||
| 				attach_to_freelist (xma, (hawk_xma_fblk_t*)tmp); | 				attach_to_freelist (xma, (hawk_xma_fblk_t*)y); | ||||||
|  |  | ||||||
| 				n = next_mblk(tmp); |  | ||||||
| 				if ((hawk_uint8_t*)n < xma->end) n->prev_size = tmp->size; |  | ||||||
|  |  | ||||||
|  | 				z = next_mblk(y); /* get adjacent block to the merged block */ | ||||||
|  | 				if ((hawk_uint8_t*)z < xma->end) z->prev_size = y->size; | ||||||
|  |  | ||||||
| #if defined(HAWK_XMA_ENABLE_STAT) | #if defined(HAWK_XMA_ENABLE_STAT) | ||||||
| 				xma->stat.alloc -= rem; | 				xma->stat.alloc -= rem; | ||||||
| 				/* rem - MBLKHDRSIZE(tmp) + MBLKHDRSIZE(n) */ | 				xma->stat.avail += rem; /* rem - MBLKHDRSIZE(y) + MBLKHDRSIZE(n) */ | ||||||
| 				xma->stat.avail += rem; |  | ||||||
| #endif | #endif | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
|  | 				hawk_xma_mblk_t* y; | ||||||
|  |  | ||||||
| 				/* link the leftover block to the free list */ | 				/* link the leftover block to the free list */ | ||||||
| 				blk->size = size; | 				blk->size = size; | ||||||
|  |  | ||||||
| 				tmp = next_mblk(blk); | 				y = next_mblk(blk); /* update y to the leftover block with the new block size set above */ | ||||||
| 				tmp->free = 1; | 				y->free = 1; | ||||||
| 				tmp->size = rem - MBLKHDRSIZE; | 				y->size = rem - MBLKHDRSIZE; | ||||||
| 				tmp->prev_size = blk->size; | 				y->prev_size = blk->size; | ||||||
|  |  | ||||||
| 				attach_to_freelist (xma, (hawk_xma_fblk_t*)tmp); | 				attach_to_freelist (xma, (hawk_xma_fblk_t*)y); | ||||||
| 				/*n = next_mblk(tmp); | 				/*n = next_mblk(y); | ||||||
| 				if ((hawk_uint8_t*)n < xma->end)*/ n->prev_size = tmp->size; | 				if ((hawk_uint8_t*)n < xma->end)*/ n->prev_size = y->size; | ||||||
|  |  | ||||||
| #if defined(HAWK_XMA_ENABLE_STAT) | #if defined(HAWK_XMA_ENABLE_STAT) | ||||||
| 				xma->stat.nfree++; | 				xma->stat.nfree++; | ||||||
| 				xma->stat.alloc -= rem; | 				xma->stat.alloc -= rem; | ||||||
| 				xma->stat.avail += tmp->size; | 				xma->stat.avail += y->size; | ||||||
| #endif | #endif | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @ -625,7 +677,7 @@ void hawk_xma_free (hawk_xma_t* xma, void* b) | |||||||
| 		 * | 		 * | ||||||
| 		 */ | 		 */ | ||||||
| 		 | 		 | ||||||
| 		hawk_xma_mblk_t* z; | 		hawk_xma_mblk_t* z = next_mblk(y); | ||||||
| 		hawk_oow_t ns = MBLKHDRSIZE + blk->size + MBLKHDRSIZE; | 		hawk_oow_t ns = MBLKHDRSIZE + blk->size + MBLKHDRSIZE; | ||||||
| 		hawk_oow_t bs = ns + y->size; | 		hawk_oow_t bs = ns + y->size; | ||||||
|  |  | ||||||
| @ -704,17 +756,16 @@ void hawk_xma_free (hawk_xma_t* xma, void* b) | |||||||
| 		 */ | 		 */ | ||||||
| #if defined(HAWK_XMA_ENABLE_STAT) | #if defined(HAWK_XMA_ENABLE_STAT) | ||||||
| 		xma->stat.avail += MBLKHDRSIZE + blk->size; | 		xma->stat.avail += MBLKHDRSIZE + blk->size; | ||||||
| 		//xma->stat.avail = 0; |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| 		detach_from_freelist (xma, (hawk_xma_fblk_t*)x); | 		detach_from_freelist (xma, (hawk_xma_fblk_t*)x); | ||||||
|  |  | ||||||
| 		x->size += MBLKHDRSIZE + blk->size; | 		x->size += MBLKHDRSIZE + blk->size; | ||||||
| 		//HAWK_ASSERT (y == next_mblk(x)); |  | ||||||
|  | 		HAWK_ASSERT (y == next_mblk(x)); | ||||||
| 		if ((hawk_uint8_t*)y < xma->end) y->prev_size = x->size; | 		if ((hawk_uint8_t*)y < xma->end) y->prev_size = x->size; | ||||||
|  |  | ||||||
| 		attach_to_freelist (xma, (hawk_xma_fblk_t*)x); | 		attach_to_freelist (xma, (hawk_xma_fblk_t*)x); | ||||||
|  |  | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user