mirror of
https://github.com/ksherlock/mpw.git
synced 2024-11-22 00:32:44 +00:00
mplite
This commit is contained in:
parent
271bc85c37
commit
0d594d9e31
@ -9,3 +9,4 @@ cmake_minimum_required(VERSION 2.6)
|
||||
add_subdirectory(bin)
|
||||
add_subdirectory(cpu)
|
||||
add_subdirectory(toolbox)
|
||||
add_subdirectory(mplite)
|
5
mplite/CMakeLists.txt
Normal file
5
mplite/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
set(MPLITE_SRC mplite.c)
|
||||
|
||||
add_library(MPLITE_LIB ${MPLITE_SRC})
|
455
mplite/mplite.c
Normal file
455
mplite/mplite.c
Normal file
@ -0,0 +1,455 @@
|
||||
#include "mplite.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
** A minimum allocation is an instance of the following structure.
|
||||
** Larger allocations are an array of these structures where the
|
||||
** size of the array is a power of 2.
|
||||
**
|
||||
** The size of this object must be a power of two. That fact is
|
||||
** verified in mplite_init().
|
||||
*/
|
||||
typedef struct mplite_link mplite_link_t;
|
||||
|
||||
struct mplite_link {
|
||||
int next; /* Index of next free chunk */
|
||||
int prev; /* Index of previous free chunk */
|
||||
};
|
||||
|
||||
/*
|
||||
** Masks used for mplite_t.aCtrl[] elements.
|
||||
*/
|
||||
#define MPLITE_CTRL_LOGSIZE 0x1f /* Log2 Size of this block */
|
||||
#define MPLITE_CTRL_FREE 0x20 /* True if not checked out */
|
||||
|
||||
#ifdef _WIN32
|
||||
#define snprintf(buf, buf_size, format, ...) \
|
||||
_snprintf(buf, buf_size, format, ## __VA_ARGS__)
|
||||
#endif /* #ifdef _WIN32 */
|
||||
|
||||
/*
|
||||
** Assuming mplite_t.zPool is divided up into an array of mplite_link_t
|
||||
** structures, return a pointer to the idx-th such lik.
|
||||
*/
|
||||
#define mplite_getlink(handle, idx) ((mplite_link_t *) \
|
||||
(&handle->zPool[(idx) * handle->szAtom]))
|
||||
|
||||
#define mplite_enter(handle) if((handle != NULL) && \
|
||||
((handle)->lock.acquire != NULL)) \
|
||||
{ (handle)->lock.acquire((handle)->lock.arg); }
|
||||
#define mplite_leave(handle) if((handle != NULL) && \
|
||||
((handle)->lock.release != NULL)) \
|
||||
{ (handle)->lock.release((handle)->lock.arg); }
|
||||
|
||||
static int mplite_logarithm(const int iValue);
|
||||
static int mplite_size(const mplite_t *handle, const void *p);
|
||||
static void mplite_link(mplite_t *handle, const int i, const int iLogsize);
|
||||
static void mplite_unlink(mplite_t *handle, const int i, const int iLogsize);
|
||||
static int mplite_unlink_first(mplite_t *handle, const int iLogsize);
|
||||
static void *mplite_malloc_unsafe(mplite_t *handle, const int nByte);
|
||||
static void mplite_free_unsafe(mplite_t *handle, const void *pOld);
|
||||
|
||||
MPLITE_API int mplite_init(mplite_t *handle, const void *buf,
|
||||
const int buf_size, const int min_alloc,
|
||||
const mplite_lock_t *lock)
|
||||
{
|
||||
int ii; /* Loop counter */
|
||||
int nByte; /* Number of bytes of memory available to this allocator */
|
||||
uint8_t *zByte; /* Memory usable by this allocator */
|
||||
int nMinLog; /* Log base 2 of minimum allocation size in bytes */
|
||||
int iOffset; /* An offset into handle->aCtrl[] */
|
||||
|
||||
/* Check the parameters */
|
||||
if ((NULL == handle) || (NULL == buf) || (buf_size <= 0) ||
|
||||
(min_alloc <= 0)) {
|
||||
return MPLITE_ERR_INVPAR;
|
||||
}
|
||||
|
||||
/* Initialize the mplite_t object */
|
||||
memset(handle, 0, sizeof (*handle));
|
||||
|
||||
/* Copy the lock if it is not NULL */
|
||||
if (lock != NULL) {
|
||||
memcpy(&handle->lock, lock, sizeof (handle->lock));
|
||||
}
|
||||
|
||||
/* The size of a mplite_link_t object must be a power of two. Verify that
|
||||
** this is case.
|
||||
*/
|
||||
assert((sizeof (mplite_link_t)&(sizeof (mplite_link_t) - 1)) == 0);
|
||||
|
||||
nByte = buf_size;
|
||||
zByte = (uint8_t*) buf;
|
||||
|
||||
nMinLog = mplite_logarithm(min_alloc);
|
||||
handle->szAtom = (1 << nMinLog);
|
||||
while ((int) sizeof (mplite_link_t) > handle->szAtom) {
|
||||
handle->szAtom = handle->szAtom << 1;
|
||||
}
|
||||
|
||||
handle->nBlock = (nByte / (handle->szAtom + sizeof (uint8_t)));
|
||||
handle->zPool = zByte;
|
||||
handle->aCtrl = (uint8_t *) & handle->zPool[handle->nBlock * handle->szAtom];
|
||||
|
||||
for (ii = 0; ii <= MPLITE_LOGMAX; ii++) {
|
||||
handle->aiFreelist[ii] = -1;
|
||||
}
|
||||
|
||||
iOffset = 0;
|
||||
for (ii = MPLITE_LOGMAX; ii >= 0; ii--) {
|
||||
int nAlloc = (1 << ii);
|
||||
if ((iOffset + nAlloc) <= handle->nBlock) {
|
||||
handle->aCtrl[iOffset] = (uint8_t) (ii | MPLITE_CTRL_FREE);
|
||||
mplite_link(handle, iOffset, ii);
|
||||
iOffset += nAlloc;
|
||||
}
|
||||
assert((iOffset + nAlloc) > handle->nBlock);
|
||||
}
|
||||
|
||||
return MPLITE_OK;
|
||||
}
|
||||
|
||||
MPLITE_API void *mplite_malloc(mplite_t *handle, const int nBytes)
|
||||
{
|
||||
int64_t *p = 0;
|
||||
|
||||
/* Check the parameters */
|
||||
if ((NULL == handle) || (nBytes <= 0)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mplite_enter(handle);
|
||||
p = mplite_malloc_unsafe(handle, nBytes);
|
||||
mplite_leave(handle);
|
||||
|
||||
return (void*) p;
|
||||
}
|
||||
|
||||
MPLITE_API void mplite_free(mplite_t *handle, const void *pPrior)
|
||||
{
|
||||
/* Check the parameters */
|
||||
if ((NULL == handle) || (NULL == pPrior)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mplite_enter(handle);
|
||||
mplite_free_unsafe(handle, pPrior);
|
||||
mplite_leave(handle);
|
||||
}
|
||||
|
||||
MPLITE_API void *mplite_realloc(mplite_t *handle, const void *pPrior,
|
||||
const int nBytes)
|
||||
{
|
||||
int nOld;
|
||||
void *p;
|
||||
|
||||
/* Check the parameters */
|
||||
if ((NULL == handle) || (NULL == pPrior) || (nBytes <= 0) ||
|
||||
(nBytes & (nBytes - 1))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nOld = mplite_size(handle, pPrior);
|
||||
if (nBytes <= nOld) {
|
||||
return (void *) pPrior;
|
||||
}
|
||||
mplite_enter(handle);
|
||||
p = mplite_malloc_unsafe(handle, nBytes);
|
||||
if (p) {
|
||||
memcpy(p, pPrior, nOld);
|
||||
mplite_free_unsafe(handle, pPrior);
|
||||
}
|
||||
mplite_leave(handle);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
MPLITE_API int mplite_roundup(mplite_t *handle, const int n)
|
||||
{
|
||||
int iFullSz;
|
||||
|
||||
/* Check the parameters */
|
||||
if ((NULL == handle) || (n > MPLITE_MAX_ALLOC_SIZE)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (iFullSz = handle->szAtom; iFullSz < n; iFullSz *= 2);
|
||||
|
||||
return iFullSz;
|
||||
}
|
||||
|
||||
MPLITE_API void mplite_print_stats(const mplite_t * const handle,
|
||||
const mplite_putsfunc_t putsfunc)
|
||||
{
|
||||
if ((handle != NULL) && (putsfunc != NULL)) {
|
||||
char zStats[256];
|
||||
snprintf(zStats, sizeof (zStats), "Total number of calls to malloc: %u",
|
||||
(unsigned) handle->nAlloc);
|
||||
putsfunc(zStats);
|
||||
|
||||
snprintf(zStats, sizeof (zStats), "Total of all malloc calls - includes "
|
||||
"internal fragmentation: %u", (unsigned) handle->totalAlloc);
|
||||
putsfunc(zStats);
|
||||
|
||||
snprintf(zStats, sizeof (zStats), "Total internal fragmentation: %u",
|
||||
(unsigned) handle->totalExcess);
|
||||
putsfunc(zStats);
|
||||
|
||||
snprintf(zStats, sizeof (zStats), "Current checkout, including internal "
|
||||
"fragmentation: %u", handle->currentOut);
|
||||
putsfunc(zStats);
|
||||
|
||||
snprintf(zStats, sizeof (zStats), "Current number of distinct checkouts: %u",
|
||||
handle->currentCount);
|
||||
putsfunc(zStats);
|
||||
|
||||
snprintf(zStats, sizeof (zStats), "Maximum instantaneous currentOut: %u",
|
||||
handle->maxOut);
|
||||
putsfunc(zStats);
|
||||
|
||||
snprintf(zStats, sizeof (zStats), "Maximum instantaneous currentCount: %u",
|
||||
handle->maxCount);
|
||||
putsfunc(zStats);
|
||||
|
||||
snprintf(zStats, sizeof (zStats), "Largest allocation (exclusive of "
|
||||
"internal frag): %u", handle->maxRequest);
|
||||
putsfunc(zStats);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the ceiling of the logarithm base 2 of iValue.
|
||||
**
|
||||
** Examples: mplite_logarithm(1) -> 0
|
||||
** mplite_logarithm(2) -> 1
|
||||
** mplite_logarithm(4) -> 2
|
||||
** mplite_logarithm(5) -> 3
|
||||
** mplite_logarithm(8) -> 3
|
||||
** mplite_logarithm(9) -> 4
|
||||
*/
|
||||
static int mplite_logarithm(const int iValue)
|
||||
{
|
||||
int iLog;
|
||||
for (iLog = 0; (1 << iLog) < iValue; iLog++);
|
||||
return iLog;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the size of an outstanding allocation, in bytes. The
|
||||
** size returned omits the 8-byte header overhead. This only
|
||||
** works for chunks that are currently checked out.
|
||||
*/
|
||||
static int mplite_size(const mplite_t *handle, const void *p)
|
||||
{
|
||||
int iSize = 0;
|
||||
if (p) {
|
||||
int i = ((uint8_t *) p - handle->zPool) / handle->szAtom;
|
||||
assert(i >= 0 && i < handle->nBlock);
|
||||
iSize = handle->szAtom *
|
||||
(1 << (handle->aCtrl[i] & MPLITE_CTRL_LOGSIZE));
|
||||
}
|
||||
return iSize;
|
||||
}
|
||||
|
||||
/*
|
||||
** Link the chunk at handle->aPool[i] so that is on the iLogsize
|
||||
** free list.
|
||||
*/
|
||||
static void mplite_link(mplite_t *handle, const int i, const int iLogsize)
|
||||
{
|
||||
int x;
|
||||
assert(i >= 0 && i < handle->nBlock);
|
||||
assert(iLogsize >= 0 && iLogsize <= MPLITE_LOGMAX);
|
||||
assert((handle->aCtrl[i] & MPLITE_CTRL_LOGSIZE) == iLogsize);
|
||||
|
||||
x = mplite_getlink(handle, i)->next = handle->aiFreelist[iLogsize];
|
||||
mplite_getlink(handle, i)->prev = -1;
|
||||
if (x >= 0) {
|
||||
assert(x < handle->nBlock);
|
||||
mplite_getlink(handle, x)->prev = i;
|
||||
}
|
||||
handle->aiFreelist[iLogsize] = i;
|
||||
}
|
||||
|
||||
/*
|
||||
** Unlink the chunk at handle->aPool[i] from list it is currently
|
||||
** on. It should be found on handle->aiFreelist[iLogsize].
|
||||
*/
|
||||
static void mplite_unlink(mplite_t *handle, const int i, const int iLogsize)
|
||||
{
|
||||
int next, prev;
|
||||
assert(i >= 0 && i < handle->nBlock);
|
||||
assert(iLogsize >= 0 && iLogsize <= MPLITE_LOGMAX);
|
||||
assert((handle->aCtrl[i] & MPLITE_CTRL_LOGSIZE) == iLogsize);
|
||||
|
||||
next = mplite_getlink(handle, i)->next;
|
||||
prev = mplite_getlink(handle, i)->prev;
|
||||
if (prev < 0) {
|
||||
handle->aiFreelist[iLogsize] = next;
|
||||
}
|
||||
else {
|
||||
mplite_getlink(handle, prev)->next = next;
|
||||
}
|
||||
if (next >= 0) {
|
||||
mplite_getlink(handle, next)->prev = prev;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Find the first entry on the freelist iLogsize. Unlink that
|
||||
** entry and return its index.
|
||||
*/
|
||||
static int mplite_unlink_first(mplite_t *handle, const int iLogsize)
|
||||
{
|
||||
int i;
|
||||
int iFirst;
|
||||
|
||||
assert(iLogsize >= 0 && iLogsize <= MPLITE_LOGMAX);
|
||||
i = iFirst = handle->aiFreelist[iLogsize];
|
||||
assert(iFirst >= 0);
|
||||
while (i > 0) {
|
||||
if (i < iFirst) iFirst = i;
|
||||
i = mplite_getlink(handle, i)->next;
|
||||
}
|
||||
mplite_unlink(handle, iFirst, iLogsize);
|
||||
return iFirst;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return a block of memory of at least nBytes in size.
|
||||
** Return NULL if unable. Return NULL if nBytes==0.
|
||||
**
|
||||
** The caller guarantees that nByte positive.
|
||||
**
|
||||
** The caller has obtained a lock prior to invoking this
|
||||
** routine so there is never any chance that two or more
|
||||
** threads can be in this routine at the same time.
|
||||
*/
|
||||
static void *mplite_malloc_unsafe(mplite_t *handle, const int nByte)
|
||||
{
|
||||
int i; /* Index of a handle->aPool[] slot */
|
||||
int iBin; /* Index into handle->aiFreelist[] */
|
||||
int iFullSz; /* Size of allocation rounded up to power of 2 */
|
||||
int iLogsize; /* Log2 of iFullSz/POW2_MIN */
|
||||
|
||||
/* nByte must be a positive */
|
||||
assert(nByte > 0);
|
||||
|
||||
/* Keep track of the maximum allocation request. Even unfulfilled
|
||||
** requests are counted */
|
||||
if ((uint32_t) nByte > handle->maxRequest) {
|
||||
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 */
|
||||
for (iFullSz = handle->szAtom, iLogsize = 0; iFullSz < nByte; iFullSz *= 2,
|
||||
iLogsize++) {
|
||||
}
|
||||
|
||||
/* Make sure handle->aiFreelist[iLogsize] contains at least one free
|
||||
** block. If not, then split a block of the next larger power of
|
||||
** two in order to create a new free block of size iLogsize.
|
||||
*/
|
||||
for (iBin = iLogsize; handle->aiFreelist[iBin] < 0 && iBin <= MPLITE_LOGMAX;
|
||||
iBin++) {
|
||||
}
|
||||
if (iBin > MPLITE_LOGMAX) {
|
||||
return NULL;
|
||||
}
|
||||
i = mplite_unlink_first(handle, iBin);
|
||||
while (iBin > iLogsize) {
|
||||
int newSize;
|
||||
|
||||
iBin--;
|
||||
newSize = 1 << iBin;
|
||||
handle->aCtrl[i + newSize] = (uint8_t) (MPLITE_CTRL_FREE | iBin);
|
||||
mplite_link(handle, i + newSize, iBin);
|
||||
}
|
||||
handle->aCtrl[i] = (uint8_t) iLogsize;
|
||||
|
||||
/* Update allocator performance statistics. */
|
||||
handle->nAlloc++;
|
||||
handle->totalAlloc += iFullSz;
|
||||
handle->totalExcess += iFullSz - nByte;
|
||||
handle->currentCount++;
|
||||
handle->currentOut += iFullSz;
|
||||
if (handle->maxCount < handle->currentCount) {
|
||||
handle->maxCount = handle->currentCount;
|
||||
}
|
||||
if (handle->maxOut < handle->currentOut) {
|
||||
handle->maxOut = handle->currentOut;
|
||||
}
|
||||
|
||||
/* Return a pointer to the allocated memory. */
|
||||
return (void*) &handle->zPool[i * handle->szAtom];
|
||||
}
|
||||
|
||||
/*
|
||||
** Free an outstanding memory allocation.
|
||||
*/
|
||||
static void mplite_free_unsafe(mplite_t *handle, const void *pOld)
|
||||
{
|
||||
uint32_t size, iLogsize;
|
||||
int iBlock;
|
||||
|
||||
/* Set iBlock to the index of the block pointed to by pOld in
|
||||
** the array of handle->szAtom byte blocks pointed to by handle->zPool.
|
||||
*/
|
||||
iBlock = ((uint8_t *) pOld - handle->zPool) / handle->szAtom;
|
||||
|
||||
/* Check that the pointer pOld points to a valid, non-free block. */
|
||||
assert(iBlock >= 0 && iBlock < handle->nBlock);
|
||||
assert(((uint8_t *) pOld - handle->zPool) % handle->szAtom == 0);
|
||||
assert((handle->aCtrl[iBlock] & MPLITE_CTRL_FREE) == 0);
|
||||
|
||||
iLogsize = handle->aCtrl[iBlock] & MPLITE_CTRL_LOGSIZE;
|
||||
size = 1 << iLogsize;
|
||||
assert(iBlock + size - 1 < (uint32_t) handle->nBlock);
|
||||
|
||||
handle->aCtrl[iBlock] |= MPLITE_CTRL_FREE;
|
||||
handle->aCtrl[iBlock + size - 1] |= MPLITE_CTRL_FREE;
|
||||
assert(handle->currentCount > 0);
|
||||
assert(handle->currentOut >= (size * handle->szAtom));
|
||||
handle->currentCount--;
|
||||
handle->currentOut -= size * handle->szAtom;
|
||||
assert(handle->currentOut > 0 || handle->currentCount == 0);
|
||||
assert(handle->currentCount > 0 || handle->currentOut == 0);
|
||||
|
||||
handle->aCtrl[iBlock] = (uint8_t) (MPLITE_CTRL_FREE | iLogsize);
|
||||
while (iLogsize < MPLITE_LOGMAX) {
|
||||
int iBuddy;
|
||||
if ((iBlock >> iLogsize) & 1) {
|
||||
iBuddy = iBlock - size;
|
||||
}
|
||||
else {
|
||||
iBuddy = iBlock + size;
|
||||
}
|
||||
assert(iBuddy >= 0);
|
||||
if ((iBuddy + (1 << iLogsize)) > handle->nBlock) break;
|
||||
if (handle->aCtrl[iBuddy] != (MPLITE_CTRL_FREE | iLogsize)) break;
|
||||
mplite_unlink(handle, iBuddy, iLogsize);
|
||||
iLogsize++;
|
||||
if (iBuddy < iBlock) {
|
||||
handle->aCtrl[iBuddy] = (uint8_t) (MPLITE_CTRL_FREE | iLogsize);
|
||||
handle->aCtrl[iBlock] = 0;
|
||||
iBlock = iBuddy;
|
||||
}
|
||||
else {
|
||||
handle->aCtrl[iBlock] = (uint8_t) (MPLITE_CTRL_FREE | iLogsize);
|
||||
handle->aCtrl[iBuddy] = 0;
|
||||
}
|
||||
size *= 2;
|
||||
}
|
||||
mplite_link(handle, iBlock, iLogsize);
|
||||
}
|
222
mplite/mplite.h
Normal file
222
mplite/mplite.h
Normal file
@ -0,0 +1,222 @@
|
||||
/**
|
||||
* The author disclaims copyright to this source code. In place of
|
||||
* a legal notice, here is a blessing:
|
||||
*
|
||||
* May you do good and not evil.
|
||||
* May you find forgiveness for yourself and forgive others.
|
||||
* May you share freely, never taking more than you give.
|
||||
*
|
||||
* This file contains the APIs that implement a memory allocation subsystem
|
||||
* based on SQLite's memsys5 memory subsystem. Refer to
|
||||
* http://www.sqlite.org/malloc.html for more info.
|
||||
*
|
||||
* This version of the memory allocation subsystem omits all
|
||||
* use of malloc(). The application gives a block of memory
|
||||
* from which allocations are made and returned by the mplite_malloc()
|
||||
* and mplite_realloc() implementations.
|
||||
*
|
||||
* This memory allocator uses the following algorithm:
|
||||
*
|
||||
* 1. All memory allocations sizes are rounded up to a power of 2.
|
||||
*
|
||||
* 2. If two adjacent free blocks are the halves of a larger block,
|
||||
* then the two blocks are coalesed into the single larger block.
|
||||
*
|
||||
* 3. New memory is allocated from the first available free block.
|
||||
*
|
||||
* This algorithm is described in: J. M. Robson. "Bounds for Some Functions
|
||||
* Concerning Dynamic Storage Allocation". Journal of the Association for
|
||||
* Computing Machinery, Volume 21, Number 8, July 1974, pages 491-499.
|
||||
*
|
||||
* Let n be the size of the largest allocation divided by the minimum
|
||||
* allocation size (after rounding all sizes up to a power of 2.) Let M
|
||||
* be the maximum amount of memory ever outstanding at one time. Let
|
||||
* N be the total amount of memory available for allocation. Robson
|
||||
* proved that this memory allocator will never breakdown due to
|
||||
* fragmentation as long as the following constraint holds:
|
||||
*
|
||||
* N >= M*(1 + log2(n)/2) - n + 1
|
||||
*/
|
||||
#ifndef MPLITE_H
|
||||
#define MPLITE_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "pstdint.h"
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif /* #ifdef _WIN32 */
|
||||
|
||||
/**
|
||||
* @brief The function call returns success
|
||||
*/
|
||||
#define MPLITE_OK 0
|
||||
/**
|
||||
* @brief Invalid parameters are passed to a function
|
||||
*/
|
||||
#define MPLITE_ERR_INVPAR -1
|
||||
/**
|
||||
* @brief Macro to fix unused parameter compiler warning
|
||||
*/
|
||||
#define MPLITE_UNUSED_PARAM(param) (void)(param)
|
||||
/**
|
||||
* @brief Maximum size of any allocation is ((1 << @ref MPLITE_LOGMAX) *
|
||||
* mplite_t.szAtom). Since mplite_t.szAtom is always at least 8 and
|
||||
* 32-bit integers are used, it is not actually possible to reach this
|
||||
* limit.
|
||||
*/
|
||||
#define MPLITE_LOGMAX 30
|
||||
/**
|
||||
* @brief Maximum allocation size of this memory pool library. All allocations
|
||||
* must be a power of two and must be expressed by a 32-bit signed
|
||||
* integer. Hence the largest allocation is 0x40000000 or 1073741824.
|
||||
*/
|
||||
#define MPLITE_MAX_ALLOC_SIZE 0x40000000
|
||||
/**
|
||||
* @brief An indicator that a function is a public API
|
||||
*/
|
||||
#define MPLITE_API
|
||||
|
||||
/**
|
||||
* @brief Lock object to be used in a threadsafe memory pool
|
||||
*/
|
||||
typedef struct mplite_lock {
|
||||
void *arg; /**< Argument to be passed to acquire and release function
|
||||
pointers */
|
||||
int (*acquire)(void *arg); /**< Function pointer to acquire a lock */
|
||||
int (*release)(void *arg); /**< Function pointer to release a lock */
|
||||
} mplite_lock_t;
|
||||
|
||||
/**
|
||||
* @brief Memory pool object
|
||||
*/
|
||||
typedef struct mplite {
|
||||
/*-------------------------------
|
||||
Memory available for allocation
|
||||
-------------------------------*/
|
||||
int szAtom; /**< Smallest possible allocation in bytes */
|
||||
int nBlock; /**< Number of szAtom sized blocks in zPool */
|
||||
uint8_t *zPool; /**< Memory available to be allocated */
|
||||
|
||||
mplite_lock_t lock; /**< Lock to control access to the memory allocation
|
||||
subsystem. */
|
||||
|
||||
/*----------------------
|
||||
Performance statistics
|
||||
----------------------*/
|
||||
uint64_t nAlloc; /**< Total number of calls to malloc */
|
||||
uint64_t totalAlloc; /**< Total of all malloc calls - includes internal
|
||||
fragmentation */
|
||||
uint64_t totalExcess; /**< Total internal fragmentation */
|
||||
uint32_t currentOut; /**< Current checkout, including internal
|
||||
fragmentation */
|
||||
uint32_t currentCount; /**< Current number of distinct checkouts */
|
||||
uint32_t maxOut; /**< Maximum instantaneous currentOut */
|
||||
uint32_t maxCount; /**< Maximum instantaneous currentCount */
|
||||
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
|
||||
blocks of size szAtom * 2 and so forth.*/
|
||||
|
||||
uint8_t *aCtrl; /**< Space for tracking which blocks are checked out and the
|
||||
size of each block. One byte per block. */
|
||||
} mplite_t;
|
||||
|
||||
/**
|
||||
* @brief Print string function pointer to be passed to @ref mplite_print_stats
|
||||
* function. This must be same as stdio's puts function mechanism which
|
||||
* automatically appends a new line character in every call.
|
||||
*/
|
||||
typedef int (*mplite_putsfunc_t)(const char* stats);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize the memory pool object.
|
||||
* @param[in,out] handle Pointer to a @ref mplite_t object which is allocated
|
||||
* by the caller either from stack, heap, or application's
|
||||
* memory space.
|
||||
* @param[in] buf Pointer to a large, contiguous chunk of memory space that
|
||||
* @ref mplite_t will use to satisfy all of its memory
|
||||
* allocation needs. This might point to a static array or it
|
||||
* might be memory obtained from some other application-specific
|
||||
* mechanism.
|
||||
* @param[in] buf_size The number of bytes of memory space pointed to by @ref
|
||||
* buf
|
||||
* @param[in] min_alloc Minimum size of an allocation. Any call to @ref
|
||||
* mplite_malloc where nBytes is less than min_alloc will
|
||||
* be rounded up to min_alloc. min_alloc must be a power of
|
||||
* two.
|
||||
* @param[in] lock Pointer to a lock object to control access to the memory
|
||||
* allocation subsystem of @ref mplite_t object. If this is
|
||||
* @ref NULL, @ref mplite_t will be non-threadsafe and can only
|
||||
* be safely used by a single thread. It is safe to allocate
|
||||
* this in stack because it will be copied to @ref mplite_t
|
||||
* object.
|
||||
* @return @ref MPLITE_OK on success and @ref MPLITE_ERR_INVPAR on invalid
|
||||
* parameters error.
|
||||
*/
|
||||
MPLITE_API int mplite_init(mplite_t *handle, const void *buf,
|
||||
const int buf_size, const int min_alloc,
|
||||
const mplite_lock_t *lock);
|
||||
|
||||
/**
|
||||
* @brief Allocate bytes of memory
|
||||
* @param[in,out] handle Pointer to an initialized @ref mplite_t object
|
||||
* @param[in] nBytes Number of bytes to allocate
|
||||
* @return Non-NULL on success, NULL otherwise
|
||||
*/
|
||||
MPLITE_API void *mplite_malloc(mplite_t *handle, const int nBytes);
|
||||
|
||||
/**
|
||||
* @brief Free memory
|
||||
* @param[in,out] handle Pointer to an initialized @ref mplite_t object
|
||||
* @param[in] pPrior Allocated buffer
|
||||
*/
|
||||
MPLITE_API void mplite_free(mplite_t *handle, const void *pPrior);
|
||||
|
||||
/**
|
||||
* @brief Change the size of an existing memory allocation.
|
||||
* @param[in,out] handle Pointer to an initialized @ref mplite_t object
|
||||
* @param[in] pPrior Existing allocated memory
|
||||
* @param[in] nBytes Size of the new memory allocation. This is always a value
|
||||
* obtained from a prior call to mplite_roundup(). Hence,
|
||||
* this is always a non-negative power of two. If nBytes == 0
|
||||
* that means that an oversize allocation (an allocation
|
||||
* larger than @ref MPLITE_MAX_ALLOC_SIZE) was requested and
|
||||
* this routine should return NULL without freeing pPrior.
|
||||
* @return Non-NULL on success, NULL otherwise
|
||||
*/
|
||||
MPLITE_API void *mplite_realloc(mplite_t *handle, const void *pPrior,
|
||||
const int nBytes);
|
||||
|
||||
/**
|
||||
* @brief Round up a request size to the next valid allocation size.
|
||||
* @param[in,out] handle Pointer to an initialized @ref mplite_t object
|
||||
* @param[in] n Request size
|
||||
* @return Positive non-zero value if the size can be allocated or zero if the
|
||||
* allocation is too large to be handled.
|
||||
*/
|
||||
MPLITE_API int mplite_roundup(mplite_t *handle, const int n);
|
||||
|
||||
/**
|
||||
* @brief Print the statistics of the memory pool object
|
||||
* @param[in,out] handle Pointer to an initialized @ref mplite_t object
|
||||
* @param[in] logfunc Non-NULL log function of the caller. Refer to
|
||||
* @ref mplite_logfunc_t for the prototype of this function.
|
||||
*/
|
||||
MPLITE_API void mplite_print_stats(const mplite_t * const handle,
|
||||
const mplite_putsfunc_t logfunc);
|
||||
|
||||
/**
|
||||
* @brief Macro to return the number of times mplite_malloc() has been called.
|
||||
*/
|
||||
#define mplite_alloc_count(handle) (((handle) != NULL)? (handle)->nAlloc : 0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #ifndef MPLITE_H */
|
799
mplite/pstdint.h
Normal file
799
mplite/pstdint.h
Normal file
@ -0,0 +1,799 @@
|
||||
/* A portable stdint.h
|
||||
****************************************************************************
|
||||
* BSD License:
|
||||
****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2005-2007 Paul Hsieh
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************
|
||||
*
|
||||
* Version 0.1.11
|
||||
*
|
||||
* The ANSI C standard committee, for the C99 standard, specified the
|
||||
* inclusion of a new standard include file called stdint.h. This is
|
||||
* a very useful and long desired include file which contains several
|
||||
* very precise definitions for integer scalar types that is
|
||||
* critically important for making portable several classes of
|
||||
* applications including cryptography, hashing, variable length
|
||||
* integer libraries and so on. But for most developers its likely
|
||||
* useful just for programming sanity.
|
||||
*
|
||||
* The problem is that most compiler vendors have decided not to
|
||||
* implement the C99 standard, and the next C++ language standard
|
||||
* (which has a lot more mindshare these days) will be a long time in
|
||||
* coming and its unknown whether or not it will include stdint.h or
|
||||
* how much adoption it will have. Either way, it will be a long time
|
||||
* before all compilers come with a stdint.h and it also does nothing
|
||||
* for the extremely large number of compilers available today which
|
||||
* do not include this file, or anything comparable to it.
|
||||
*
|
||||
* So that's what this file is all about. Its an attempt to build a
|
||||
* single universal include file that works on as many platforms as
|
||||
* possible to deliver what stdint.h is supposed to. A few things
|
||||
* that should be noted about this file:
|
||||
*
|
||||
* 1) It is not guaranteed to be portable and/or present an identical
|
||||
* interface on all platforms. The extreme variability of the
|
||||
* ANSI C standard makes this an impossibility right from the
|
||||
* very get go. Its really only meant to be useful for the vast
|
||||
* majority of platforms that possess the capability of
|
||||
* implementing usefully and precisely defined, standard sized
|
||||
* integer scalars. Systems which are not intrinsically 2s
|
||||
* complement may produce invalid constants.
|
||||
*
|
||||
* 2) There is an unavoidable use of non-reserved symbols.
|
||||
*
|
||||
* 3) Other standard include files are invoked.
|
||||
*
|
||||
* 4) This file may come in conflict with future platforms that do
|
||||
* include stdint.h. The hope is that one or the other can be
|
||||
* used with no real difference.
|
||||
*
|
||||
* 5) In the current verison, if your platform can't represent
|
||||
* int32_t, int16_t and int8_t, it just dumps out with a compiler
|
||||
* error.
|
||||
*
|
||||
* 6) 64 bit integers may or may not be defined. Test for their
|
||||
* presence with the test: #ifdef INT64_MAX or #ifdef UINT64_MAX.
|
||||
* Note that this is different from the C99 specification which
|
||||
* requires the existence of 64 bit support in the compiler. If
|
||||
* this is not defined for your platform, yet it is capable of
|
||||
* dealing with 64 bits then it is because this file has not yet
|
||||
* been extended to cover all of your system's capabilities.
|
||||
*
|
||||
* 7) (u)intptr_t may or may not be defined. Test for its presence
|
||||
* with the test: #ifdef PTRDIFF_MAX. If this is not defined
|
||||
* for your platform, then it is because this file has not yet
|
||||
* been extended to cover all of your system's capabilities, not
|
||||
* because its optional.
|
||||
*
|
||||
* 8) The following might not been defined even if your platform is
|
||||
* capable of defining it:
|
||||
*
|
||||
* WCHAR_MIN
|
||||
* WCHAR_MAX
|
||||
* (u)int64_t
|
||||
* PTRDIFF_MIN
|
||||
* PTRDIFF_MAX
|
||||
* (u)intptr_t
|
||||
*
|
||||
* 9) The following have not been defined:
|
||||
*
|
||||
* WINT_MIN
|
||||
* WINT_MAX
|
||||
*
|
||||
* 10) The criteria for defining (u)int_least(*)_t isn't clear,
|
||||
* except for systems which don't have a type that precisely
|
||||
* defined 8, 16, or 32 bit types (which this include file does
|
||||
* not support anyways). Default definitions have been given.
|
||||
*
|
||||
* 11) The criteria for defining (u)int_fast(*)_t isn't something I
|
||||
* would trust to any particular compiler vendor or the ANSI C
|
||||
* committee. It is well known that "compatible systems" are
|
||||
* commonly created that have very different performance
|
||||
* characteristics from the systems they are compatible with,
|
||||
* especially those whose vendors make both the compiler and the
|
||||
* system. Default definitions have been given, but its strongly
|
||||
* recommended that users never use these definitions for any
|
||||
* reason (they do *NOT* deliver any serious guarantee of
|
||||
* improved performance -- not in this file, nor any vendor's
|
||||
* stdint.h).
|
||||
*
|
||||
* 12) The following macros:
|
||||
*
|
||||
* PRINTF_INTMAX_MODIFIER
|
||||
* PRINTF_INT64_MODIFIER
|
||||
* PRINTF_INT32_MODIFIER
|
||||
* PRINTF_INT16_MODIFIER
|
||||
* PRINTF_LEAST64_MODIFIER
|
||||
* PRINTF_LEAST32_MODIFIER
|
||||
* PRINTF_LEAST16_MODIFIER
|
||||
* PRINTF_INTPTR_MODIFIER
|
||||
*
|
||||
* are strings which have been defined as the modifiers required
|
||||
* for the "d", "u" and "x" printf formats to correctly output
|
||||
* (u)intmax_t, (u)int64_t, (u)int32_t, (u)int16_t, (u)least64_t,
|
||||
* (u)least32_t, (u)least16_t and (u)intptr_t types respectively.
|
||||
* PRINTF_INTPTR_MODIFIER is not defined for some systems which
|
||||
* provide their own stdint.h. PRINTF_INT64_MODIFIER is not
|
||||
* defined if INT64_MAX is not defined. These are an extension
|
||||
* beyond what C99 specifies must be in stdint.h.
|
||||
*
|
||||
* In addition, the following macros are defined:
|
||||
*
|
||||
* PRINTF_INTMAX_HEX_WIDTH
|
||||
* PRINTF_INT64_HEX_WIDTH
|
||||
* PRINTF_INT32_HEX_WIDTH
|
||||
* PRINTF_INT16_HEX_WIDTH
|
||||
* PRINTF_INT8_HEX_WIDTH
|
||||
* PRINTF_INTMAX_DEC_WIDTH
|
||||
* PRINTF_INT64_DEC_WIDTH
|
||||
* PRINTF_INT32_DEC_WIDTH
|
||||
* PRINTF_INT16_DEC_WIDTH
|
||||
* PRINTF_INT8_DEC_WIDTH
|
||||
*
|
||||
* Which specifies the maximum number of characters required to
|
||||
* print the number of that type in either hexadecimal or decimal.
|
||||
* These are an extension beyond what C99 specifies must be in
|
||||
* stdint.h.
|
||||
*
|
||||
* Compilers tested (all with 0 warnings at their highest respective
|
||||
* settings): Borland Turbo C 2.0, WATCOM C/C++ 11.0 (16 bits and 32
|
||||
* bits), Microsoft Visual C++ 6.0 (32 bit), Microsoft Visual Studio
|
||||
* .net (VC7), Intel C++ 4.0, GNU gcc v3.3.3
|
||||
*
|
||||
* This file should be considered a work in progress. Suggestions for
|
||||
* improvements, especially those which increase coverage are strongly
|
||||
* encouraged.
|
||||
*
|
||||
* Acknowledgements
|
||||
*
|
||||
* The following people have made significant contributions to the
|
||||
* development and testing of this file:
|
||||
*
|
||||
* Chris Howie
|
||||
* John Steele Scott
|
||||
* Dave Thorup
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
|
||||
/*
|
||||
* For gcc with _STDINT_H, fill in the PRINTF_INT*_MODIFIER macros, and
|
||||
* do nothing else. On the Mac OS X version of gcc this is _STDINT_H_.
|
||||
*/
|
||||
|
||||
#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) )) && !defined (_PSTDINT_H_INCLUDED)
|
||||
#include <stdint.h>
|
||||
#define _PSTDINT_H_INCLUDED
|
||||
# ifndef PRINTF_INT64_MODIFIER
|
||||
# define PRINTF_INT64_MODIFIER "ll"
|
||||
# endif
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_INT32_MODIFIER "l"
|
||||
# endif
|
||||
# ifndef PRINTF_INT16_MODIFIER
|
||||
# define PRINTF_INT16_MODIFIER "h"
|
||||
# endif
|
||||
# ifndef PRINTF_INTMAX_MODIFIER
|
||||
# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER
|
||||
# endif
|
||||
# ifndef PRINTF_INT64_HEX_WIDTH
|
||||
# define PRINTF_INT64_HEX_WIDTH "16"
|
||||
# endif
|
||||
# ifndef PRINTF_INT32_HEX_WIDTH
|
||||
# define PRINTF_INT32_HEX_WIDTH "8"
|
||||
# endif
|
||||
# ifndef PRINTF_INT16_HEX_WIDTH
|
||||
# define PRINTF_INT16_HEX_WIDTH "4"
|
||||
# endif
|
||||
# ifndef PRINTF_INT8_HEX_WIDTH
|
||||
# define PRINTF_INT8_HEX_WIDTH "2"
|
||||
# endif
|
||||
# ifndef PRINTF_INT64_DEC_WIDTH
|
||||
# define PRINTF_INT64_DEC_WIDTH "20"
|
||||
# endif
|
||||
# ifndef PRINTF_INT32_DEC_WIDTH
|
||||
# define PRINTF_INT32_DEC_WIDTH "10"
|
||||
# endif
|
||||
# ifndef PRINTF_INT16_DEC_WIDTH
|
||||
# define PRINTF_INT16_DEC_WIDTH "5"
|
||||
# endif
|
||||
# ifndef PRINTF_INT8_DEC_WIDTH
|
||||
# define PRINTF_INT8_DEC_WIDTH "3"
|
||||
# endif
|
||||
# ifndef PRINTF_INTMAX_HEX_WIDTH
|
||||
# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH
|
||||
# endif
|
||||
# ifndef PRINTF_INTMAX_DEC_WIDTH
|
||||
# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH
|
||||
# endif
|
||||
|
||||
/*
|
||||
* Something really weird is going on with Open Watcom. Just pull some of
|
||||
* these duplicated definitions from Open Watcom's stdint.h file for now.
|
||||
*/
|
||||
|
||||
# if defined (__WATCOMC__) && __WATCOMC__ >= 1250
|
||||
# if !defined (INT64_C)
|
||||
# define INT64_C(x) (x + (INT64_MAX - INT64_MAX))
|
||||
# endif
|
||||
# if !defined (UINT64_C)
|
||||
# define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX))
|
||||
# endif
|
||||
# if !defined (INT32_C)
|
||||
# define INT32_C(x) (x + (INT32_MAX - INT32_MAX))
|
||||
# endif
|
||||
# if !defined (UINT32_C)
|
||||
# define UINT32_C(x) (x + (UINT32_MAX - UINT32_MAX))
|
||||
# endif
|
||||
# if !defined (INT16_C)
|
||||
# define INT16_C(x) (x)
|
||||
# endif
|
||||
# if !defined (UINT16_C)
|
||||
# define UINT16_C(x) (x)
|
||||
# endif
|
||||
# if !defined (INT8_C)
|
||||
# define INT8_C(x) (x)
|
||||
# endif
|
||||
# if !defined (UINT8_C)
|
||||
# define UINT8_C(x) (x)
|
||||
# endif
|
||||
# if !defined (UINT64_MAX)
|
||||
# define UINT64_MAX 18446744073709551615ULL
|
||||
# endif
|
||||
# if !defined (INT64_MAX)
|
||||
# define INT64_MAX 9223372036854775807LL
|
||||
# endif
|
||||
# if !defined (UINT32_MAX)
|
||||
# define UINT32_MAX 4294967295UL
|
||||
# endif
|
||||
# if !defined (INT32_MAX)
|
||||
# define INT32_MAX 2147483647L
|
||||
# endif
|
||||
# if !defined (INTMAX_MAX)
|
||||
# define INTMAX_MAX INT64_MAX
|
||||
# endif
|
||||
# if !defined (INTMAX_MIN)
|
||||
# define INTMAX_MIN INT64_MIN
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef _PSTDINT_H_INCLUDED
|
||||
#define _PSTDINT_H_INCLUDED
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
# define SIZE_MAX (~(size_t)0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Deduce the type assignments from limits.h under the assumption that
|
||||
* integer sizes in bits are powers of 2, and follow the ANSI
|
||||
* definitions.
|
||||
*/
|
||||
|
||||
#ifndef UINT8_MAX
|
||||
# define UINT8_MAX 0xff
|
||||
#endif
|
||||
#ifndef uint8_t
|
||||
# if (UCHAR_MAX == UINT8_MAX) || defined (S_SPLINT_S)
|
||||
typedef unsigned char uint8_t;
|
||||
# define UINT8_C(v) ((uint8_t) v)
|
||||
# else
|
||||
# error "Platform not supported"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef INT8_MAX
|
||||
# define INT8_MAX 0x7f
|
||||
#endif
|
||||
#ifndef INT8_MIN
|
||||
# define INT8_MIN INT8_C(0x80)
|
||||
#endif
|
||||
#ifndef int8_t
|
||||
# if (SCHAR_MAX == INT8_MAX) || defined (S_SPLINT_S)
|
||||
typedef signed char int8_t;
|
||||
# define INT8_C(v) ((int8_t) v)
|
||||
# else
|
||||
# error "Platform not supported"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef UINT16_MAX
|
||||
# define UINT16_MAX 0xffff
|
||||
#endif
|
||||
#ifndef uint16_t
|
||||
#if (UINT_MAX == UINT16_MAX) || defined (S_SPLINT_S)
|
||||
typedef unsigned int uint16_t;
|
||||
# ifndef PRINTF_INT16_MODIFIER
|
||||
# define PRINTF_INT16_MODIFIER ""
|
||||
# endif
|
||||
# define UINT16_C(v) ((uint16_t) (v))
|
||||
#elif (USHRT_MAX == UINT16_MAX)
|
||||
typedef unsigned short uint16_t;
|
||||
# define UINT16_C(v) ((uint16_t) (v))
|
||||
# ifndef PRINTF_INT16_MODIFIER
|
||||
# define PRINTF_INT16_MODIFIER "h"
|
||||
# endif
|
||||
#else
|
||||
#error "Platform not supported"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef INT16_MAX
|
||||
# define INT16_MAX 0x7fff
|
||||
#endif
|
||||
#ifndef INT16_MIN
|
||||
# define INT16_MIN INT16_C(0x8000)
|
||||
#endif
|
||||
#ifndef int16_t
|
||||
#if (INT_MAX == INT16_MAX) || defined (S_SPLINT_S)
|
||||
typedef signed int int16_t;
|
||||
# define INT16_C(v) ((int16_t) (v))
|
||||
# ifndef PRINTF_INT16_MODIFIER
|
||||
# define PRINTF_INT16_MODIFIER ""
|
||||
# endif
|
||||
#elif (SHRT_MAX == INT16_MAX)
|
||||
typedef signed short int16_t;
|
||||
# define INT16_C(v) ((int16_t) (v))
|
||||
# ifndef PRINTF_INT16_MODIFIER
|
||||
# define PRINTF_INT16_MODIFIER "h"
|
||||
# endif
|
||||
#else
|
||||
#error "Platform not supported"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef UINT32_MAX
|
||||
# define UINT32_MAX (0xffffffffUL)
|
||||
#endif
|
||||
#ifndef uint32_t
|
||||
#if (ULONG_MAX == UINT32_MAX) || defined (S_SPLINT_S)
|
||||
typedef unsigned long uint32_t;
|
||||
# define UINT32_C(v) v ## UL
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_INT32_MODIFIER "l"
|
||||
# endif
|
||||
#elif (UINT_MAX == UINT32_MAX)
|
||||
typedef unsigned int uint32_t;
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_INT32_MODIFIER ""
|
||||
# endif
|
||||
# define UINT32_C(v) v ## U
|
||||
#elif (USHRT_MAX == UINT32_MAX)
|
||||
typedef unsigned short uint32_t;
|
||||
# define UINT32_C(v) ((unsigned short) (v))
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_INT32_MODIFIER ""
|
||||
# endif
|
||||
#else
|
||||
#error "Platform not supported"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef INT32_MAX
|
||||
# define INT32_MAX (0x7fffffffL)
|
||||
#endif
|
||||
#ifndef INT32_MIN
|
||||
# define INT32_MIN INT32_C(0x80000000)
|
||||
#endif
|
||||
#ifndef int32_t
|
||||
#if (LONG_MAX == INT32_MAX) || defined (S_SPLINT_S)
|
||||
typedef signed long int32_t;
|
||||
# define INT32_C(v) v ## L
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_INT32_MODIFIER "l"
|
||||
# endif
|
||||
#elif (INT_MAX == INT32_MAX)
|
||||
typedef signed int int32_t;
|
||||
# define INT32_C(v) v
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_INT32_MODIFIER ""
|
||||
# endif
|
||||
#elif (SHRT_MAX == INT32_MAX)
|
||||
typedef signed short int32_t;
|
||||
# define INT32_C(v) ((short) (v))
|
||||
# ifndef PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_INT32_MODIFIER ""
|
||||
# endif
|
||||
#else
|
||||
#error "Platform not supported"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The macro stdint_int64_defined is temporarily used to record
|
||||
* whether or not 64 integer support is available. It must be
|
||||
* defined for any 64 integer extensions for new platforms that are
|
||||
* added.
|
||||
*/
|
||||
|
||||
#undef stdint_int64_defined
|
||||
#if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined (S_SPLINT_S)
|
||||
# if (__STDC__ && __STDC_VERSION >= 199901L) || defined (S_SPLINT_S)
|
||||
# define stdint_int64_defined
|
||||
typedef long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
# define UINT64_C(v) v ## ULL
|
||||
# define INT64_C(v) v ## LL
|
||||
# ifndef PRINTF_INT64_MODIFIER
|
||||
# define PRINTF_INT64_MODIFIER "ll"
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined (stdint_int64_defined)
|
||||
# if defined(__GNUC__)
|
||||
# define stdint_int64_defined
|
||||
__extension__ typedef long long int64_t;
|
||||
__extension__ typedef unsigned long long uint64_t;
|
||||
# define UINT64_C(v) v ## ULL
|
||||
# define INT64_C(v) v ## LL
|
||||
# ifndef PRINTF_INT64_MODIFIER
|
||||
# define PRINTF_INT64_MODIFIER "ll"
|
||||
# endif
|
||||
# elif defined(__MWERKS__) || defined (__SUNPRO_C) || defined (__SUNPRO_CC) || defined (__APPLE_CC__) || defined (_LONG_LONG) || defined (_CRAYC) || defined (S_SPLINT_S)
|
||||
# define stdint_int64_defined
|
||||
typedef long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
# define UINT64_C(v) v ## ULL
|
||||
# define INT64_C(v) v ## LL
|
||||
# ifndef PRINTF_INT64_MODIFIER
|
||||
# define PRINTF_INT64_MODIFIER "ll"
|
||||
# endif
|
||||
# elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined (__BORLANDC__) && __BORLANDC__ > 0x460) || defined (__alpha) || defined (__DECC)
|
||||
# define stdint_int64_defined
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
# define UINT64_C(v) v ## UI64
|
||||
# define INT64_C(v) v ## I64
|
||||
# ifndef PRINTF_INT64_MODIFIER
|
||||
# define PRINTF_INT64_MODIFIER "I64"
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined (LONG_LONG_MAX) && defined (INT64_C)
|
||||
# define LONG_LONG_MAX INT64_C (9223372036854775807)
|
||||
#endif
|
||||
#ifndef ULONG_LONG_MAX
|
||||
# define ULONG_LONG_MAX UINT64_C (18446744073709551615)
|
||||
#endif
|
||||
|
||||
#if !defined (INT64_MAX) && defined (INT64_C)
|
||||
# define INT64_MAX INT64_C (9223372036854775807)
|
||||
#endif
|
||||
#if !defined (INT64_MIN) && defined (INT64_C)
|
||||
# define INT64_MIN INT64_C (-9223372036854775808)
|
||||
#endif
|
||||
#if !defined (UINT64_MAX) && defined (INT64_C)
|
||||
# define UINT64_MAX UINT64_C (18446744073709551615)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Width of hexadecimal for number field.
|
||||
*/
|
||||
|
||||
#ifndef PRINTF_INT64_HEX_WIDTH
|
||||
# define PRINTF_INT64_HEX_WIDTH "16"
|
||||
#endif
|
||||
#ifndef PRINTF_INT32_HEX_WIDTH
|
||||
# define PRINTF_INT32_HEX_WIDTH "8"
|
||||
#endif
|
||||
#ifndef PRINTF_INT16_HEX_WIDTH
|
||||
# define PRINTF_INT16_HEX_WIDTH "4"
|
||||
#endif
|
||||
#ifndef PRINTF_INT8_HEX_WIDTH
|
||||
# define PRINTF_INT8_HEX_WIDTH "2"
|
||||
#endif
|
||||
|
||||
#ifndef PRINTF_INT64_DEC_WIDTH
|
||||
# define PRINTF_INT64_DEC_WIDTH "20"
|
||||
#endif
|
||||
#ifndef PRINTF_INT32_DEC_WIDTH
|
||||
# define PRINTF_INT32_DEC_WIDTH "10"
|
||||
#endif
|
||||
#ifndef PRINTF_INT16_DEC_WIDTH
|
||||
# define PRINTF_INT16_DEC_WIDTH "5"
|
||||
#endif
|
||||
#ifndef PRINTF_INT8_DEC_WIDTH
|
||||
# define PRINTF_INT8_DEC_WIDTH "3"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Ok, lets not worry about 128 bit integers for now. Moore's law says
|
||||
* we don't need to worry about that until about 2040 at which point
|
||||
* we'll have bigger things to worry about.
|
||||
*/
|
||||
|
||||
#ifdef stdint_int64_defined
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
# define INTMAX_MAX INT64_MAX
|
||||
# define INTMAX_MIN INT64_MIN
|
||||
# define UINTMAX_MAX UINT64_MAX
|
||||
# define UINTMAX_C(v) UINT64_C(v)
|
||||
# define INTMAX_C(v) INT64_C(v)
|
||||
# ifndef PRINTF_INTMAX_MODIFIER
|
||||
# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER
|
||||
# endif
|
||||
# ifndef PRINTF_INTMAX_HEX_WIDTH
|
||||
# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH
|
||||
# endif
|
||||
# ifndef PRINTF_INTMAX_DEC_WIDTH
|
||||
# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH
|
||||
# endif
|
||||
#else
|
||||
typedef int32_t intmax_t;
|
||||
typedef uint32_t uintmax_t;
|
||||
# define INTMAX_MAX INT32_MAX
|
||||
# define UINTMAX_MAX UINT32_MAX
|
||||
# define UINTMAX_C(v) UINT32_C(v)
|
||||
# define INTMAX_C(v) INT32_C(v)
|
||||
# ifndef PRINTF_INTMAX_MODIFIER
|
||||
# define PRINTF_INTMAX_MODIFIER PRINTF_INT32_MODIFIER
|
||||
# endif
|
||||
# ifndef PRINTF_INTMAX_HEX_WIDTH
|
||||
# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT32_HEX_WIDTH
|
||||
# endif
|
||||
# ifndef PRINTF_INTMAX_DEC_WIDTH
|
||||
# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT32_DEC_WIDTH
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Because this file currently only supports platforms which have
|
||||
* precise powers of 2 as bit sizes for the default integers, the
|
||||
* least definitions are all trivial. Its possible that a future
|
||||
* version of this file could have different definitions.
|
||||
*/
|
||||
|
||||
#ifndef stdint_least_defined
|
||||
typedef int8_t int_least8_t;
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
# define PRINTF_LEAST32_MODIFIER PRINTF_INT32_MODIFIER
|
||||
# define PRINTF_LEAST16_MODIFIER PRINTF_INT16_MODIFIER
|
||||
# define UINT_LEAST8_MAX UINT8_MAX
|
||||
# define INT_LEAST8_MAX INT8_MAX
|
||||
# define UINT_LEAST16_MAX UINT16_MAX
|
||||
# define INT_LEAST16_MAX INT16_MAX
|
||||
# define UINT_LEAST32_MAX UINT32_MAX
|
||||
# define INT_LEAST32_MAX INT32_MAX
|
||||
# define INT_LEAST8_MIN INT8_MIN
|
||||
# define INT_LEAST16_MIN INT16_MIN
|
||||
# define INT_LEAST32_MIN INT32_MIN
|
||||
# ifdef stdint_int64_defined
|
||||
typedef int64_t int_least64_t;
|
||||
typedef uint64_t uint_least64_t;
|
||||
# define PRINTF_LEAST64_MODIFIER PRINTF_INT64_MODIFIER
|
||||
# define UINT_LEAST64_MAX UINT64_MAX
|
||||
# define INT_LEAST64_MAX INT64_MAX
|
||||
# define INT_LEAST64_MIN INT64_MIN
|
||||
# endif
|
||||
#endif
|
||||
#undef stdint_least_defined
|
||||
|
||||
/*
|
||||
* The ANSI C committee pretending to know or specify anything about
|
||||
* performance is the epitome of misguided arrogance. The mandate of
|
||||
* this file is to *ONLY* ever support that absolute minimum
|
||||
* definition of the fast integer types, for compatibility purposes.
|
||||
* No extensions, and no attempt to suggest what may or may not be a
|
||||
* faster integer type will ever be made in this file. Developers are
|
||||
* warned to stay away from these types when using this or any other
|
||||
* stdint.h.
|
||||
*/
|
||||
|
||||
typedef int_least8_t int_fast8_t;
|
||||
typedef uint_least8_t uint_fast8_t;
|
||||
typedef int_least16_t int_fast16_t;
|
||||
typedef uint_least16_t uint_fast16_t;
|
||||
typedef int_least32_t int_fast32_t;
|
||||
typedef uint_least32_t uint_fast32_t;
|
||||
#define UINT_FAST8_MAX UINT_LEAST8_MAX
|
||||
#define INT_FAST8_MAX INT_LEAST8_MAX
|
||||
#define UINT_FAST16_MAX UINT_LEAST16_MAX
|
||||
#define INT_FAST16_MAX INT_LEAST16_MAX
|
||||
#define UINT_FAST32_MAX UINT_LEAST32_MAX
|
||||
#define INT_FAST32_MAX INT_LEAST32_MAX
|
||||
#define INT_FAST8_MIN INT_LEAST8_MIN
|
||||
#define INT_FAST16_MIN INT_LEAST16_MIN
|
||||
#define INT_FAST32_MIN INT_LEAST32_MIN
|
||||
#ifdef stdint_int64_defined
|
||||
typedef int_least64_t int_fast64_t;
|
||||
typedef uint_least64_t uint_fast64_t;
|
||||
# define UINT_FAST64_MAX UINT_LEAST64_MAX
|
||||
# define INT_FAST64_MAX INT_LEAST64_MAX
|
||||
# define INT_FAST64_MIN INT_LEAST64_MIN
|
||||
#endif
|
||||
|
||||
#undef stdint_int64_defined
|
||||
|
||||
/*
|
||||
* Whatever piecemeal, per compiler thing we can do about the wchar_t
|
||||
* type limits.
|
||||
*/
|
||||
|
||||
#if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__)
|
||||
# include <wchar.h>
|
||||
# ifndef WCHAR_MIN
|
||||
# define WCHAR_MIN 0
|
||||
# endif
|
||||
# ifndef WCHAR_MAX
|
||||
# define WCHAR_MAX ((wchar_t)-1)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Whatever piecemeal, per compiler/platform thing we can do about the
|
||||
* (u)intptr_t types and limits.
|
||||
*/
|
||||
|
||||
#if defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED)
|
||||
# define STDINT_H_UINTPTR_T_DEFINED
|
||||
#endif
|
||||
|
||||
#ifndef STDINT_H_UINTPTR_T_DEFINED
|
||||
# if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64)
|
||||
# define stdint_intptr_bits 64
|
||||
# elif defined (__WATCOMC__) || defined (__TURBOC__)
|
||||
# if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__)
|
||||
# define stdint_intptr_bits 16
|
||||
# else
|
||||
# define stdint_intptr_bits 32
|
||||
# endif
|
||||
# elif defined (__i386__) || defined (_WIN32) || defined (WIN32)
|
||||
# define stdint_intptr_bits 32
|
||||
# elif defined (__INTEL_COMPILER)
|
||||
/* TODO -- what will Intel do about x86-64? */
|
||||
# endif
|
||||
|
||||
# ifdef stdint_intptr_bits
|
||||
# define stdint_intptr_glue3_i(a,b,c) a##b##c
|
||||
# define stdint_intptr_glue3(a,b,c) stdint_intptr_glue3_i(a,b,c)
|
||||
# ifndef PRINTF_INTPTR_MODIFIER
|
||||
# define PRINTF_INTPTR_MODIFIER stdint_intptr_glue3(PRINTF_INT,stdint_intptr_bits,_MODIFIER)
|
||||
# endif
|
||||
# ifndef PTRDIFF_MAX
|
||||
# define PTRDIFF_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX)
|
||||
# endif
|
||||
# ifndef PTRDIFF_MIN
|
||||
# define PTRDIFF_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN)
|
||||
# endif
|
||||
# ifndef UINTPTR_MAX
|
||||
# define UINTPTR_MAX stdint_intptr_glue3(UINT,stdint_intptr_bits,_MAX)
|
||||
# endif
|
||||
# ifndef INTPTR_MAX
|
||||
# define INTPTR_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX)
|
||||
# endif
|
||||
# ifndef INTPTR_MIN
|
||||
# define INTPTR_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN)
|
||||
# endif
|
||||
# ifndef INTPTR_C
|
||||
# define INTPTR_C(x) stdint_intptr_glue3(INT,stdint_intptr_bits,_C)(x)
|
||||
# endif
|
||||
# ifndef UINTPTR_C
|
||||
# define UINTPTR_C(x) stdint_intptr_glue3(UINT,stdint_intptr_bits,_C)(x)
|
||||
# endif
|
||||
typedef stdint_intptr_glue3(uint,stdint_intptr_bits,_t) uintptr_t;
|
||||
typedef stdint_intptr_glue3( int,stdint_intptr_bits,_t) intptr_t;
|
||||
# else
|
||||
/* TODO -- This following is likely wrong for some platforms, and does
|
||||
nothing for the definition of uintptr_t. */
|
||||
typedef ptrdiff_t intptr_t;
|
||||
# endif
|
||||
# define STDINT_H_UINTPTR_T_DEFINED
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Assumes sig_atomic_t is signed and we have a 2s complement machine.
|
||||
*/
|
||||
|
||||
#ifndef SIG_ATOMIC_MAX
|
||||
# define SIG_ATOMIC_MAX ((((sig_atomic_t) 1) << (sizeof (sig_atomic_t)*CHAR_BIT-1)) - 1)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined (__TEST_PSTDINT_FOR_CORRECTNESS)
|
||||
|
||||
/*
|
||||
* Please compile with the maximum warning settings to make sure macros are not
|
||||
* defined more than once.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define glue3_aux(x,y,z) x ## y ## z
|
||||
#define glue3(x,y,z) glue3_aux(x,y,z)
|
||||
|
||||
#define DECLU(bits) glue3(uint,bits,_t) glue3(u,bits,=) glue3(UINT,bits,_C) (0);
|
||||
#define DECLI(bits) glue3(int,bits,_t) glue3(i,bits,=) glue3(INT,bits,_C) (0);
|
||||
|
||||
#define DECL(us,bits) glue3(DECL,us,) (bits)
|
||||
|
||||
#define TESTUMAX(bits) glue3(u,bits,=) glue3(~,u,bits); if (glue3(UINT,bits,_MAX) glue3(!=,u,bits)) printf ("Something wrong with UINT%d_MAX\n", bits)
|
||||
|
||||
int main () {
|
||||
DECL(I,8)
|
||||
DECL(U,8)
|
||||
DECL(I,16)
|
||||
DECL(U,16)
|
||||
DECL(I,32)
|
||||
DECL(U,32)
|
||||
#ifdef INT64_MAX
|
||||
DECL(I,64)
|
||||
DECL(U,64)
|
||||
#endif
|
||||
intmax_t imax = INTMAX_C(0);
|
||||
uintmax_t umax = UINTMAX_C(0);
|
||||
char str0[256], str1[256];
|
||||
|
||||
sprintf (str0, "%d %x\n", 0, ~0);
|
||||
|
||||
sprintf (str1, "%d %x\n", i8, ~0);
|
||||
if (0 != strcmp (str0, str1)) printf ("Something wrong with i8 : %s\n", str1);
|
||||
sprintf (str1, "%u %x\n", u8, ~0);
|
||||
if (0 != strcmp (str0, str1)) printf ("Something wrong with u8 : %s\n", str1);
|
||||
sprintf (str1, "%d %x\n", i16, ~0);
|
||||
if (0 != strcmp (str0, str1)) printf ("Something wrong with i16 : %s\n", str1);
|
||||
sprintf (str1, "%u %x\n", u16, ~0);
|
||||
if (0 != strcmp (str0, str1)) printf ("Something wrong with u16 : %s\n", str1);
|
||||
sprintf (str1, "%" PRINTF_INT32_MODIFIER "d %x\n", i32, ~0);
|
||||
if (0 != strcmp (str0, str1)) printf ("Something wrong with i32 : %s\n", str1);
|
||||
sprintf (str1, "%" PRINTF_INT32_MODIFIER "u %x\n", u32, ~0);
|
||||
if (0 != strcmp (str0, str1)) printf ("Something wrong with u32 : %s\n", str1);
|
||||
#ifdef INT64_MAX
|
||||
sprintf (str1, "%" PRINTF_INT64_MODIFIER "d %x\n", i64, ~0);
|
||||
if (0 != strcmp (str0, str1)) printf ("Something wrong with i64 : %s\n", str1);
|
||||
#endif
|
||||
sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "d %x\n", imax, ~0);
|
||||
if (0 != strcmp (str0, str1)) printf ("Something wrong with imax : %s\n", str1);
|
||||
sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "u %x\n", umax, ~0);
|
||||
if (0 != strcmp (str0, str1)) printf ("Something wrong with umax : %s\n", str1);
|
||||
|
||||
TESTUMAX(8);
|
||||
TESTUMAX(16);
|
||||
TESTUMAX(32);
|
||||
#ifdef INT64_MAX
|
||||
TESTUMAX(64);
|
||||
#endif
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user