upstream (lemon) mplite tweaks.

This commit is contained in:
Kelvin Sherlock 2016-07-18 21:54:08 -04:00
parent c3b235ee95
commit ac3c3293d1
2 changed files with 33 additions and 27 deletions

View File

@ -307,19 +307,17 @@ static int mplite_logarithm(const int iValue)
} }
/* /*
** Return the size of an outstanding allocation, in bytes. The ** Return the size of an outstanding allocation, in bytes.
** size returned omits the 8-byte header overhead. This only ** This only works for chunks that are currently checked out.
** works for chunks that are currently checked out.
*/ */
static int mplite_size(const mplite_t *handle, const void *p) static int mplite_size(const mplite_t *handle, const void *p)
{ {
int iSize = 0; int iSize, i;
if (p) { assert( p!=0 );
int i = (int)((uint8_t *) p - handle->zPool) / handle->szAtom; i = (int)((uint8_t *) p - handle->zPool) / handle->szAtom;
assert(i >= 0 && i < handle->nBlock); assert(i >= 0 && i < handle->nBlock);
iSize = handle->szAtom * iSize = handle->szAtom * (1 << (handle->aCtrl[i] & MPLITE_CTRL_LOGSIZE));
(1 << (handle->aCtrl[i] & MPLITE_CTRL_LOGSIZE));
}
return iSize; return iSize;
} }
@ -388,19 +386,15 @@ static void *mplite_malloc_unsafe(mplite_t *handle, const int nByte)
/* nByte must be a positive */ /* nByte must be a positive */
assert(nByte > 0); assert(nByte > 0);
/* No more than 1GiB per allocation */
if( nByte > MPLITE_MAX_ALLOC_SIZE ) return 0;
/* Keep track of the maximum allocation request. Even unfulfilled /* Keep track of the maximum allocation request. Even unfulfilled
** requests are counted */ ** requests are counted */
if ((uint32_t) nByte > handle->maxRequest) { if ((uint32_t) nByte > handle->maxRequest) {
handle->maxRequest = nByte; handle->maxRequest = nByte;
} }
/* Abort if the requested allocation size is larger than the largest
** power of two that we can represent using 32-bit signed integers.
*/
if (nByte > MPLITE_MAX_ALLOC_SIZE) {
return NULL;
}
/* Round nByte up to the next valid power of two */ /* Round nByte up to the next valid power of two */
for (iFullSz = handle->szAtom, iLogsize = 0; iFullSz < nByte; iFullSz *= 2, for (iFullSz = handle->szAtom, iLogsize = 0; iFullSz < nByte; iFullSz *= 2,
iLogsize++) { iLogsize++) {
@ -443,6 +437,12 @@ static void *mplite_malloc_unsafe(mplite_t *handle, const int nByte)
handle->maxOut = handle->currentOut; handle->maxOut = handle->currentOut;
} }
#ifdef MPLITE_DEBUG
/* Make sure the allocated memory does not assume that it is set to zero
** or retains a value from a previous allocation */
memset(&handle->zPool[i * handle->szAtom], 0xAA, iFullSz);
#endif
/* Return a pointer to the allocated memory. */ /* Return a pointer to the allocated memory. */
return (void*) &handle->zPool[i * handle->szAtom]; return (void*) &handle->zPool[i * handle->szAtom];
} }
@ -483,12 +483,12 @@ static void mplite_free_unsafe(mplite_t *handle, const void *pOld)
int iBuddy; int iBuddy;
if ((iBlock >> iLogsize) & 1) { if ((iBlock >> iLogsize) & 1) {
iBuddy = iBlock - size; iBuddy = iBlock - size;
assert(iBuddy >= 0);
} }
else { else {
iBuddy = iBlock + size; iBuddy = iBlock + size;
if (iBuddy >= handle->nBlock) break;
} }
assert(iBuddy >= 0);
if ((iBuddy + (1 << iLogsize)) > handle->nBlock) break;
if (handle->aCtrl[iBuddy] != (MPLITE_CTRL_FREE | iLogsize)) break; if (handle->aCtrl[iBuddy] != (MPLITE_CTRL_FREE | iLogsize)) break;
mplite_unlink(handle, iBuddy, iLogsize); mplite_unlink(handle, iBuddy, iLogsize);
iLogsize++; iLogsize++;
@ -503,5 +503,12 @@ static void mplite_free_unsafe(mplite_t *handle, const void *pOld)
} }
size *= 2; size *= 2;
} }
#ifdef MPLITE_DEBUG
/* Overwrite freed memory with the 0x55 bit pattern to verify that it is
** not used after being freed */
memset(&handle->zPool[iBlock * handle->szAtom], 0x55, size);
#endif
mplite_link(handle, iBlock, iLogsize); mplite_link(handle, iBlock, iLogsize);
} }

View File

@ -17,7 +17,7 @@
* *
* This memory allocator uses the following algorithm: * This memory allocator uses the following algorithm:
* *
* 1. All memory allocations sizes are rounded up to a power of 2. * 1. All memory allocation sizes are rounded up to a power of 2.
* *
* 2. If two adjacent free blocks are the halves of a larger block, * 2. If two adjacent free blocks are the halves of a larger block,
* then the two blocks are coalesced into the single larger block. * then the two blocks are coalesced into the single larger block.
@ -40,11 +40,7 @@
#ifndef MPLITE_H #ifndef MPLITE_H
#define MPLITE_H #define MPLITE_H
#ifdef _WIN32
#include "pstdint.h"
#else
#include <stdint.h> #include <stdint.h>
#endif /* #ifdef _WIN32 */
/** /**
* @brief The function call returns success * @brief The function call returns success
@ -114,9 +110,12 @@ typedef struct mplite {
uint32_t maxCount; /**< Maximum instantaneous currentCount */ uint32_t maxCount; /**< Maximum instantaneous currentCount */
uint32_t maxRequest; /**< Largest allocation (exclusive of internal frag) */ uint32_t maxRequest; /**< Largest allocation (exclusive of internal frag) */
int aiFreelist[MPLITE_LOGMAX + 1]; /**< List of free blocks. aiFreelist[0] /**
is a list of free blocks of size mplite_t.szAtom. aiFreelist[1] holds * Lists of free blocks. aiFreelist[0] is a list of free blocks of
blocks of size szAtom * 2 and so forth.*/ * size mplite_t.szAtom. aiFreelist[1] holds blocks of size szAtom*2.
* aiFreelist[2] holds free blocks of size szAtom*4. And so forth.
*/
int aiFreelist[MPLITE_LOGMAX + 1];
uint8_t *aCtrl; /**< Space for tracking which blocks are checked out and the uint8_t *aCtrl; /**< Space for tracking which blocks are checked out and the
size of each block. One byte per block. */ size of each block. One byte per block. */