|
|
| version 1.1.2.1, 2012/02/27 20:56:38 | version 1.1.2.5, 2012/02/28 00:25:25 |
|---|---|
| Line 1 | Line 1 |
| /************************************************************************* | |
| * (C) 2012 AITNET ltd - Sofia/Bulgaria - <misho@elwix.org> | |
| * by Michael Pounov <misho@openbsd-bg.org> | |
| * | |
| * $Author$ | |
| * $Id$ | |
| * | |
| ************************************************************************** | |
| 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 <info@elwix.org> | |
| Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 | |
| by Michael Pounov <misho@elwix.org>. 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 <misho@elwix.org> | |
| 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" | #include "global.h" |
| Line 10 mpool_t * | Line 55 mpool_t * |
| mpool_init(void) | mpool_init(void) |
| { | { |
| mpool_t *mp; | mpool_t *mp; |
| register int i; | |
| mp = malloc(sizeof(mpool_t)); | mp = malloc(sizeof(mpool_t)); |
| if (!mp) { | if (!mp) { |
| Line 19 mpool_init(void) | Line 65 mpool_init(void) |
| memset(mp, 0, sizeof(mpool_t)); | memset(mp, 0, sizeof(mpool_t)); |
| pthread_mutex_init(&mp->pool_mtx, NULL); | 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; | return mp; |
| } | } |
| Line 86 pullInactive(mpool_t * __restrict mp, int idx) | Line 140 pullInactive(mpool_t * __restrict mp, int idx) |
| /* must be locked pool before use this function */ | /* must be locked pool before use this function */ |
| if ((m = TAILQ_FIRST(&mp->pool_inactive[idx]))) { | if ((m = TAILQ_FIRST(&mp->pool_inactive[idx]))) { |
| TAILQ_REMOVE(&mp->pool_inactive[idx], m, alloc_node); | TAILQ_REMOVE(&mp->pool_inactive[idx], m, alloc_node); |
| /* statistics */ | |
| mp->pool_calls.cache--; | |
| mp->pool_bytes.cache -= mem_size(m); | |
| /* clear name */ | /* clear name */ |
| *m->alloc_name = 0; | *m->alloc_name = 0; |
| Line 171 mpool_malloc(mpool_t * __restrict mp, u_int size, cons | Line 228 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() | * mpool_free() Free allocated memory with mpool_alloc() |
| * | * |
| * @mp = Memory pool | * @mp = Memory pool |
| Line 193 mpool_free(mpool_t * __restrict mp, void * __restrict | Line 298 mpool_free(mpool_t * __restrict mp, void * __restrict |
| sess_SetErr(EFAULT, "Corrupted memory address"); | sess_SetErr(EFAULT, "Corrupted memory address"); |
| return -2; | return -2; |
| } else | } else |
| idx = BucketIndex(((u_int*)data)[-2]); | idx = BucketIndex(((u_int*)data)[-2] * sizeof(u_int)); |
| mpool_lock(mp); | mpool_lock(mp); |
| TAILQ_FOREACH(m, &mp->pool_active[idx], alloc_node) | TAILQ_FOREACH(m, &mp->pool_active[idx], alloc_node) |
| if (mem_data(m, void*) == data) { | if (mem_data(m, void*) == data) { |
| TAILQ_REMOVE(&mp->pool_active[idx], m, alloc_node); | TAILQ_REMOVE(&mp->pool_active[idx], m, alloc_node); |
| /* statistics */ | |
| mp->pool_calls.alloc--; | |
| mp->pool_bytes.alloc -= mem_size(m); | |
| if (!purge) { | if (!purge) { |
| TAILQ_INSERT_HEAD(&mp->pool_inactive[idx], m, alloc_node); | TAILQ_INSERT_HEAD(&mp->pool_inactive[idx], m, alloc_node); |
| Line 206 mpool_free(mpool_t * __restrict mp, void * __restrict | Line 314 mpool_free(mpool_t * __restrict mp, void * __restrict |
| mp->pool_calls.cache++; | mp->pool_calls.cache++; |
| mp->pool_bytes.cache += mem_size(m); | mp->pool_bytes.cache += mem_size(m); |
| } else { | } else { |
| if (m->alloc_mem) | |
| free(m->alloc_mem); | |
| free(m); | |
| /* statistics */ | /* statistics */ |
| mp->pool_calls.free++; | mp->pool_calls.free++; |
| mp->pool_bytes.free += mem_size(m); | 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; | break; |
| } | } |
| Line 245 mpool_free2(mpool_t * __restrict mp, u_int size, const | Line 356 mpool_free2(mpool_t * __restrict mp, u_int size, const |
| TAILQ_FOREACH(m, &mp->pool_active[idx], alloc_node) | TAILQ_FOREACH(m, &mp->pool_active[idx], alloc_node) |
| if (!strcmp(m->alloc_name, memname)) { | if (!strcmp(m->alloc_name, memname)) { |
| TAILQ_REMOVE(&mp->pool_active[idx], m, alloc_node); | TAILQ_REMOVE(&mp->pool_active[idx], m, alloc_node); |
| /* statistics */ | |
| mp->pool_calls.alloc--; | |
| mp->pool_bytes.alloc -= mem_size(m); | |
| if (!purge) { | if (!purge) { |
| TAILQ_INSERT_HEAD(&mp->pool_inactive[idx], m, alloc_node); | TAILQ_INSERT_HEAD(&mp->pool_inactive[idx], m, alloc_node); |
| Line 252 mpool_free2(mpool_t * __restrict mp, u_int size, const | Line 366 mpool_free2(mpool_t * __restrict mp, u_int size, const |
| mp->pool_calls.cache++; | mp->pool_calls.cache++; |
| mp->pool_bytes.cache += mem_size(m); | mp->pool_bytes.cache += mem_size(m); |
| } else { | } else { |
| if (m->alloc_mem) | |
| free(m->alloc_mem); | |
| free(m); | |
| /* statistics */ | /* statistics */ |
| mp->pool_calls.free++; | mp->pool_calls.free++; |
| mp->pool_bytes.free += mem_size(m); | 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; | break; |
| } | } |
| Line 289 mpool_getmembynam(mpool_t * __restrict mp, u_int size, | Line 406 mpool_getmembynam(mpool_t * __restrict mp, u_int size, |
| break; | break; |
| return mem_data(m, void*); | 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; | |
| } | } |