mirror of https://github.com/Cisco-Talos/clamav
git-svn-id: file:///var/lib/svn/clamav-devel/branches/mpool@4286 77e5149b-7576-45b1-b177-96237e5ba77b0.95
parent
eb8ab9d28a
commit
e21657dfc9
@ -1,86 +0,0 @@ |
||||
2006-05-31 Gray Watson <> |
||||
|
||||
* Version 2.1.0 released. |
||||
|
||||
* Added MPOOL_ERROR_PNT_OVER to distinguish between pointer |
||||
overwrite and mpool structure overwrite. |
||||
|
||||
2005-05-20 Gray Watson <> |
||||
|
||||
* Version 2.0.0 released. |
||||
|
||||
* First external publication of library. |
||||
|
||||
Thu Mar 4 10:14:21 1999 Gray Watson <> |
||||
|
||||
* Reworked the way the blocks were split up. |
||||
|
||||
* Removed the round arguments. Not used. |
||||
|
||||
Wed Mar 3 19:29:38 1999 Gray Watson <> |
||||
|
||||
* Moved to random(). Fucking rand() was hiding a lot of problems |
||||
from me. |
||||
|
||||
* Added some additional sanity checks in free(). |
||||
|
||||
* Added mpool_set_max_pages to the library. |
||||
|
||||
Thu Feb 25 12:41:51 1999 Gray Watson <> |
||||
|
||||
* Added log_function transaction callback. |
||||
|
||||
Thu Feb 25 09:53:33 1999 Gray Watson <> |
||||
|
||||
* Changed the default page size to 16 * getpagesize. |
||||
|
||||
Wed Feb 24 17:52:52 1999 Gray Watson <> |
||||
|
||||
* Major reworking of internals to simplify structures. |
||||
|
||||
Fri Feb 19 12:52:55 1999 Gray Watson <> |
||||
|
||||
* Made a number of changes to the internals which removed the |
||||
addr_to_block as a performance pig. |
||||
|
||||
Tue Feb 16 21:11:23 1999 Gray Watson <> |
||||
|
||||
* Added ability for free to look up in the free bit lists for |
||||
memory to use. |
||||
|
||||
* Added mpool_clear. Good idea. |
||||
|
||||
Thu Feb 11 02:53:45 1999 Gray Watson <> |
||||
|
||||
* Finally a working version. Looks much better. |
||||
|
||||
* Added rounding sizes so it will allocate aligned memory. |
||||
|
||||
* Added minimum size to the mpool_free function to speed it up. |
||||
|
||||
Wed Feb 10 23:30:48 1999 Gray Watson <> |
||||
|
||||
* Version 1 with new fine grained memory resolution almost |
||||
working. |
||||
|
||||
Fri May 2 02:26:28 1997 Gray Watson <> |
||||
|
||||
* Moved to MAP_PRIVATE from MAP_SHARED. |
||||
|
||||
* Fixed the min/max handling. |
||||
|
||||
* Added additional info to mpool_stat. |
||||
|
||||
Thu May 1 16:51:06 1997 Gray Watson <> |
||||
|
||||
* Added page-size information request. |
||||
|
||||
* Added better no-memory errors. |
||||
|
||||
Thu Apr 24 01:58:41 1997 Gray Watson <> |
||||
|
||||
* Added handling of null for debugging purposes. |
||||
|
||||
Mon Apr 14 03:31:26 1997 Gray Watson <> |
||||
|
||||
* Started the mpool routines. |
||||
@ -1,56 +0,0 @@ |
||||
#
|
||||
# $Id: Makefile.all,v 1.1.1.1 2005/05/20 19:58:29 gray Exp $
|
||||
#
|
||||
|
||||
HFLS = mpool.h
|
||||
OBJS = mpool.o
|
||||
|
||||
CC = cc
|
||||
|
||||
CFLAGS = -g -I. $(DEFINES)
|
||||
#CFLAGS = -g -I.
|
||||
LDFLAGS =
|
||||
RANLIB = ranlib
|
||||
|
||||
DESTDIR = /usr/local
|
||||
TEST = mpool_t
|
||||
LIBRARY = libmpool.a
|
||||
|
||||
all : $(LIBRARY) $(UTIL) |
||||
|
||||
clean : |
||||
rm -f a.out core *.o *.t
|
||||
rm -f $(LIBRARY) $(TEST)
|
||||
|
||||
install : $(HFLS) $(LIBRARY) |
||||
install -c -m 444 $(HFLS) $(DESTDIR)/include
|
||||
install -c -m 444 $(LIBRARY) $(DESTDIR)/lib
|
||||
$(RANLIB) $(DESTDIR)/libo/$(LIBRARY)
|
||||
|
||||
$(LIBRARY) : $(OBJS) |
||||
ar cr $(LIBRARY) $?
|
||||
$(RANLIB) $@
|
||||
|
||||
tests : $(TEST) |
||||
|
||||
$(TEST) : $(TEST).o $(LIBRARY) |
||||
rm -f $@
|
||||
$(CC) $(LDFLAGS) $(TEST).o $(LIBRARY)
|
||||
mv a.out $@
|
||||
|
||||
$(UTIL) : $(UTIL).o $(LIBRARY) |
||||
rm -f $@
|
||||
$(CC) $(LDFLAGS) $(UTIL).o $(LIBRARY)
|
||||
mv a.out $@
|
||||
|
||||
.c.o : |
||||
rm -f $@
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
#
|
||||
# Below are dependencies that are automatically generated by make
|
||||
# depend. Please do not edit by hand.
|
||||
#
|
||||
|
||||
mpool.o: mpool.c mpool.h mpool_loc.h |
||||
mpool_t.o: mpool_t.c mpool.h |
||||
@ -1,11 +0,0 @@ |
||||
------------------------------------------------------------------------------- |
||||
$Id: NEWS,v 1.2 2006/05/31 20:28:31 gray Exp $ |
||||
------------------------------------------------------------------------------- |
||||
|
||||
Version 2.1.0: |
||||
|
||||
* Added MPOOL_ERROR_PNT_OVER to show pointer overwrites. |
||||
|
||||
Version 2.0.0: |
||||
|
||||
* Initial external release of library after use since 1996. |
||||
@ -1,46 +0,0 @@ |
||||
------------------------------------------------------------------------------- |
||||
$Id: README,v 1.2 2005/05/22 19:49:30 gray Exp $ |
||||
------------------------------------------------------------------------------- |
||||
|
||||
BACKGROUND: |
||||
|
||||
This is a memory pool library which was written to allow a program to |
||||
have heaps that it could destroy without fragmenting memory. You can |
||||
have multiple heaps and reset them easily completely reclaiming the |
||||
memory (as opposed to standard heaps). |
||||
|
||||
With it you can mpool_open() a new heap, then mpool_alloc(), |
||||
mpool_calloc(), mpool_realloc(), mpool_free() to your heart's content. |
||||
Once you are done with the memory-pool you can run mpool_clear() or |
||||
mpool_close() and completely remove the memory associated with the |
||||
pools. This is very handy if you are working with some large blocks |
||||
of memory and want to reset back to a clean state. |
||||
|
||||
Check out the mpool.h file for more information. Sorry for minimal |
||||
docs. |
||||
|
||||
------------------------------------------------------------------------------- |
||||
|
||||
INSTALLATION: |
||||
|
||||
1) Typing 'make' should be enough to build libskip.a. |
||||
2) Typing 'make tests' should make the mpool_t test program. |
||||
|
||||
------------------------------------------------------------------------------- |
||||
|
||||
REPOSITORY: |
||||
|
||||
The newest versions of the library are available from: |
||||
|
||||
http://256.com/sources/mpool/ |
||||
|
||||
------------------------------------------------------------------------------- |
||||
|
||||
AUTHOR: |
||||
|
||||
If you have any questions or problems feel free to send me mail. |
||||
|
||||
Gray Watson |
||||
http://256.com/gray/ |
||||
|
||||
------------------------------------------------------------------------------- |
||||
File diff suppressed because it is too large
Load Diff
@ -1,466 +0,0 @@ |
||||
/*
|
||||
* Memory pool defines. |
||||
* |
||||
* Copyright 1996 by Gray Watson. |
||||
* |
||||
* This file is part of the mpool package. |
||||
* |
||||
* Permission to use, copy, modify, and distribute this software for |
||||
* any purpose and without fee is hereby granted, provided that the |
||||
* above copyright notice and this permission notice appear in all |
||||
* copies, and that the name of Gray Watson not be used in advertising |
||||
* or publicity pertaining to distribution of the document or software |
||||
* without specific, written prior permission. |
||||
* |
||||
* Gray Watson makes no representations about the suitability of the |
||||
* software described herein for any purpose. It is provided "as is" |
||||
* without express or implied warranty. |
||||
* |
||||
* The author may be reached via http://256.com/gray/
|
||||
* |
||||
* $Id: mpool.h,v 1.4 2006/05/31 20:26:11 gray Exp $ |
||||
*/ |
||||
|
||||
#ifndef __MPOOL_H__ |
||||
#define __MPOOL_H__ |
||||
|
||||
#include <sys/types.h> |
||||
|
||||
/*
|
||||
* mpool flags to mpool_alloc or mpool_set_attr |
||||
*/ |
||||
|
||||
/*
|
||||
* Choose a best fit algorithm not first fit. This takes more CPU |
||||
* time but will result in a tighter heap. |
||||
*/ |
||||
#define MPOOL_FLAG_BEST_FIT (1<<0) |
||||
|
||||
/*
|
||||
* By default the library adds 2 bytes onto all allocations to insert |
||||
* a magic number that it can look for to determine how large a freed |
||||
* memory chunk is. This flag indicates that few if any frees are |
||||
* going to be performed on the pool and to not waste memory on these |
||||
* bytes. |
||||
*/ |
||||
#define MPOOL_FLAG_NO_FREE (1<<1) |
||||
|
||||
/*
|
||||
* This enables very heavy packing at the possible expense of CPU. |
||||
* This affects a number of parts of the library. |
||||
* |
||||
* By default the 1st page of memory is reserved for the main mpool |
||||
* structure. This flag will cause the rest of the 1st block to be |
||||
* available for use as user memory. |
||||
* |
||||
* By default the library looks through the memory when freed looking |
||||
* for a magic value. There is an internal max size that it will look |
||||
* and then it will give up. This flag forces it to look until it |
||||
* finds it. |
||||
*/ |
||||
#define MPOOL_FLAG_HEAVY_PACKING (1<<2) |
||||
|
||||
/*
|
||||
* Use sbrk not mmap to allocate pages. This is not recommended for |
||||
* normal use. |
||||
*/ |
||||
#define MPOOL_FLAG_USE_SBRK (1<<3) |
||||
|
||||
/*
|
||||
* Mpool error codes |
||||
*/ |
||||
#define MPOOL_ERROR_NONE 1 /* no error */ |
||||
#define MPOOL_ERROR_ARG_NULL 2 /* function argument is null */ |
||||
#define MPOOL_ERROR_ARG_INVALID 3 /* function argument is invalid */ |
||||
#define MPOOL_ERROR_PNT 4 /* invalid mpool pointer */ |
||||
#define MPOOL_ERROR_POOL_OVER 5 /* mpool structure was overwritten */ |
||||
#define MPOOL_ERROR_PAGE_SIZE 6 /* could not get system page-size */ |
||||
#define MPOOL_ERROR_OPEN_ZERO 7 /* could not open /dev/zero */ |
||||
#define MPOOL_ERROR_NO_MEM 8 /* no memory available */ |
||||
#define MPOOL_ERROR_MMAP 9 /* problems with mmap */ |
||||
#define MPOOL_ERROR_SIZE 10 /* error processing requested size */ |
||||
#define MPOOL_ERROR_TOO_BIG 11 /* allocation exceeded max size */ |
||||
#define MPOOL_ERROR_MEM 12 /* invalid memory address */ |
||||
#define MPOOL_ERROR_MEM_OVER 13 /* memory lower bounds overwritten */ |
||||
#define MPOOL_ERROR_NOT_FOUND 14 /* memory block not found in pool */ |
||||
#define MPOOL_ERROR_IS_FREE 15 /* memory block already free */ |
||||
#define MPOOL_ERROR_BLOCK_STAT 16 /* invalid internal block status */ |
||||
#define MPOOL_ERROR_FREE_ADDR 17 /* invalid internal free address */ |
||||
#define MPOOL_ERROR_SBRK_CONTIG 18 /* sbrk did not return contiguous mem*/ |
||||
#define MPOOL_ERROR_NO_PAGES 19 /* ran out of pages in pool */ |
||||
#define MPOOL_ERROR_ALLOC 20 /* calloc,malloc,free,realloc failed */ |
||||
#define MPOOL_ERROR_PNT_OVER 21 /* pointer structure was overwritten */ |
||||
|
||||
/*
|
||||
* Mpool function IDs for the mpool_log_func callback function. |
||||
*/ |
||||
#define MPOOL_FUNC_CLOSE 1 /* mpool_close function called */ |
||||
#define MPOOL_FUNC_CLEAR 2 /* mpool_clear function called */ |
||||
#define MPOOL_FUNC_ALLOC 3 /* mpool_alloc function called */ |
||||
#define MPOOL_FUNC_CALLOC 4 /* mpool_calloc function called */ |
||||
#define MPOOL_FUNC_FREE 5 /* mpool_free function called */ |
||||
#define MPOOL_FUNC_RESIZE 6 /* mpool_resize function called */ |
||||
|
||||
/*
|
||||
* void mpool_log_func_t |
||||
* |
||||
* DESCRIPTION: |
||||
* |
||||
* Mpool transaction log function. |
||||
* |
||||
* RETURNS: |
||||
* |
||||
* None. |
||||
* |
||||
* ARGUMENT: |
||||
* |
||||
* mp_p -> Associated mpool address. |
||||
* |
||||
* func_id -> Integer function ID which identifies which mpool |
||||
* function is being called. |
||||
* |
||||
* byte_size -> Optionally specified byte size. |
||||
* |
||||
* ele_n -> Optionally specified element number. For mpool_calloc |
||||
* only. |
||||
* |
||||
* new_addr -> Optionally specified new address. For mpool_alloc, |
||||
* mpool_calloc, and mpool_resize only. |
||||
* |
||||
* old_addr -> Optionally specified old address. For mpool_resize and |
||||
* mpool_free only. |
||||
* |
||||
* old_byte_size -> Optionally specified old byte size. For |
||||
* mpool_resize only. |
||||
*/ |
||||
typedef void (*mpool_log_func_t)(const void *mp_p, |
||||
const int func_id, |
||||
const unsigned long byte_size, |
||||
const unsigned long ele_n, |
||||
const void *old_addr, const void *new_addr, |
||||
const unsigned long old_byte_size); |
||||
|
||||
#ifdef MPOOL_MAIN |
||||
|
||||
#include "mpool_loc.h" |
||||
|
||||
#else |
||||
|
||||
/* generic mpool type */ |
||||
typedef void mpool_t; |
||||
|
||||
#endif |
||||
|
||||
/*<<<<<<<<<< The below prototypes are auto-generated by fillproto */ |
||||
|
||||
/*
|
||||
* mpool_t *mpool_open |
||||
* |
||||
* DESCRIPTION: |
||||
* |
||||
* Open/allocate a new memory pool. |
||||
* |
||||
* RETURNS: |
||||
* |
||||
* Success - Pool pointer which must be passed to mpool_close to |
||||
* deallocate. |
||||
* |
||||
* Failure - NULL |
||||
* |
||||
* ARGUMENTS: |
||||
* |
||||
* flags -> Flags to set attributes of the memory pool. See the top |
||||
* of mpool.h. |
||||
* |
||||
* page_size -> Set the internal memory page-size. This must be a |
||||
* multiple of the getpagesize() value. Set to 0 for the default. |
||||
* |
||||
* start_addr -> Starting address to try and allocate memory pools. |
||||
* This is ignored if the MPOOL_FLAG_USE_SBRK is enabled. |
||||
* |
||||
* error_p <- Pointer to integer which, if not NULL, will be set with |
||||
* a mpool error code. |
||||
*/ |
||||
extern |
||||
mpool_t *mpool_open(const unsigned int flags, const unsigned int page_size, |
||||
void *start_addr, int *error_p); |
||||
|
||||
/*
|
||||
* int mpool_close |
||||
* |
||||
* DESCRIPTION: |
||||
* |
||||
* Close/free a memory allocation pool previously opened with |
||||
* mpool_open. |
||||
* |
||||
* RETURNS: |
||||
* |
||||
* Success - MPOOL_ERROR_NONE |
||||
* |
||||
* Failure - Mpool error code |
||||
* |
||||
* ARGUMENTS: |
||||
* |
||||
* mp_p <-> Pointer to our memory pool. |
||||
*/ |
||||
extern |
||||
int mpool_close(mpool_t *mp_p); |
||||
|
||||
/*
|
||||
* int mpool_clear |
||||
* |
||||
* DESCRIPTION: |
||||
* |
||||
* Wipe an opened memory pool clean so we can start again. |
||||
* |
||||
* RETURNS: |
||||
* |
||||
* Success - MPOOL_ERROR_NONE |
||||
* |
||||
* Failure - Mpool error code |
||||
* |
||||
* ARGUMENTS: |
||||
* |
||||
* mp_p <-> Pointer to our memory pool. |
||||
*/ |
||||
extern |
||||
int mpool_clear(mpool_t *mp_p); |
||||
|
||||
/*
|
||||
* void *mpool_alloc |
||||
* |
||||
* DESCRIPTION: |
||||
* |
||||
* Allocate space for bytes inside of an already open memory pool. |
||||
* |
||||
* RETURNS: |
||||
* |
||||
* Success - Pointer to the address to use. |
||||
* |
||||
* Failure - NULL |
||||
* |
||||
* ARGUMENTS: |
||||
* |
||||
* mp_p <-> Pointer to the memory pool. If NULL then it will do a |
||||
* normal malloc. |
||||
* |
||||
* byte_size -> Number of bytes to allocate in the pool. Must be >0. |
||||
* |
||||
* error_p <- Pointer to integer which, if not NULL, will be set with |
||||
* a mpool error code. |
||||
*/ |
||||
extern |
||||
void *mpool_alloc(mpool_t *mp_p, const unsigned long byte_size, |
||||
int *error_p); |
||||
|
||||
/*
|
||||
* void *mpool_calloc |
||||
* |
||||
* DESCRIPTION: |
||||
* |
||||
* Allocate space for elements of bytes in the memory pool and zero |
||||
* the space afterwards. |
||||
* |
||||
* RETURNS: |
||||
* |
||||
* Success - Pointer to the address to use. |
||||
* |
||||
* Failure - NULL |
||||
* |
||||
* ARGUMENTS: |
||||
* |
||||
* mp_p <-> Pointer to the memory pool. If NULL then it will do a |
||||
* normal calloc. |
||||
* |
||||
* ele_n -> Number of elements to allocate. |
||||
* |
||||
* ele_size -> Number of bytes per element being allocated. |
||||
* |
||||
* error_p <- Pointer to integer which, if not NULL, will be set with |
||||
* a mpool error code. |
||||
*/ |
||||
extern |
||||
void *mpool_calloc(mpool_t *mp_p, const unsigned long ele_n, |
||||
const unsigned long ele_size, int *error_p); |
||||
|
||||
/*
|
||||
* int mpool_free |
||||
* |
||||
* DESCRIPTION: |
||||
* |
||||
* Free an address from a memory pool. |
||||
* |
||||
* RETURNS: |
||||
* |
||||
* Success - MPOOL_ERROR_NONE |
||||
* |
||||
* Failure - Mpool error code |
||||
* |
||||
* ARGUMENTS: |
||||
* |
||||
* mp_p <-> Pointer to the memory pool. If NULL then it will do a |
||||
* normal free. |
||||
* |
||||
* addr <-> Address to free. |
||||
* |
||||
* size -> Size of the address being freed. |
||||
*/ |
||||
extern |
||||
int mpool_free(mpool_t *mp_p, void *addr); |
||||
|
||||
/*
|
||||
* void *mpool_resize |
||||
* |
||||
* DESCRIPTION: |
||||
* |
||||
* Reallocate an address in a mmeory pool to a new size. This is |
||||
* different from realloc in that it needs the old address' size. If |
||||
* you don't have it then you need to allocate new space, copy the |
||||
* data, and free the old pointer yourself. |
||||
* |
||||
* RETURNS: |
||||
* |
||||
* Success - Pointer to the address to use. |
||||
* |
||||
* Failure - NULL |
||||
* |
||||
* ARGUMENTS: |
||||
* |
||||
* mp_p <-> Pointer to the memory pool. If NULL then it will do a |
||||
* normal realloc. |
||||
* |
||||
* old_addr -> Previously allocated address. |
||||
* |
||||
* old_byte_size -> Size of the old address. Must be known, cannot be |
||||
* 0. |
||||
* |
||||
* new_byte_size -> New size of the allocation. |
||||
* |
||||
* error_p <- Pointer to integer which, if not NULL, will be set with |
||||
* a mpool error code. |
||||
*/ |
||||
extern |
||||
void *mpool_resize(mpool_t *mp_p, void *old_addr, |
||||
const unsigned long new_byte_size, |
||||
int *error_p); |
||||
extern |
||||
void *mpool_resize2(mpool_t *mp_p, void *old_addr, |
||||
const unsigned long new_byte_size, |
||||
int *error_p); |
||||
|
||||
/*
|
||||
* int mpool_stats |
||||
* |
||||
* DESCRIPTION: |
||||
* |
||||
* Return stats from the memory pool. |
||||
* |
||||
* RETURNS: |
||||
* |
||||
* Success - MPOOL_ERROR_NONE |
||||
* |
||||
* Failure - Mpool error code |
||||
* |
||||
* ARGUMENTS: |
||||
* |
||||
* mp_p -> Pointer to the memory pool. |
||||
* |
||||
* page_size_p <- Pointer to an unsigned integer which, if not NULL, |
||||
* will be set to the page-size of the pool. |
||||
* |
||||
* num_alloced_p <- Pointer to an unsigned long which, if not NULL, |
||||
* will be set to the number of pointers currently allocated in pool. |
||||
* |
||||
* user_alloced_p <- Pointer to an unsigned long which, if not NULL, |
||||
* will be set to the number of user bytes allocated in this pool. |
||||
* |
||||
* max_alloced_p <- Pointer to an unsigned long which, if not NULL, |
||||
* will be set to the maximum number of user bytes that have been |
||||
* allocated in this pool. |
||||
* |
||||
* tot_alloced_p <- Pointer to an unsigned long which, if not NULL, |
||||
* will be set to the total amount of space (including administrative |
||||
* overhead) used by the pool. |
||||
*/ |
||||
extern |
||||
int mpool_stats(const mpool_t *mp_p, unsigned int *page_size_p, |
||||
unsigned long *num_alloced_p, |
||||
unsigned long *user_alloced_p, |
||||
unsigned long *max_alloced_p, |
||||
unsigned long *tot_alloced_p); |
||||
|
||||
/*
|
||||
* int mpool_set_log_func |
||||
* |
||||
* DESCRIPTION: |
||||
* |
||||
* Set a logging callback function to be called whenever there was a |
||||
* memory transaction. See mpool_log_func_t. |
||||
* |
||||
* RETURNS: |
||||
* |
||||
* Success - MPOOL_ERROR_NONE |
||||
* |
||||
* Failure - Mpool error code |
||||
* |
||||
* ARGUMENTS: |
||||
* |
||||
* mp_p <-> Pointer to the memory pool. |
||||
* |
||||
* log_func -> Log function (defined in mpool.h) which will be called |
||||
* with each mpool transaction. |
||||
*/ |
||||
extern |
||||
int mpool_set_log_func(mpool_t *mp_p, mpool_log_func_t log_func); |
||||
|
||||
/*
|
||||
* int mpool_set_max_pages |
||||
* |
||||
* DESCRIPTION: |
||||
* |
||||
* Set the maximum number of pages that the library will use. Once it |
||||
* hits the limit it will return MPOOL_ERROR_NO_PAGES. |
||||
* |
||||
* NOTE: if the MPOOL_FLAG_HEAVY_PACKING is set then this max-pages |
||||
* value will include the page with the mpool header structure in it. |
||||
* If the flag is _not_ set then the max-pages will not include this |
||||
* first page. |
||||
* |
||||
* RETURNS: |
||||
* |
||||
* Success - MPOOL_ERROR_NONE |
||||
* |
||||
* Failure - Mpool error code |
||||
* |
||||
* ARGUMENTS: |
||||
* |
||||
* mp_p <-> Pointer to the memory pool. |
||||
* |
||||
* max_pages -> Maximum number of pages used by the library. |
||||
*/ |
||||
extern |
||||
int mpool_set_max_pages(mpool_t *mp_p, const unsigned int max_pages); |
||||
|
||||
/*
|
||||
* const char *mpool_strerror |
||||
* |
||||
* DESCRIPTION: |
||||
* |
||||
* Return the corresponding string for the error number. |
||||
* |
||||
* RETURNS: |
||||
* |
||||
* Success - String equivalient of the error. |
||||
* |
||||
* Failure - String "invalid error code" |
||||
* |
||||
* ARGUMENTS: |
||||
* |
||||
* error -> Error number that we are converting. |
||||
*/ |
||||
extern |
||||
const char *mpool_strerror(const int error); |
||||
|
||||
/*<<<<<<<<<< This is end of the auto-generated output from fillproto. */ |
||||
|
||||
#endif /* ! __MPOOL_H__ */ |
||||
@ -1,116 +0,0 @@ |
||||
/*
|
||||
* Memory pool local defines. |
||||
* |
||||
* Copyright 1996 by Gray Watson. |
||||
* |
||||
* This file is part of the mpool package. |
||||
* |
||||
* Permission to use, copy, modify, and distribute this software for |
||||
* any purpose and without fee is hereby granted, provided that the |
||||
* above copyright notice and this permission notice appear in all |
||||
* copies, and that the name of Gray Watson not be used in advertising |
||||
* or publicity pertaining to distribution of the document or software |
||||
* without specific, written prior permission. |
||||
* |
||||
* Gray Watson makes no representations about the suitability of the |
||||
* software described herein for any purpose. It is provided "as is" |
||||
* without express or implied warranty. |
||||
* |
||||
* The author may be reached via http://256.com/gray/
|
||||
* |
||||
* $Id: mpool_loc.h,v 1.2 2005/05/20 20:08:54 gray Exp $ |
||||
*/ |
||||
|
||||
#ifndef __MPOOL_LOC_H__ |
||||
#define __MPOOL_LOC_H__ |
||||
|
||||
#define MPOOL_MAGIC 0xABACABA /* magic for struct */ |
||||
#define BLOCK_MAGIC 0xB1B1007 /* magic for blocks */ |
||||
#define FENCE_MAGIC0 (unsigned char)(0xFAU) /* 1st magic mem byte */ |
||||
#define FENCE_MAGIC1 (unsigned char)(0xD3U) /* 2nd magic mem byte */ |
||||
|
||||
#define FENCE_SIZE 2 /* fence space */ |
||||
#define MIN_ALLOCATION (sizeof(mpool_free_t)) /* min alloc */ |
||||
#define MAX_FREE_SEARCH 10240 /* max size to search */ |
||||
#define MAX_FREE_LIST_SEARCH 100 /* max looking for free mem */ |
||||
|
||||
/*
|
||||
* bitflag tools for Variable and a Flag |
||||
*/ |
||||
#define BIT_FLAG(x) (1 << (x)) |
||||
#define BIT_SET(v,f) (v) |= (f) |
||||
#define BIT_CLEAR(v,f) (v) &= ~(f) |
||||
#define BIT_IS_SET(v,f) ((v) & (f)) |
||||
#define BIT_TOGGLE(v,f) (v) ^= (f) |
||||
|
||||
#define SET_POINTER(pnt, val) \ |
||||
do { \
|
||||
if ((pnt) != NULL) { \
|
||||
(*(pnt)) = (val); \
|
||||
} \
|
||||
} while(0) |
||||
|
||||
#define BLOCK_FLAG_USED BIT_FLAG(0) /* block is used */ |
||||
#define BLOCK_FLAG_FREE BIT_FLAG(1) /* block is free */ |
||||
|
||||
#define DEFAULT_PAGE_MULT 16 /* pagesize = this * getpagesize*/ |
||||
|
||||
/* How many pages SIZE bytes resides in. We add in the block header. */ |
||||
#define PAGES_IN_SIZE(mp_p, size) (((size) + sizeof(mpool_block_t) + \ |
||||
(mp_p)->mp_page_size - 1) / \
|
||||
(mp_p)->mp_page_size) |
||||
#define SIZE_OF_PAGES(mp_p, page_n) ((page_n) * (mp_p)->mp_page_size) |
||||
#define MAX_BITS 30 /* we only can allocate 1gb chunks */ |
||||
|
||||
#define MAX_BLOCK_USER_MEMORY(mp_p) ((mp_p)->mp_page_size - \ |
||||
sizeof(mpool_block_t)) |
||||
#define FIRST_ADDR_IN_BLOCK(block_p) (void *)((char *)(block_p) + \ |
||||
sizeof(mpool_block_t)) |
||||
#define MEMORY_IN_BLOCK(block_p) ((char *)(block_p)->mb_bounds_p - \ |
||||
((char *)(block_p) + \
|
||||
sizeof(mpool_block_t))) |
||||
|
||||
typedef struct { |
||||
unsigned int mp_magic; /* magic number for struct */ |
||||
unsigned int mp_flags; /* flags for the struct */ |
||||
unsigned long mp_alloc_c; /* number of allocations */ |
||||
unsigned long mp_user_alloc; /* user bytes allocated */ |
||||
unsigned long mp_max_alloc; /* maximum user bytes allocated */ |
||||
unsigned int mp_page_c; /* number of pages allocated */ |
||||
unsigned int mp_max_pages; /* maximum number of pages to use */ |
||||
unsigned int mp_page_size; /* page-size of our system */ |
||||
int mp_fd; /* fd for /dev/zero if mmap-ing */ |
||||
off_t mp_top; /* top of our allocations in fd */
|
||||
mpool_log_func_t mp_log_func; /* log callback function */ |
||||
void *mp_addr; /* current address for mmaping */ |
||||
void *mp_min_p; /* min address in pool for checks */ |
||||
void *mp_bounds_p; /* max address in pool for checks */ |
||||
struct mpool_block_st *mp_first_p; /* first memory block we are using */ |
||||
struct mpool_block_st *mp_last_p; /* last memory block we are using */ |
||||
struct mpool_block_st *mp_free[MAX_BITS + 1]; /* free lists based on size */ |
||||
unsigned int mp_magic2; /* upper magic for overwrite sanity */ |
||||
} mpool_t; |
||||
|
||||
/* for debuggers to be able to interrogate the generic type in the .h file */ |
||||
typedef mpool_t mpool_ext_t; |
||||
|
||||
/*
|
||||
* Block header structure. This structure *MUST* be long-word |
||||
* aligned. |
||||
*/ |
||||
typedef struct mpool_block_st { |
||||
unsigned int mb_magic; /* magic number for block header */ |
||||
void *mb_bounds_p; /* block boundary location */ |
||||
struct mpool_block_st *mb_next_p; /* linked list next pointer */ |
||||
unsigned int mb_magic2; /* upper magic for overwrite sanity */ |
||||
} mpool_block_t; |
||||
|
||||
/*
|
||||
* Free list structure. |
||||
*/ |
||||
typedef struct { |
||||
void *mf_next_p; /* pointer to the next free address */ |
||||
unsigned long mf_size; /* size of the free block */ |
||||
} mpool_free_t; |
||||
|
||||
#endif /* ! __MPOOL_LOC_H__ */ |
||||
@ -1,914 +0,0 @@ |
||||
/*
|
||||
* Memory pool test program. |
||||
* |
||||
* Copyright 1996 by Gray Watson. |
||||
* |
||||
* This file is part of the mpool package. |
||||
* |
||||
* Permission to use, copy, modify, and distribute this software for |
||||
* any purpose and without fee is hereby granted, provided that the |
||||
* above copyright notice and this permission notice appear in all |
||||
* copies, and that the name of Gray Watson not be used in advertising |
||||
* or publicity pertaining to distribution of the document or software |
||||
* without specific, written prior permission. |
||||
* |
||||
* Gray Watson makes no representations about the suitability of the |
||||
* software described herein for any purpose. It is provided "as is" |
||||
* without express or implied warranty. |
||||
* |
||||
* The author may be reached via http://256.com/gray/
|
||||
* |
||||
* $Id: mpool_t.c,v 1.2 2005/05/20 20:08:55 gray Exp $ |
||||
*/ |
||||
|
||||
/*
|
||||
* Test program for the malloc library. Current it is interactive although |
||||
* should be script based. |
||||
*/ |
||||
|
||||
#include <errno.h> |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
#include <time.h> |
||||
#include <unistd.h> |
||||
|
||||
#include "mpool.h" |
||||
|
||||
#ifdef __GNUC__ |
||||
#ident "$Id: mpool_t.c,v 1.2 2005/05/20 20:08:55 gray Exp $" |
||||
#else |
||||
static char *rcs_id = "$Id: mpool_t.c,v 1.2 2005/05/20 20:08:55 gray Exp $"; |
||||
#endif |
||||
|
||||
#define DEFAULT_ITERATIONS 10000 |
||||
#define MAX_POINTERS 1024 |
||||
#define MAX_ALLOC (1024 * 1024) |
||||
#define MIN_AVAIL 10 |
||||
|
||||
#define RANDOM_VALUE(x) ((random() % ((x) * 10)) / 10) |
||||
|
||||
/* pointer tracking structure */ |
||||
struct pnt_info_st { |
||||
long pi_crc; /* crc of storage */ |
||||
long pi_size; /* size of storage */ |
||||
void *pi_pnt; /* pnt to storage */ |
||||
struct pnt_info_st *pi_next; /* pnt to next */ |
||||
}; |
||||
|
||||
typedef struct pnt_info_st pnt_info_t; |
||||
|
||||
static pnt_info_t *pointer_grid; |
||||
|
||||
/* argument variables */ |
||||
static int best_fit_b = 0; /* set best fit flag */ |
||||
static int heavy_pack_b = 0; /* set heavy pack flg*/ |
||||
static int interactive_b = 0; /* interactive flag */ |
||||
static int log_trxn_b = 0; /* log mem trxns */ |
||||
static long max_alloc = MAX_ALLOC; /* amt of mem to use */ |
||||
static int max_pages_n = 0; /* max # pages */ |
||||
static int use_malloc_b = 0; /* use system alloc */ |
||||
static int max_pointers = MAX_POINTERS; /* # of pnts to use */ |
||||
static int no_free_b = 0; /* set no free flag */ |
||||
static long page_size = 0; /* mpool pagesize */ |
||||
static int use_sbrk_b = 0; /* use sbrk not mmap */ |
||||
static unsigned int seed_random = 0; /* random seed */ |
||||
static int default_iter_n = DEFAULT_ITERATIONS; /* # of iters */ |
||||
static int verbose_b = 0; /* verbose flag */ |
||||
|
||||
/*
|
||||
* static long hex_to_long |
||||
* |
||||
* DESCRIPTION: |
||||
* |
||||
* Hexadecimal string to integer translation. |
||||
* |
||||
* RETURNS: |
||||
* |
||||
* Long value of converted hex string. |
||||
* |
||||
* ARGUMENTS: |
||||
* |
||||
* str -> Hex string we are converting. |
||||
*/ |
||||
static long hex_to_long(const char *str) |
||||
{ |
||||
long ret; |
||||
const char *str_p = str; |
||||
|
||||
/* strip off spaces */ |
||||
for (; *str_p == ' ' || *str_p == '\t'; str_p++) { |
||||
} |
||||
|
||||
/* skip a leading 0[xX] */ |
||||
if (*str_p == '0' && (*(str_p + 1) == 'x' || *(str_p + 1) == 'X')) { |
||||
str_p += 2; |
||||
} |
||||
|
||||
for (ret = 0;; str_p++) { |
||||
if (*str_p >= '0' && *str_p <= '9') { |
||||
ret = ret * 16 + (*str_p - '0'); |
||||
} |
||||
else if (*str_p >= 'a' && *str_p <= 'f') { |
||||
ret = ret * 16 + (*str_p - 'a' + 10); |
||||
} |
||||
else if (*str_p >= 'A' && *str_p <= 'F') { |
||||
ret = ret * 16 + (*str_p - 'A' + 10); |
||||
} |
||||
else { |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
/*
|
||||
* static void* get_address |
||||
* |
||||
* DESCRIPTION: |
||||
* |
||||
* Read an address from the user. |
||||
* |
||||
* RETURNS: |
||||
* |
||||
* Address read in from user. |
||||
* |
||||
* ARGUMENTS: |
||||
* |
||||
* None. |
||||
*/ |
||||
static void *get_address(void) |
||||
{ |
||||
char line[80]; |
||||
void *pnt; |
||||
|
||||
do { |
||||
(void)printf("Enter a hex address: "); |
||||
if (fgets(line, sizeof(line), stdin) == NULL) { |
||||
return NULL; |
||||
} |
||||
} while (line[0] == '\0'); |
||||
|
||||
pnt = (void *)hex_to_long(line); |
||||
|
||||
return pnt; |
||||
} |
||||
|
||||
/*
|
||||
* static void do_random |
||||
* |
||||
* DESCRIPTION: |
||||
* |
||||
* Try ITER_N random program iterations, returns 1 on success else 0 |
||||
* |
||||
* RETURNS: |
||||
* |
||||
* None. |
||||
* |
||||
* ARGUMENTS: |
||||
* |
||||
* pool <-> Out memory pool. |
||||
* |
||||
* iter_n -> Number of iterations to run. |
||||
*/ |
||||
static void do_random(mpool_t *pool, const int iter_n) |
||||
{ |
||||
int iter_c, free_c, ret; |
||||
long max = max_alloc, amount; |
||||
char *chunk_p; |
||||
void *new_pnt; |
||||
pnt_info_t *free_p, *used_p = NULL; |
||||
pnt_info_t *pnt_p, *last_p; |
||||
|
||||
if (use_malloc_b) { |
||||
pointer_grid = (pnt_info_t *)malloc(sizeof(pnt_info_t) * max_pointers); |
||||
} |
||||
else { |
||||
pointer_grid = (pnt_info_t *)mpool_alloc(pool, |
||||
sizeof(pnt_info_t) * max_pointers, |
||||
&ret); |
||||
} |
||||
if (pointer_grid == NULL) { |
||||
(void)printf("mpool_t: problems allocating %d pointer slots: %s\n", |
||||
max_pointers, strerror(errno)); |
||||
return; |
||||
} |
||||
|
||||
/* initialize free list */ |
||||
free_p = pointer_grid; |
||||
for (pnt_p = pointer_grid; pnt_p < pointer_grid + max_pointers; pnt_p++) { |
||||
pnt_p->pi_size = 0; |
||||
pnt_p->pi_pnt = NULL; |
||||
pnt_p->pi_next = pnt_p + 1; |
||||
} |
||||
/* redo the last next pointer */ |
||||
(pnt_p - 1)->pi_next = NULL; |
||||
free_c = max_pointers; |
||||
|
||||
for (iter_c = 0; iter_c < iter_n;) { |
||||
int which; |
||||
|
||||
/* special case when doing non-linear stuff, sbrk took all memory */ |
||||
if (max < MIN_AVAIL && free_c == max_pointers) { |
||||
break; |
||||
} |
||||
|
||||
if (free_c < max_pointers && used_p == NULL) { |
||||
(void)fprintf(stderr, "mpool_t: problem with test program free list\n"); |
||||
exit(1); |
||||
} |
||||
|
||||
/* decide whether to malloc a new pointer or free/realloc an existing */ |
||||
which = RANDOM_VALUE(4); |
||||
|
||||
/*
|
||||
* < MIN_AVAIL means alloc as long as we have enough memory and |
||||
* there are free slots we do an allocation, else we free |
||||
*/ |
||||
if (free_c == max_pointers |
||||
|| (free_c > 0 && which < 3 && max >= MIN_AVAIL)) { |
||||
|
||||
while (1) { |
||||
amount = RANDOM_VALUE(max / 2); |
||||
if (amount > 0) { |
||||
break; |
||||
} |
||||
} |
||||
which = RANDOM_VALUE(9); |
||||
pnt_p = NULL; |
||||
|
||||
switch (which) { |
||||
|
||||
case 0: case 1: case 2: |
||||
pnt_p = free_p; |
||||
if (use_malloc_b) { |
||||
pnt_p->pi_pnt = malloc(amount); |
||||
} |
||||
else { |
||||
pnt_p->pi_pnt = mpool_alloc(pool, amount, &ret); |
||||
} |
||||
|
||||
if (verbose_b) { |
||||
(void)printf("%d: malloc %ld (max %ld) into slot %d. got %#lx\n", |
||||
iter_c + 1, amount, max, pnt_p - pointer_grid, |
||||
(long)pnt_p->pi_pnt); |
||||
} |
||||
|
||||
if (pnt_p->pi_pnt == NULL) { |
||||
(void)printf("malloc of %ld failed: %s\n", |
||||
amount, |
||||
(use_malloc_b ? strerror(errno) : mpool_strerror(ret))); |
||||
} |
||||
pnt_p->pi_size = amount; |
||||
break; |
||||
|
||||
case 3: case 4: case 5: |
||||
pnt_p = free_p; |
||||
if (use_malloc_b) { |
||||
pnt_p->pi_pnt = calloc(amount, sizeof(char)); |
||||
} |
||||
else { |
||||
pnt_p->pi_pnt = mpool_calloc(pool, amount, sizeof(char), &ret); |
||||
} |
||||
|
||||
if (verbose_b) { |
||||
(void)printf("%d: calloc %ld (max %ld) into slot %d. got %#lx\n", |
||||
iter_c + 1, amount, max, pnt_p - pointer_grid, |
||||
(long)pnt_p->pi_pnt); |
||||
} |
||||
|
||||
/* test the returned block to make sure that is has been cleared */ |
||||
if (pnt_p->pi_pnt == NULL) { |
||||
(void)printf("calloc of %ld failed: %s\n", |
||||
amount, |
||||
(use_malloc_b ? strerror(errno) : mpool_strerror(ret))); |
||||
} |
||||
else { |
||||
for (chunk_p = pnt_p->pi_pnt; |
||||
chunk_p < (char *)pnt_p->pi_pnt + amount; |
||||
chunk_p++) { |
||||
if (*chunk_p != '\0') { |
||||
(void)printf("calloc of %ld not zeroed on iteration #%d\n", |
||||
amount, iter_c + 1); |
||||
break; |
||||
} |
||||
} |
||||
pnt_p->pi_size = amount; |
||||
} |
||||
break; |
||||
|
||||
case 6: case 7: case 8: |
||||
if (free_c == max_pointers) { |
||||
continue; |
||||
} |
||||
|
||||
which = RANDOM_VALUE(max_pointers - free_c); |
||||
for (pnt_p = used_p; which > 0; which--) { |
||||
pnt_p = pnt_p->pi_next; |
||||
} |
||||
|
||||
if (use_malloc_b) { |
||||
new_pnt = realloc(pnt_p->pi_pnt, amount); |
||||
} |
||||
else { |
||||
new_pnt = mpool_resize(pool, pnt_p->pi_pnt, amount, |
||||
&ret); |
||||
} |
||||
|
||||
if (verbose_b) { |
||||
(void)printf("%d: resize %#lx from %ld to %ld (max %ld) slot %d. " |
||||
"got %#lx\n", |
||||
iter_c + 1, (long)pnt_p->pi_pnt, pnt_p->pi_size, amount, |
||||
max, pnt_p - pointer_grid, (long)new_pnt); |
||||
} |
||||
|
||||
if (new_pnt == NULL) { |
||||
(void)printf("resize of %#lx old size %ld new size %ld failed: %s\n", |
||||
(long)pnt_p->pi_pnt, pnt_p->pi_size, amount, |
||||
(use_malloc_b ? strerror(errno) : mpool_strerror(ret))); |
||||
pnt_p->pi_pnt = NULL; |
||||
pnt_p->pi_size = 0; |
||||
} |
||||
else { |
||||
/* we effectively freed the old memory */ |
||||
max += pnt_p->pi_size; |
||||
pnt_p->pi_pnt = new_pnt; |
||||
pnt_p->pi_size = amount; |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
break; |
||||
} |
||||
|
||||
if (pnt_p != NULL && pnt_p->pi_pnt != NULL) { |
||||
if (pnt_p == free_p) { |
||||
free_p = pnt_p->pi_next; |
||||
pnt_p->pi_next = used_p; |
||||
used_p = pnt_p; |
||||
free_c--; |
||||
} |
||||
|
||||
max -= amount; |
||||
iter_c++; |
||||
} |
||||
continue; |
||||
} |
||||
|
||||
/*
|
||||
* choose a rand slot to free and make sure it is not a free-slot |
||||
*/ |
||||
which = RANDOM_VALUE(max_pointers - free_c); |
||||
/* find pnt in the used list */ |
||||
last_p = NULL; |
||||
for (pnt_p = used_p, last_p = NULL; |
||||
pnt_p != NULL && which > 0; |
||||
last_p = pnt_p, pnt_p = pnt_p->pi_next, which--) { |
||||
} |
||||
if (pnt_p == NULL) { |
||||
/* huh? error here */ |
||||
abort(); |
||||
} |
||||
if (last_p == NULL) { |
||||
used_p = pnt_p->pi_next; |
||||
} |
||||
else { |
||||
last_p->pi_next = pnt_p->pi_next; |
||||
} |
||||
|
||||
if (use_malloc_b) { |
||||
free(pnt_p->pi_pnt); |
||||
} |
||||
else { |
||||
ret = mpool_free(pool, pnt_p->pi_pnt); |
||||
if (ret != MPOOL_ERROR_NONE) { |
||||
(void)printf("free error on pointer '%#lx' of size %ld: %s\n", |
||||
(long)pnt_p->pi_pnt, pnt_p->pi_size, |
||||
mpool_strerror(ret)); |
||||
} |
||||
} |
||||
|
||||
if (verbose_b) { |
||||
(void)printf("%d: free'd %ld bytes from slot %d (%#lx)\n", |
||||
iter_c + 1, pnt_p->pi_size, pnt_p - pointer_grid, |
||||
(long)pnt_p->pi_pnt); |
||||
} |
||||
|
||||
pnt_p->pi_pnt = NULL; |
||||
pnt_p->pi_next = free_p; |
||||
free_p = pnt_p; |
||||
free_c++; |
||||
|
||||
max += pnt_p->pi_size; |
||||
iter_c++; |
||||
} |
||||
|
||||
/* free used pointers */ |
||||
for (pnt_p = pointer_grid; pnt_p < pointer_grid + max_pointers; pnt_p++) { |
||||
if (pnt_p->pi_pnt != NULL) { |
||||
if (use_malloc_b) { |
||||
free(pnt_p->pi_pnt); |
||||
} |
||||
else { |
||||
ret = mpool_free(pool, pnt_p->pi_pnt); |
||||
if (ret != MPOOL_ERROR_NONE) { |
||||
(void)printf("free error on pointer '%#lx' of size %ld: %s\n", |
||||
(long)pnt_p->pi_pnt, pnt_p->pi_size, |
||||
mpool_strerror(ret)); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (use_malloc_b) { |
||||
free(pointer_grid); |
||||
} |
||||
else { |
||||
ret = mpool_free(pool, pointer_grid); |
||||
if (ret != MPOOL_ERROR_NONE) { |
||||
(void)printf("free error on grid pointer: %s\n", mpool_strerror(ret)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/*
|
||||
* static void do_interactive |
||||
* |
||||
* DESCRIPTION: |
||||
* |
||||
* Run the interactive section of the program. |
||||
* |
||||
* RETURNS: |
||||
* |
||||
* None. |
||||
* |
||||
* ARGUMENTS: |
||||
* |
||||
* pool <-> Out memory pool. |
||||
*/ |
||||
static void do_interactive(mpool_t *pool) |
||||
{ |
||||
int len, ret; |
||||
char line[128], *line_p; |
||||
void *pnt, *new_pnt; |
||||
|
||||
(void)printf("Mpool test program. Type 'help' for assistance.\n"); |
||||
|
||||
for (;;) { |
||||
(void)printf("> "); |
||||
if (fgets(line, sizeof(line), stdin) == NULL) { |
||||
break; |
||||
} |
||||
line_p = strchr(line, '\n'); |
||||
if (line_p != NULL) { |
||||
*line_p = '\0'; |
||||
} |
||||
|
||||
len = strlen(line); |
||||
if (len == 0) { |
||||
continue; |
||||
} |
||||
|
||||
if (strncmp(line, "?", len) == 0 |
||||
|| strncmp(line, "help", len) == 0) { |
||||
(void)printf("\thelp - print this message\n\n"); |
||||
|
||||
(void)printf("\tmalloc - allocate memory\n"); |
||||
(void)printf("\tcalloc - allocate/clear memory\n"); |
||||
(void)printf("\tresize - resize memory\n"); |
||||
(void)printf("\tfree - deallocate memory\n\n"); |
||||
|
||||
(void)printf("\tclear - clear the pool\n"); |
||||
(void)printf("\toverwrite - overwrite some memory to test errors\n"); |
||||
(void)printf("\trandom - randomly execute a number of [de] allocs\n"); |
||||
|
||||
(void)printf("\tquit - quit this test program\n"); |
||||
continue; |
||||
} |
||||
|
||||
if (strncmp(line, "quit", len) == 0) { |
||||
break; |
||||
} |
||||
|
||||
if (strncmp(line, "malloc", len) == 0) { |
||||
int size; |
||||
|
||||
(void)printf("How much to malloc: "); |
||||
if (fgets(line, sizeof(line), stdin) == NULL) { |
||||
break; |
||||
} |
||||
size = atoi(line); |
||||
pnt = mpool_alloc(pool, size, &ret); |
||||
if (pnt == NULL) { |
||||
(void)printf("malloc(%d) failed: %s\n", size, mpool_strerror(ret)); |
||||
} |
||||
else { |
||||
(void)printf("malloc(%d) returned '%#lx'\n", size, (long)pnt); |
||||
} |
||||
continue; |
||||
} |
||||
|
||||
if (strncmp(line, "calloc", len) == 0) { |
||||
int size; |
||||
|
||||
(void)printf("How much to calloc: "); |
||||
if (fgets(line, sizeof(line), stdin) == NULL) { |
||||
break; |
||||
} |
||||
size = atoi(line); |
||||
pnt = mpool_calloc(pool, size, sizeof(char), &ret); |
||||
if (pnt == NULL) { |
||||
(void)printf("calloc(%d) failed: %s\n", size, mpool_strerror(ret)); |
||||
} |
||||
else { |
||||
(void)printf("calloc(%d) returned '%#lx'\n", size, (long)pnt); |
||||
} |
||||
continue; |
||||
} |
||||
|
||||
if (strncmp(line, "resize", len) == 0) { |
||||
int size, old_size; |
||||
|
||||
pnt = get_address(); |
||||
|
||||
(void)printf("Old size of allocation: "); |
||||
if (fgets(line, sizeof(line), stdin) == NULL) { |
||||
break; |
||||
} |
||||
old_size = atoi(line); |
||||
(void)printf("New size of allocation: "); |
||||
if (fgets(line, sizeof(line), stdin) == NULL) { |
||||
break; |
||||
} |
||||
size = atoi(line); |
||||
|
||||
new_pnt = mpool_resize(pool, pnt, size, &ret); |
||||
if (new_pnt == NULL) { |
||||
(void)printf("resize(%#lx, %d) failed: %s\n", |
||||
(long)pnt, size, mpool_strerror(ret)); |
||||
} |
||||
else { |
||||
(void)printf("resize(%#lx, %d) returned '%#lx'\n", |
||||
(long)pnt, size, (long)new_pnt); |
||||
} |
||||
continue; |
||||
} |
||||
|
||||
if (strncmp(line, "free", len) == 0) { |
||||
int old_size; |
||||
|
||||
pnt = get_address(); |
||||
|
||||
(void)printf("Old minimum size we are freeing: "); |
||||
if (fgets(line, sizeof(line), stdin) == NULL) { |
||||
break; |
||||
} |
||||
old_size = atoi(line); |
||||
ret = mpool_free(pool, pnt); |
||||
if (ret != MPOOL_ERROR_NONE) { |
||||
(void)fprintf(stderr, "free failed: %s\n", mpool_strerror(ret)); |
||||
} |
||||
continue; |
||||
} |
||||
|
||||
if (strncmp(line, "clear", len) == 0) { |
||||
ret = mpool_clear(pool); |
||||
if (ret == MPOOL_ERROR_NONE) { |
||||
(void)fprintf(stderr, "clear succeeded\n"); |
||||
} |
||||
else { |
||||
(void)fprintf(stderr, "clear failed: %s\n", mpool_strerror(ret)); |
||||
} |
||||
continue; |
||||
} |
||||
|
||||
if (strncmp(line, "overwrite", len) == 0) { |
||||
char *overwrite = "OVERWRITTEN"; |
||||
|
||||
pnt = get_address(); |
||||
memcpy((char *)pnt, overwrite, strlen(overwrite)); |
||||
(void)printf("Done.\n"); |
||||
continue; |
||||
} |
||||
|
||||
/* do random heap hits */ |
||||
if (strncmp(line, "random", len) == 0) { |
||||
int iter_n; |
||||
|
||||
(void)printf("How many iterations[%d]: ", default_iter_n); |
||||
if (fgets(line, sizeof(line), stdin) == NULL) { |
||||
break; |
||||
} |
||||
if (line[0] == '\0' || line[0] == '\n') { |
||||
iter_n = default_iter_n; |
||||
} |
||||
else { |
||||
iter_n = atoi(line); |
||||
} |
||||
|
||||
do_random(pool, iter_n); |
||||
continue; |
||||
} |
||||
|
||||
(void)printf("Unknown command '%s'. Type 'help' for assistance.\n", line); |
||||
} |
||||
} |
||||
|
||||
/*
|
||||
* static void log_func |
||||
* |
||||
* DESCRIPTION: |
||||
* |
||||
* Mpool transaction log function. |
||||
* |
||||
* RETURNS: |
||||
* |
||||
* None. |
||||
* |
||||
* ARGUMENT: |
||||
* |
||||
* mp_p -> Associated mpool address. |
||||
* |
||||
* func_id -> Integer function ID which identifies which mpool |
||||
* function is being called. |
||||
* |
||||
* byte_size -> Optionally specified byte size. |
||||
* |
||||
* ele_n -> Optionally specified element number. For mpool_calloc |
||||
* only. |
||||
* |
||||
* new_addr -> Optionally specified new address. For mpool_alloc, |
||||
* mpool_calloc, and mpool_resize only. |
||||
* |
||||
* old_addr -> Optionally specified old address. For mpool_resize and |
||||
* mpool_free only. |
||||
* |
||||
* old_byte_size -> Optionally specified old byte size. For |
||||
* mpool_resize only. |
||||
*/ |
||||
static void log_func(const void *mp_p, const int func_id, |
||||
const unsigned long byte_size, |
||||
const unsigned long ele_n, |
||||
const void *new_addr, const void *old_addr, |
||||
const unsigned long old_byte_size) |
||||
{ |
||||
(void)printf("mp %#lx ", (long)mp_p); |
||||
|
||||
switch (func_id) { |
||||
|
||||
case MPOOL_FUNC_CLOSE: |
||||
(void)printf("close\n"); |
||||
break; |
||||
|
||||
case MPOOL_FUNC_CLEAR: |
||||
(void)printf("clear\n"); |
||||
break; |
||||
|
||||
case MPOOL_FUNC_ALLOC: |
||||
(void)printf("alloc %lu bytes got %#lx\n", |
||||
byte_size, (long)new_addr); |
||||
break; |
||||
|
||||
case MPOOL_FUNC_CALLOC: |
||||
(void)printf("calloc %lu ele size, %lu ele number, got %#lx\n", |
||||
byte_size, ele_n, (long)new_addr); |
||||
break; |
||||
|
||||
case MPOOL_FUNC_FREE: |
||||
(void)printf("free %#lx of %lu bytes\n", (long)old_addr, byte_size); |
||||
break; |
||||
|
||||
case MPOOL_FUNC_RESIZE: |
||||
(void)printf("resize %#lx of %lu bytes to %lu bytes, got %#lx\n", |
||||
(long)old_addr, old_byte_size, byte_size, |
||||
(long)new_addr); |
||||
break; |
||||
|
||||
default: |
||||
(void)printf("unknown function %d, %lu bytes\n", func_id, byte_size); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
/*
|
||||
* static void usage |
||||
* |
||||
* DESCRIPTION: |
||||
* |
||||
* Print a usage message. |
||||
* |
||||
* RETURNS: |
||||
* |
||||
* None. |
||||
* |
||||
* ARGUMENTS: |
||||
* |
||||
* None. |
||||
*/ |
||||
static void usage(void) |
||||
{ |
||||
(void)fprintf(stderr, |
||||
"Usage: mpool_t [-bhHilMnsv] [-m size] [-p number] " |
||||
"[-P size] [-S seed] [-t times]\n"); |
||||
(void)fprintf(stderr, |
||||
" -b set MPOOL_FLAG_BEST_FIT\n" |
||||
" -h set MPOOL_FLAG_NO_FREE\n" |
||||
" -H use system heap not mpool\n" |
||||
" -i turn on interactive mode\n" |
||||
" -l log memory transactions\n" |
||||
" -M max number pages in mpool\n" |
||||
" -n set MPOOL_FLAG_NO_FREE\n" |
||||
" -s use sbrk instead of mmap\n" |
||||
" -v enable verbose messages\n" |
||||
" -m size maximum allocation to test\n" |
||||
" -p max-pnts number of pointers to test\n" |
||||
" -S seed-rand seed for random function\n" |
||||
" -t interations number of iterations to run\n"); |
||||
exit(1);
|
||||
} |
||||
|
||||
/*
|
||||
* static void process_args |
||||
* |
||||
* DESCRIPTION: |
||||
* |
||||
* Process our arguments. |
||||
* |
||||
* RETURNS: |
||||
* |
||||
* None. |
||||
* |
||||
* ARGUMENTS: |
||||
* |
||||
* None. |
||||
*/ |
||||
static void process_args(int argc, char ** argv) |
||||
{ |
||||
argc--, argv++; |
||||
|
||||
/* process the args */ |
||||
for (; *argv != NULL; argv++, argc--) { |
||||
if (**argv != '-') { |
||||
continue; |
||||
} |
||||
|
||||
switch (*(*argv + 1)) { |
||||
|
||||
case 'b': |
||||
best_fit_b = 1; |
||||
break; |
||||
case 'h': |
||||
heavy_pack_b = 1; |
||||
break; |
||||
case 'H': |
||||
use_malloc_b = 1; |
||||
break; |
||||
case 'i': |
||||
interactive_b = 1; |
||||
break; |
||||
case 'l': |
||||
log_trxn_b = 1; |
||||
break; |
||||
case 'm': |
||||
argv++, argc--; |
||||
if (argc <= 0) { |
||||
usage(); |
||||
} |
||||
max_alloc = atoi(*argv); |
||||
break; |
||||
case 'M': |
||||
max_pages_n = 1; |
||||
break; |
||||
case 'n': |
||||
no_free_b = 1; |
||||
break; |
||||
case 'p': |
||||
argv++, argc--; |
||||
if (argc <= 0) { |
||||
usage(); |
||||
} |
||||
max_pointers = atoi(*argv); |
||||
break; |
||||
case 'P': |
||||
argv++, argc--; |
||||
if (argc <= 0) { |
||||
usage(); |
||||
} |
||||
page_size = atoi(*argv); |
||||
break; |
||||
case 'S': |
||||
argv++, argc--; |
||||
if (argc <= 0) { |
||||
usage(); |
||||
} |
||||
seed_random = atoi(*argv); |
||||
break; |
||||
case 't': |
||||
argv++, argc--; |
||||
if (argc <= 0) { |
||||
usage(); |
||||
} |
||||
default_iter_n = atoi(*argv); |
||||
break; |
||||
case 'v': |
||||
verbose_b = 1; |
||||
break; |
||||
default: |
||||
usage(); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
/*
|
||||
* Main routine |
||||
*/ |
||||
int main(int argc, char **argv) |
||||
{ |
||||
int ret; |
||||
unsigned int flags = 0, pool_page_size; |
||||
unsigned long num_alloced, user_alloced, max_alloced, tot_alloced; |
||||
mpool_t *pool; |
||||
|
||||
process_args(argc, argv); |
||||
|
||||
/* repeat until we get a non 0 seed */ |
||||
while (seed_random == 0) { |
||||
seed_random = time(0) ^ getpid(); |
||||
} |
||||
(void)srandom(seed_random); |
||||
|
||||
(void)printf("Random seed is %u\n", seed_random); |
||||
|
||||
if (best_fit_b) { |
||||
flags |= MPOOL_FLAG_BEST_FIT; |
||||
} |
||||
if (heavy_pack_b) { |
||||
flags |= MPOOL_FLAG_HEAVY_PACKING; |
||||
} |
||||
if (no_free_b) { |
||||
flags |= MPOOL_FLAG_NO_FREE; |
||||
} |
||||
if (use_sbrk_b) { |
||||
flags |= MPOOL_FLAG_USE_SBRK; |
||||
} |
||||
|
||||
/* open our memory pool */ |
||||
pool = mpool_open(flags, page_size, NULL, &ret); |
||||
if (pool == NULL) { |
||||
(void)fprintf(stderr, "Error in mpool_open: %s\n", mpool_strerror(ret)); |
||||
exit(1); |
||||
} |
||||
|
||||
/* are we logging transactions */ |
||||
if (log_trxn_b) { |
||||
ret = mpool_set_log_func(pool, log_func); |
||||
if (ret != MPOOL_ERROR_NONE) { |
||||
(void)fprintf(stderr, "Error in mpool_set_log_func: %s\n", |
||||
mpool_strerror(ret)); |
||||
} |
||||
} |
||||
|
||||
if (max_pages_n > 0) { |
||||
ret = mpool_set_max_pages(pool, max_pages_n); |
||||
if (ret != MPOOL_ERROR_NONE) { |
||||
(void)fprintf(stderr, "Error in mpool_set_max_pages: %s\n", |
||||
mpool_strerror(ret)); |
||||
} |
||||
} |
||||
|
||||
if (interactive_b) { |
||||
do_interactive(pool); |
||||
} |
||||
else { |
||||
(void)printf("Running %d tests (use -i for interactive)...\n", |
||||
default_iter_n); |
||||
(void)fflush(stdout); |
||||
|
||||
do_random(pool, default_iter_n); |
||||
} |
||||
|
||||
/* get stats from the pool */ |
||||
ret = mpool_stats(pool, &pool_page_size, &num_alloced, &user_alloced, |
||||
&max_alloced, &tot_alloced); |
||||
if (ret == MPOOL_ERROR_NONE) { |
||||
(void)printf("Pool page size = %d. Number active allocated = %lu\n", |
||||
pool_page_size, num_alloced); |
||||
(void)printf("User bytes allocated = %lu. Max space allocated = %lu\n", |
||||
user_alloced, max_alloced); |
||||
(void)printf("Total space allocated = %lu\n", tot_alloced); |
||||
} |
||||
else { |
||||
(void)fprintf(stderr, "Error in mpool_stats: %s\n", mpool_strerror(ret)); |
||||
} |
||||
|
||||
/* close the pool */ |
||||
ret = mpool_close(pool); |
||||
if (ret != MPOOL_ERROR_NONE) { |
||||
(void)fprintf(stderr, "Error in mpool_close: %s\n", mpool_strerror(ret)); |
||||
exit(1); |
||||
} |
||||
|
||||
exit(0); |
||||
} |
||||
@ -0,0 +1,253 @@ |
||||
/*
|
||||
* Copyright (C) 2008 Sourcefire, Inc. |
||||
* |
||||
* Authors: Alberto Wu |
||||
* |
||||
* This program is free software; you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License version 2 as |
||||
* published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
||||
* MA 02110-1301, USA. |
||||
*/ |
||||
|
||||
/* a naive pool allocator */ |
||||
|
||||
#if HAVE_CONFIG_H |
||||
#include "clamav-config.h" |
||||
#endif |
||||
|
||||
#ifdef USE_MPOOL |
||||
|
||||
#include <sys/types.h> |
||||
#include <sys/stat.h> |
||||
#include <fcntl.h> |
||||
#ifdef HAVE_UNISTD_H |
||||
#include <unistd.h> |
||||
#endif |
||||
#if HAVE_STRING_H |
||||
#include <string.h> |
||||
#endif |
||||
#include <sys/mman.h> |
||||
#include <stddef.h> |
||||
|
||||
|
||||
/* #define DEBUGMPOOL */ |
||||
#ifdef DEBUGMPOOL |
||||
#include <stdio.h> |
||||
FILE *lfd = NULL; |
||||
#define spam(...) fprintf(lfd, __VA_ARGS__) |
||||
#else |
||||
#define spam |
||||
#endif |
||||
|
||||
#include "mpool.h" |
||||
|
||||
//#define MIN_FRAGSIZE 4096 /* 1m2.282s */
|
||||
//#define MIN_FRAGSIZE 8192 /* 0m46.652s */
|
||||
//#define MIN_FRAGSIZE 16384 /* 0m8.365s */
|
||||
//#define MIN_FRAGSIZE 32768 /* 0m3.788s */
|
||||
//#define MIN_FRAGSIZE 65536 /* 0m2.759s */
|
||||
//#define MIN_FRAGSIZE 131072 /* 0m2.445s */
|
||||
#define MIN_FRAGSIZE 262144 /* 0m2.343s */ |
||||
//#define MIN_FRAGSIZE 524288 /* 0m2.387s */
|
||||
//#define MIN_FRAGSIZE 1048576 /* 0m2.392s */
|
||||
//#define MIN_FRAGSIZE 2097152 /* 0m2.402s */
|
||||
|
||||
|
||||
struct FRAG { |
||||
struct FRAG *next; |
||||
unsigned int sbits; |
||||
void *fake; |
||||
}; |
||||
#define FRAG_OVERHEAD (offsetof(struct FRAG, fake)) |
||||
|
||||
|
||||
static unsigned int align_to_pagesize(struct MP *mp, unsigned int size) { |
||||
return (size / mp->psize + (size % mp->psize != 0)) * mp->psize; |
||||
} |
||||
static unsigned int align_to_voidptr(unsigned int size) { |
||||
return (size / sizeof(void *) + (size % sizeof(void *) != 0)) * sizeof(void *); |
||||
} |
||||
|
||||
/* FIXME: use instead a bit2size table so we can spare bits and offer a better granularity */ |
||||
static unsigned int to_bits(unsigned int size) { |
||||
unsigned int i; |
||||
for(i=0; i<32; i++) |
||||
if((unsigned int)1<<i >= size) return i; |
||||
return i; /* NOTREACHED */ |
||||
} |
||||
static unsigned int from_bits(unsigned int bits) { |
||||
return 1<<bits; |
||||
} |
||||
|
||||
struct MP *mp_create() { |
||||
struct MP mp, *mp_p; |
||||
memset(&mp, 0, sizeof(mp)); |
||||
mp.psize = getpagesize(); |
||||
#ifdef DEBUGMPOOL |
||||
lfd = fopen("mmpool_log", "w"); |
||||
#endif |
||||
mp.fd = open("/dev/zero", O_RDWR, 0); |
||||
mp.top = align_to_pagesize(&mp, MIN_FRAGSIZE + 0*sizeof(mp)); |
||||
mp.mpm.usize = align_to_voidptr(sizeof(struct MPMAP)); |
||||
mp.mpm.size = mp.top - align_to_voidptr(sizeof(mp)); |
||||
if ((mp_p = (struct MP *)mmap(NULL, mp.top, PROT_READ | PROT_WRITE, MAP_PRIVATE, mp.fd, 0)) == MAP_FAILED) |
||||
return NULL; |
||||
memcpy(mp_p, &mp, sizeof(mp)); |
||||
spam("Map created @ %p->%p - size %u out of %u\n", mp_p, (void*)mp_p + mp.mpm.size, mp.mpm.usize, mp.mpm.size); |
||||
return mp_p; |
||||
} |
||||
|
||||
void mp_destroy(struct MP *mp) { |
||||
struct MPMAP *mpm_next = mp->mpm.next, *mpm; |
||||
close(mp->fd); |
||||
while((mpm = mpm_next)) { |
||||
mpm_next = mpm->next; |
||||
munmap((void *)mpm, mpm->size); |
||||
} |
||||
munmap((void *)mp, mp->mpm.size + align_to_voidptr(sizeof(mp))); |
||||
spam("Map destroyed @ %p\n", mp); |
||||
} |
||||
|
||||
void mp_flush(struct MP *mp) { |
||||
struct MPMAP *mpm_next = mp->mpm.next, *mpm; |
||||
while((mpm = mpm_next)) { |
||||
mpm_next = mpm->next; |
||||
munmap((void *)mpm + align_to_pagesize(mp, mpm->usize), mpm->size - align_to_pagesize(mp, mpm->usize)); |
||||
mpm->size = mpm->usize = align_to_pagesize(mp, mpm->usize); |
||||
} |
||||
munmap(&mp->mpm + align_to_pagesize(mp, mp->mpm.usize + align_to_voidptr(sizeof(mp))), mp->mpm.size - align_to_pagesize(mp, mp->mpm.usize + align_to_voidptr(sizeof(mp)))); |
||||
mp->mpm.size = mp->mpm.usize; |
||||
spam("Map flushed @ %p\n", mp); |
||||
} |
||||
|
||||
void check_all(struct MP *mp) { |
||||
struct MPMAP *mpm = &mp->mpm; |
||||
while(mpm) { |
||||
volatile unsigned char *c = (unsigned char *)mpm; |
||||
unsigned int len = mpm->size; |
||||
spam("checking object %p - size %u\n", mpm, len); |
||||
while (len--) { |
||||
c[len]; |
||||
} |
||||
mpm=mpm->next; |
||||
} |
||||
} |
||||
|
||||
void *mp_malloc(struct MP *mp, size_t size) { |
||||
unsigned int i, j, needed = align_to_voidptr(size + FRAG_OVERHEAD); |
||||
const unsigned int sbits = to_bits(needed); |
||||
struct FRAG *f = NULL; |
||||
struct MPMAP *mpm = &mp->mpm; |
||||
|
||||
// check_all(mp);
|
||||
if (!size) return NULL; |
||||
|
||||
j = sbits+2; |
||||
if (j<7) j = 7; |
||||
if (j > 32) j = 32; |
||||
|
||||
for (i=sbits; i<j; i++) |
||||
if((f = mp->avail[i])) break; |
||||
|
||||
/* Case 1: We have a free'd frag */ |
||||
if(f) { |
||||
spam("malloc %p size %u (freed)\n"), f, size; |
||||
mp->avail[i] = f->next; |
||||
return &f->fake; |
||||
} |
||||
|
||||
needed = from_bits(sbits); |
||||
|
||||
/* Case 2: We have nuff room available for this frag already */ |
||||
while(mpm) { |
||||
if(mpm->size - mpm->usize >= needed) { |
||||
f = (struct FRAG *)((void *)mpm + mpm->usize); |
||||
spam("malloc %p size %u (hole)\n", f, size); |
||||
mpm->usize += needed; |
||||
f->sbits = sbits; |
||||
return &f->fake; |
||||
} |
||||
mpm = mpm->next; |
||||
} |
||||
|
||||
/* Case 3: We allocate more */ |
||||
if (needed + align_to_voidptr(sizeof(*mpm)) > MIN_FRAGSIZE) |
||||
i = align_to_pagesize(mp, needed + align_to_voidptr(sizeof(*mpm))); |
||||
else |
||||
i = align_to_pagesize(mp, MIN_FRAGSIZE); |
||||
|
||||
if ((mpm = (struct MPMAP *)mmap(NULL, i, PROT_READ | PROT_WRITE, MAP_PRIVATE, mp->fd, mp->top)) == MAP_FAILED) { |
||||
spam("failed to alloc %u bytes (%u requested)\n", i, size); |
||||
return NULL; |
||||
} |
||||
mp->top += i; |
||||
mpm->size = i; |
||||
mpm->usize = needed + align_to_voidptr(sizeof(*mpm)); |
||||
mpm->next = mp->mpm.next; |
||||
mp->mpm.next = mpm; |
||||
f = (struct FRAG *)((void *)mpm + align_to_voidptr(sizeof(*mpm))); |
||||
spam("malloc %p size %u (new map)\n", f, size); |
||||
f->sbits = sbits; |
||||
return &f->fake; |
||||
} |
||||
|
||||
void mp_free(struct MP *mp, void *ptr) { |
||||
struct FRAG *f = (struct FRAG *)(ptr - FRAG_OVERHEAD); |
||||
if (!ptr) return; |
||||
|
||||
f->next = mp->avail[f->sbits]; |
||||
mp->avail[f->sbits] = f; |
||||
spam("free @ %p\n", f); |
||||
} |
||||
|
||||
void *mp_calloc(struct MP *mp, size_t nmemb, size_t size) { |
||||
unsigned int needed = nmemb*size; |
||||
void *ptr; |
||||
|
||||
if(!needed) return NULL; |
||||
if((ptr = mp_malloc(mp, needed))) |
||||
memset(ptr, 0, needed); |
||||
return ptr; |
||||
} |
||||
|
||||
void *mp_realloc(struct MP *mp, void *ptr, size_t size) { |
||||
struct FRAG *f = (struct FRAG *)(ptr - FRAG_OVERHEAD); |
||||
unsigned int csize; |
||||
void *new_ptr; |
||||
if (!ptr) return mp_malloc(mp, size); |
||||
|
||||
spam("realloc @ %p (size %u -> %u))\n", f, from_bits(f->sbits), size); |
||||
csize = from_bits(f->sbits) - FRAG_OVERHEAD; |
||||
if (csize >= size) return ptr; |
||||
if (!(new_ptr = mp_malloc(mp, size))) |
||||
return NULL; |
||||
memcpy(new_ptr, ptr, csize); |
||||
mp_free(mp, ptr); |
||||
return new_ptr; |
||||
} |
||||
|
||||
void *mp_realloc2(struct MP *mp, void *ptr, size_t size) { |
||||
struct FRAG *f = (struct FRAG *)(ptr - FRAG_OVERHEAD); |
||||
unsigned int csize; |
||||
void *new_ptr; |
||||
if (!ptr) return mp_malloc(mp, size); |
||||
|
||||
spam("realloc @ %p (size %u -> %u))\n", f, from_bits(f->sbits), size); |
||||
csize = from_bits(f->sbits) - FRAG_OVERHEAD; |
||||
if (csize >= size) return ptr; |
||||
if ((new_ptr = mp_malloc(mp, size))) |
||||
memcpy(new_ptr, ptr, csize); |
||||
mp_free(mp, ptr); |
||||
return new_ptr; |
||||
} |
||||
|
||||
#endif /* USE_MPOOL */ |
||||
@ -0,0 +1,62 @@ |
||||
/*
|
||||
* Copyright (C) 2008 Sourcefire, Inc. |
||||
* |
||||
* Authors: Alberto Wu |
||||
* |
||||
* This program is free software; you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License version 2 as |
||||
* published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
||||
* MA 02110-1301, USA. |
||||
*/ |
||||
|
||||
#ifndef MPOOL_H |
||||
#define MPOOL_H |
||||
|
||||
#ifdef USE_MPOOL |
||||
struct MPMAP { |
||||
struct MPMAP *next; |
||||
unsigned int size; |
||||
unsigned int usize; |
||||
}; |
||||
|
||||
struct MP { |
||||
int fd; |
||||
unsigned int psize; |
||||
unsigned int top; |
||||
struct FRAG *avail[32]; |
||||
struct MPMAP mpm; |
||||
}; |
||||
|
||||
typedef struct MP mp_t; |
||||
|
||||
mp_t *mp_create(void); |
||||
void mp_destroy(mp_t *mp); |
||||
void *mp_malloc(mp_t *mp, size_t size); |
||||
void mp_free(mp_t *mp, void *ptr); |
||||
void *mp_calloc(mp_t *mp, size_t nmemb, size_t size); |
||||
void *mp_realloc(mp_t *mp, void *ptr, size_t size); |
||||
void *mp_realloc2(mp_t *mp, void *ptr, size_t size); |
||||
void mp_flush(mp_t *mp); |
||||
|
||||
#else /* USE_MPOOL */ |
||||
|
||||
#define mp_malloc(a, b) cli_malloc(b) |
||||
#define mp_free(a, b) free(b) |
||||
#define mp_calloc(a, b, c) cli_calloc(b, c) |
||||
#define mp_realloc(a, b, c) cli_realloc(b, c) |
||||
#define mp_realloc2(a, b, c) cli_realloc2(b, c) |
||||
|
||||
#endif /* USE_MPOOL */ |
||||
|
||||
#endif |
||||
|
||||
|
||||
Loading…
Reference in new issue