alpar@1: /* glpdmp.c (dynamic memory pool) */ alpar@1: alpar@1: /*********************************************************************** alpar@1: * This code is part of GLPK (GNU Linear Programming Kit). alpar@1: * alpar@1: * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, alpar@1: * 2009, 2010 Andrew Makhorin, Department for Applied Informatics, alpar@1: * Moscow Aviation Institute, Moscow, Russia. All rights reserved. alpar@1: * E-mail: . alpar@1: * alpar@1: * GLPK is free software: you can redistribute it and/or modify it alpar@1: * under the terms of the GNU General Public License as published by alpar@1: * the Free Software Foundation, either version 3 of the License, or alpar@1: * (at your option) any later version. alpar@1: * alpar@1: * GLPK is distributed in the hope that it will be useful, but WITHOUT alpar@1: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY alpar@1: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public alpar@1: * License for more details. alpar@1: * alpar@1: * You should have received a copy of the GNU General Public License alpar@1: * along with GLPK. If not, see . alpar@1: ***********************************************************************/ alpar@1: alpar@1: #include "glpdmp.h" alpar@1: alpar@1: #if 1 /* 29/VIII-2008 */ alpar@1: /* some processors need data to be properly aligned; the macro alpar@1: align_datasize enlarges the specified size of a data item to provide alpar@1: a proper alignment of immediately following data */ alpar@1: alpar@1: #define align_datasize(size) ((((size) + 7) / 8) * 8) alpar@1: /* 8 bytes is sufficient in both 32- and 64-bit environments */ alpar@1: #endif alpar@1: alpar@1: #ifdef GLP_DEBUG alpar@1: struct info alpar@1: { DMP *pool; alpar@1: int size; alpar@1: }; alpar@1: #endif alpar@1: alpar@1: /*********************************************************************** alpar@1: * NAME alpar@1: * alpar@1: * dmp_create_pool - create dynamic memory pool alpar@1: * alpar@1: * SYNOPSIS alpar@1: * alpar@1: * #include "glpdmp.h" alpar@1: * DMP *dmp_create_pool(void); alpar@1: * alpar@1: * DESCRIPTION alpar@1: * alpar@1: * The routine dmp_create_pool creates a dynamic memory pool. alpar@1: * alpar@1: * RETURNS alpar@1: * alpar@1: * The routine returns a pointer to the memory pool created. */ alpar@1: alpar@1: DMP *dmp_create_pool(void) alpar@1: { DMP *pool; alpar@1: int k; alpar@1: #ifdef GLP_DEBUG alpar@1: xprintf("dmp_create_pool: warning: debug mode enabled\n"); alpar@1: #endif alpar@1: pool = xmalloc(sizeof(DMP)); alpar@1: #if 0 alpar@1: pool->size = 0; alpar@1: #endif alpar@1: for (k = 0; k <= 31; k++) pool->avail[k] = NULL; alpar@1: pool->block = NULL; alpar@1: pool->used = DMP_BLK_SIZE; alpar@1: pool->count.lo = pool->count.hi = 0; alpar@1: return pool; alpar@1: } alpar@1: alpar@1: /*********************************************************************** alpar@1: * NAME alpar@1: * alpar@1: * dmp_get_atom - get free atom from dynamic memory pool alpar@1: * alpar@1: * SYNOPSIS alpar@1: * alpar@1: * #include "glpdmp.h" alpar@1: * void *dmp_get_atom(DMP *pool, int size); alpar@1: * alpar@1: * DESCRIPTION alpar@1: * alpar@1: * The routine dmp_get_atom obtains a free atom (memory block) from the alpar@1: * specified memory pool. alpar@1: * alpar@1: * The parameter size is the atom size, in bytes, 1 <= size <= 256. alpar@1: * alpar@1: * Note that the free atom contains arbitrary data, not binary zeros. alpar@1: * alpar@1: * RETURNS alpar@1: * alpar@1: * The routine returns a pointer to the free atom obtained. */ alpar@1: alpar@1: void *dmp_get_atom(DMP *pool, int size) alpar@1: { void *atom; alpar@1: int k; alpar@1: #ifdef GLP_DEBUG alpar@1: int orig_size = size; alpar@1: #endif alpar@1: if (!(1 <= size && size <= 256)) alpar@1: xerror("dmp_get_atom: size = %d; invalid atom size\n", size); alpar@1: #if 0 alpar@1: if (!(pool->size == 0 || pool->size == size)) alpar@1: xerror("dmp_get_atom: size = %d; wrong atom size\n", size); alpar@1: #endif alpar@1: /* adjust the size to provide the proper data alignment */ alpar@1: size = align_datasize(size); alpar@1: #ifdef GLP_DEBUG alpar@1: size += align_datasize(sizeof(struct info)); alpar@1: #endif alpar@1: /* adjust the size to make it multiple of 8 bytes, if needed */ alpar@1: size = ((size + 7) / 8) * 8; alpar@1: /* determine the corresponding list of free cells */ alpar@1: k = size / 8 - 1; alpar@1: xassert(0 <= k && k <= 31); alpar@1: /* obtain a free atom */ alpar@1: if (pool->avail[k] == NULL) alpar@1: { /* the list of free cells is empty */ alpar@1: if (pool->used + size > DMP_BLK_SIZE) alpar@1: { /* allocate a new memory block */ alpar@1: void *block = xmalloc(DMP_BLK_SIZE); alpar@1: *(void **)block = pool->block; alpar@1: pool->block = block; alpar@1: pool->used = align_datasize(sizeof(void *)); alpar@1: } alpar@1: /* place the atom in the current memory block */ alpar@1: atom = (char *)pool->block + pool->used; alpar@1: pool->used += size; alpar@1: } alpar@1: else alpar@1: { /* obtain the atom from the list of free cells */ alpar@1: atom = pool->avail[k]; alpar@1: pool->avail[k] = *(void **)atom; alpar@1: } alpar@1: memset(atom, '?', size); alpar@1: /* increase the number of atoms which are currently in use */ alpar@1: pool->count.lo++; alpar@1: if (pool->count.lo == 0) pool->count.hi++; alpar@1: #ifdef GLP_DEBUG alpar@1: ((struct info *)atom)->pool = pool; alpar@1: ((struct info *)atom)->size = orig_size; alpar@1: atom = (char *)atom + align_datasize(sizeof(struct info)); alpar@1: #endif alpar@1: return atom; alpar@1: } alpar@1: alpar@1: /*********************************************************************** alpar@1: * NAME alpar@1: * alpar@1: * dmp_free_atom - return atom to dynamic memory pool alpar@1: * alpar@1: * SYNOPSIS alpar@1: * alpar@1: * #include "glpdmp.h" alpar@1: * void dmp_free_atom(DMP *pool, void *atom, int size); alpar@1: * alpar@1: * DESCRIPTION alpar@1: * alpar@1: * The routine dmp_free_atom returns the specified atom (memory block) alpar@1: * to the specified memory pool, making it free. alpar@1: * alpar@1: * The parameter size is the atom size, in bytes, 1 <= size <= 256. alpar@1: * alpar@1: * Note that the atom can be returned only to the pool, from which it alpar@1: * was obtained, and its size must be exactly the same as on obtaining alpar@1: * it from the pool. */ alpar@1: alpar@1: void dmp_free_atom(DMP *pool, void *atom, int size) alpar@1: { int k; alpar@1: if (!(1 <= size && size <= 256)) alpar@1: xerror("dmp_free_atom: size = %d; invalid atom size\n", size); alpar@1: #if 0 alpar@1: if (!(pool->size == 0 || pool->size == size)) alpar@1: xerror("dmp_free_atom: size = %d; wrong atom size\n", size); alpar@1: #endif alpar@1: if (pool->count.lo == 0 && pool->count.hi == 0) alpar@1: xerror("dmp_free_atom: pool allocation error\n"); alpar@1: #ifdef GLP_DEBUG alpar@1: atom = (char *)atom - align_datasize(sizeof(struct info)); alpar@1: xassert(((struct info *)atom)->pool == pool); alpar@1: xassert(((struct info *)atom)->size == size); alpar@1: #endif alpar@1: /* adjust the size to provide the proper data alignment */ alpar@1: size = align_datasize(size); alpar@1: #ifdef GLP_DEBUG alpar@1: size += align_datasize(sizeof(struct info)); alpar@1: #endif alpar@1: /* adjust the size to make it multiple of 8 bytes, if needed */ alpar@1: size = ((size + 7) / 8) * 8; alpar@1: /* determine the corresponding list of free cells */ alpar@1: k = size / 8 - 1; alpar@1: xassert(0 <= k && k <= 31); alpar@1: /* return the atom to the list of free cells */ alpar@1: *(void **)atom = pool->avail[k]; alpar@1: pool->avail[k] = atom; alpar@1: /* decrease the number of atoms which are currently in use */ alpar@1: pool->count.lo--; alpar@1: if (pool->count.lo == 0xFFFFFFFF) pool->count.hi--; alpar@1: return; alpar@1: } alpar@1: alpar@1: /*********************************************************************** alpar@1: * NAME alpar@1: * alpar@1: * dmp_in_use - determine how many atoms are still in use alpar@1: * alpar@1: * SYNOPSIS alpar@1: * alpar@1: * #include "glpdmp.h" alpar@1: * glp_long dmp_in_use(DMP *pool); alpar@1: * alpar@1: * DESCRIPTION alpar@1: * alpar@1: * The routine dmp_in_use determines how many atoms allocated from the alpar@1: * specified memory pool with the routine dmp_get_atom are still in use, alpar@1: * i.e. not returned to the pool with the routine dmp_free_atom. alpar@1: * alpar@1: * RETURNS alpar@1: * alpar@1: * The routine returns the number of atoms which are still in use. */ alpar@1: alpar@1: glp_long dmp_in_use(DMP *pool) alpar@1: { return alpar@1: pool->count; alpar@1: } alpar@1: alpar@1: /*********************************************************************** alpar@1: * NAME alpar@1: * alpar@1: * dmp_delete_pool - delete dynamic memory pool alpar@1: * alpar@1: * SYNOPSIS alpar@1: * alpar@1: * #include "glpdmp.h" alpar@1: * void dmp_delete_pool(DMP *pool); alpar@1: * alpar@1: * DESCRIPTION alpar@1: * alpar@1: * The routine dmp_delete_pool deletes the specified dynamic memory alpar@1: * pool and frees all the memory allocated to this object. */ alpar@1: alpar@1: void dmp_delete_pool(DMP *pool) alpar@1: { while (pool->block != NULL) alpar@1: { void *block = pool->block; alpar@1: pool->block = *(void **)block; alpar@1: xfree(block); alpar@1: } alpar@1: xfree(pool); alpar@1: return; alpar@1: } alpar@1: alpar@1: /* eof */