--- libaitsess/src/Attic/mem.c 2012/02/27 20:56:38 1.1.2.1 +++ libaitsess/src/Attic/mem.c 2012/02/28 00:13:26 1.1.2.4 @@ -1,3 +1,48 @@ +/************************************************************************* +* (C) 2012 AITNET ltd - Sofia/Bulgaria - +* by Michael Pounov +* +* $Author: misho $ +* $Id: mem.c,v 1.1.2.4 2012/02/28 00:13:26 misho Exp $ +* +************************************************************************** +The ELWIX and AITNET software is distributed under the following +terms: + +All of the documentation and software included in the ELWIX and AITNET +Releases is copyrighted by ELWIX - Sofia/Bulgaria + +Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + by Michael Pounov . 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. All advertising materials mentioning features or use of this software + must display the following acknowledgement: +This product includes software developed by Michael Pounov +ELWIX - Embedded LightWeight unIX and its contributors. +4. Neither the name of AITNET nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. +*/ #include "global.h" @@ -10,6 +55,7 @@ mpool_t * mpool_init(void) { mpool_t *mp; + register int i; mp = malloc(sizeof(mpool_t)); if (!mp) { @@ -19,6 +65,14 @@ mpool_init(void) memset(mp, 0, sizeof(mpool_t)); pthread_mutex_init(&mp->pool_mtx, NULL); + + mpool_lock(mp); + for (i = 0; i < MEM_BUCKETS; i++) { + TAILQ_INIT(&mp->pool_active[i]); + TAILQ_INIT(&mp->pool_inactive[i]); + } + mpool_unlock(mp); + return mp; } @@ -86,6 +140,9 @@ pullInactive(mpool_t * __restrict mp, int idx) /* must be locked pool before use this function */ if ((m = TAILQ_FIRST(&mp->pool_inactive[idx]))) { TAILQ_REMOVE(&mp->pool_inactive[idx], m, alloc_node); + /* statistics */ + mp->pool_calls.cache--; + mp->pool_bytes.cache -= mem_size(m); /* clear name */ *m->alloc_name = 0; @@ -171,6 +228,54 @@ mpool_malloc(mpool_t * __restrict mp, u_int size, cons } /* + * mpool_purge() - Purge memory block cache and release resources + * + * @mp = Memory pool + * @atmost = Free at most in buckets + * return: -1 error or 0 ok + */ +int +mpool_purge(mpool_t * __restrict mp, u_int atmost) +{ + register int i, cx; + struct tagAlloc *m, *tmp; + + if (!mp) { + sess_SetErr(EINVAL, "Pool not specified"); + return -1; + } + + mpool_lock(mp); + + for (i = cx = 0; i < MEM_BUCKETS; cx = 0, i++) { + TAILQ_FOREACH_SAFE(m, &mp->pool_inactive[i], alloc_node, tmp) { + /* barrier for purge */ + if (cx < atmost) { + cx++; + continue; + } + + TAILQ_REMOVE(&mp->pool_inactive[i], m, alloc_node); + /* statistics */ + mp->pool_calls.cache--; + mp->pool_bytes.cache -= mem_size(m); + + mp->pool_calls.free++; + mp->pool_bytes.free += mem_size(m); + /* quota */ + mp->pool_quota.curr -= mem_size(m); + + if (m->alloc_mem) + free(m->alloc_mem); + free(m); + } + } + + mpool_unlock(mp); + return 0; +} + +/* * mpool_free() Free allocated memory with mpool_alloc() * * @mp = Memory pool @@ -199,6 +304,9 @@ mpool_free(mpool_t * __restrict mp, void * __restrict TAILQ_FOREACH(m, &mp->pool_active[idx], alloc_node) if (mem_data(m, void*) == data) { TAILQ_REMOVE(&mp->pool_active[idx], m, alloc_node); + /* statistics */ + mp->pool_calls.alloc--; + mp->pool_bytes.alloc -= mem_size(m); if (!purge) { TAILQ_INSERT_HEAD(&mp->pool_inactive[idx], m, alloc_node); @@ -206,12 +314,15 @@ mpool_free(mpool_t * __restrict mp, void * __restrict mp->pool_calls.cache++; mp->pool_bytes.cache += mem_size(m); } else { - if (m->alloc_mem) - free(m->alloc_mem); - free(m); /* statistics */ mp->pool_calls.free++; mp->pool_bytes.free += mem_size(m); + /* quota */ + mp->pool_quota.curr -= mem_size(m); + + if (m->alloc_mem) + free(m->alloc_mem); + free(m); } break; } @@ -245,6 +356,9 @@ mpool_free2(mpool_t * __restrict mp, u_int size, const TAILQ_FOREACH(m, &mp->pool_active[idx], alloc_node) if (!strcmp(m->alloc_name, memname)) { TAILQ_REMOVE(&mp->pool_active[idx], m, alloc_node); + /* statistics */ + mp->pool_calls.alloc--; + mp->pool_bytes.alloc -= mem_size(m); if (!purge) { TAILQ_INSERT_HEAD(&mp->pool_inactive[idx], m, alloc_node); @@ -252,12 +366,15 @@ mpool_free2(mpool_t * __restrict mp, u_int size, const mp->pool_calls.cache++; mp->pool_bytes.cache += mem_size(m); } else { - if (m->alloc_mem) - free(m->alloc_mem); - free(m); /* statistics */ mp->pool_calls.free++; mp->pool_bytes.free += mem_size(m); + /* quota */ + mp->pool_quota.curr -= mem_size(m); + + if (m->alloc_mem) + free(m->alloc_mem); + free(m); } break; } @@ -289,4 +406,38 @@ mpool_getmembynam(mpool_t * __restrict mp, u_int size, break; return mem_data(m, void*); +} + +/* + * mpool_getsizebyaddr() - Get size of allocated memory block by address + * + * @addr = allocated memory from mpool_malloc() + * return: usable size of allocated memory block + */ +inline u_int +mpool_getsizebyaddr(void * __restrict data) +{ + if (mpool_chkaddr(data)) + return 0; + + return (((u_int*) data)[-2] * sizeof(u_int)); +} + +/* + * mpool_chkaddr() - Check validity of given address + * + * @data = allocated memory from mpool_malloc() + * return: -1 bad address, 1 corrupted address or 0 ok + */ +inline int +mpool_chkaddr(void * __restrict data) +{ + /* check address range */ + if (MEM_BADADDR(data)) + return -1; + /* check sentinel */ + if (MEM_CORRUPT(data)) + return 1; + /* data address is ok! */ + return 0; }