X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=trunk%2Fsrc%2Fmem.c;fp=trunk%2Fsrc%2Fmem.c;h=90ca516ba15e99f89bd54a640cc0ea5746407c36;hb=85718e4dcaf5f34496f629e45a47ec91145c6f9e;hp=0000000000000000000000000000000000000000;hpb=abb2bffe08424d2d7e612f423815aeb7c79b42de;p=iptables.git diff --git a/trunk/src/mem.c b/trunk/src/mem.c new file mode 100644 index 0000000..90ca516 --- /dev/null +++ b/trunk/src/mem.c @@ -0,0 +1,167 @@ +/* + Copyright (C) Slava Astashonok + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License. + + $Id: mem.c,v 1.4.2.2.2.1 2005/01/29 19:30:41 sla Exp $ +*/ + +#include +#include +#include + +#include +#include +#include + +#ifdef MEM_THREADSAFE +#include +#endif + +#ifdef MEM_THREADSAFE +static pthread_mutex_t mem_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif +static struct Mem *root; +unsigned int total_elements; +unsigned int free_elements; +static unsigned int element_size; +static unsigned int bulk_quantity; +static unsigned int limit_memory; +unsigned int total_memory; +static unsigned int mem_index_table_size; +static unsigned int element_table_size; +static unsigned int malloc_size; + +void *mem_alloc() +{ + unsigned int i; + struct Mem *mptr; + mem_index_t *iptr; +#if MEM_BITS == 0 + void *eptr; +#endif + +#ifdef MEM_THREADSAFE + pthread_mutex_lock(&mem_mutex); +#endif + if (!free_elements) { + if (limit_memory && (total_memory + malloc_size) > limit_memory) { +#if ((DEBUG) & DEBUG_M) + my_log(LOG_DEBUG, "M: limit exhausted"); +#endif + mptr = 0; + errno = ENOMEM; + goto done; + } + if (!(mptr = calloc(malloc_size, 1))) goto done; + iptr = (void *) mptr + sizeof(struct Mem); +#if MEM_BITS == 0 + eptr = (void *) iptr + mem_index_table_size; +#endif + for (i = 0; i < bulk_quantity; i++) { +#if MEM_BITS == 0 + *iptr++ = eptr; + eptr += element_size; +#else + *iptr++ = i; +#endif + } + mptr->free = bulk_quantity - 1; + free_elements += mptr->free; + total_elements += bulk_quantity; + total_memory += malloc_size; + mptr->first = iptr; + mptr->last = (void *) iptr + element_table_size - element_size; + mptr->next = root; + root = mptr; +#if ((DEBUG) & DEBUG_M) + my_log(LOG_DEBUG, "M: alloc bulk: base:%x first:%x last:%x", + mptr, mptr->first, mptr->last); + my_log(LOG_DEBUG, "M: mem: total: %d (%dKB), free: %d", + total_elements, total_memory >> 10, free_elements); +#endif + mptr = mptr->last; + goto done; + } + + mptr = root; + while (mptr->free == 0) mptr = mptr->next; + mptr->free--; + free_elements--; + iptr = (void *) mptr + sizeof(struct Mem); +#if MEM_BITS == 0 + mptr = iptr[mptr->free]; +#else + mptr = mptr->first + iptr[mptr->free] * element_size; +#endif + +done: +#if ((DEBUG) & DEBUG_M) + my_log(LOG_DEBUG, "M: alloc: %x", mptr); +#endif +#ifdef MEM_THREADSAFE + pthread_mutex_unlock(&mem_mutex); +#endif + return mptr; +} + +void mem_free(void *eptr) +{ + mem_index_t *iptr; + struct Mem *mptr, **pptr; + +#ifdef MEM_THREADSAFE + pthread_mutex_lock(&mem_mutex); +#endif +#if ((DEBUG) & DEBUG_M) + my_log(LOG_DEBUG, "M: free: %x", eptr); +#endif + mptr = root; + pptr = &root; + while (mptr->first > eptr || mptr->last < eptr) { + pptr = &mptr->next; + mptr = mptr->next; + } + iptr = (void *) mptr + sizeof(struct Mem); +#if MEM_BITS == 0 + iptr[mptr->free] = eptr; +#else + iptr[mptr->free] = (eptr - mptr->first) / element_size; +#endif + mptr->free++; + free_elements++; + if (mptr->free == bulk_quantity) { +#if ((DEBUG) & DEBUG_M) + my_log(LOG_DEBUG, "M: free bulk: base:%x first:%x last:%x", + mptr, mptr->first, mptr->last); +#endif + *pptr = mptr->next; + free(mptr); + total_elements -= bulk_quantity; + free_elements -= bulk_quantity; + total_memory -= malloc_size; +#if ((DEBUG) & DEBUG_M) + my_log(LOG_DEBUG, "M: mem: total: %d (%dKB), free: %d", + total_elements, total_memory >> 10, free_elements); +#endif + } +#ifdef MEM_THREADSAFE + pthread_mutex_unlock(&mem_mutex); +#endif +} + +int mem_init(unsigned int element, unsigned int bulk, unsigned int limit) +{ + bulk_quantity = (unsigned) (mem_index_t) bulk; /* for safety: movzbl, movzwl */ + mem_index_table_size = sizeof(mem_index_t) * bulk_quantity; + element_size = element; + element_table_size = element_size * bulk_quantity; + malloc_size = sizeof(struct Mem) + mem_index_table_size + element_table_size; + limit_memory = limit; +#if ((DEBUG) & DEBUG_M) + my_log(LOG_DEBUG, "M: init: element size:%d quantity:%d bulk size:%d limit:%d", + element_size, bulk_quantity, malloc_size, limit_memory); +#endif + return 0; +}