src/glpdmp.c
author Alpar Juttner <alpar@cs.elte.hu>
Sun, 05 Dec 2010 17:35:23 +0100
changeset 2 4c8956a7bdf4
permissions -rw-r--r--
Set up CMAKE build environment
     1 /* glpdmp.c (dynamic memory pool) */
     2 
     3 /***********************************************************************
     4 *  This code is part of GLPK (GNU Linear Programming Kit).
     5 *
     6 *  Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
     7 *  2009, 2010 Andrew Makhorin, Department for Applied Informatics,
     8 *  Moscow Aviation Institute, Moscow, Russia. All rights reserved.
     9 *  E-mail: <mao@gnu.org>.
    10 *
    11 *  GLPK is free software: you can redistribute it and/or modify it
    12 *  under the terms of the GNU General Public License as published by
    13 *  the Free Software Foundation, either version 3 of the License, or
    14 *  (at your option) any later version.
    15 *
    16 *  GLPK is distributed in the hope that it will be useful, but WITHOUT
    17 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    18 *  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
    19 *  License for more details.
    20 *
    21 *  You should have received a copy of the GNU General Public License
    22 *  along with GLPK. If not, see <http://www.gnu.org/licenses/>.
    23 ***********************************************************************/
    24 
    25 #include "glpdmp.h"
    26 
    27 #if 1 /* 29/VIII-2008 */
    28 /* some processors need data to be properly aligned; the macro
    29    align_datasize enlarges the specified size of a data item to provide
    30    a proper alignment of immediately following data */
    31 
    32 #define align_datasize(size) ((((size) + 7) / 8) * 8)
    33 /* 8 bytes is sufficient in both 32- and 64-bit environments */
    34 #endif
    35 
    36 #ifdef GLP_DEBUG
    37 struct info
    38 {     DMP *pool;
    39       int size;
    40 };
    41 #endif
    42 
    43 /***********************************************************************
    44 *  NAME
    45 *
    46 *  dmp_create_pool - create dynamic memory pool
    47 *
    48 *  SYNOPSIS
    49 *
    50 *  #include "glpdmp.h"
    51 *  DMP *dmp_create_pool(void);
    52 *
    53 *  DESCRIPTION
    54 *
    55 *  The routine dmp_create_pool creates a dynamic memory pool.
    56 *
    57 *  RETURNS
    58 *
    59 *  The routine returns a pointer to the memory pool created. */
    60 
    61 DMP *dmp_create_pool(void)
    62 {     DMP *pool;
    63       int k;
    64 #ifdef GLP_DEBUG
    65       xprintf("dmp_create_pool: warning: debug mode enabled\n");
    66 #endif
    67       pool = xmalloc(sizeof(DMP));
    68 #if 0
    69       pool->size = 0;
    70 #endif
    71       for (k = 0; k <= 31; k++) pool->avail[k] = NULL;
    72       pool->block = NULL;
    73       pool->used = DMP_BLK_SIZE;
    74       pool->count.lo = pool->count.hi = 0;
    75       return pool;
    76 }
    77 
    78 /***********************************************************************
    79 *  NAME
    80 *
    81 *  dmp_get_atom - get free atom from dynamic memory pool
    82 *
    83 *  SYNOPSIS
    84 *
    85 *  #include "glpdmp.h"
    86 *  void *dmp_get_atom(DMP *pool, int size);
    87 *
    88 *  DESCRIPTION
    89 *
    90 *  The routine dmp_get_atom obtains a free atom (memory block) from the
    91 *  specified memory pool.
    92 *
    93 *  The parameter size is the atom size, in bytes, 1 <= size <= 256.
    94 *
    95 *  Note that the free atom contains arbitrary data, not binary zeros.
    96 *
    97 *  RETURNS
    98 *
    99 *  The routine returns a pointer to the free atom obtained. */
   100 
   101 void *dmp_get_atom(DMP *pool, int size)
   102 {     void *atom;
   103       int k;
   104 #ifdef GLP_DEBUG
   105       int orig_size = size;
   106 #endif
   107       if (!(1 <= size && size <= 256))
   108          xerror("dmp_get_atom: size = %d; invalid atom size\n", size);
   109 #if 0
   110       if (!(pool->size == 0 || pool->size == size))
   111          xerror("dmp_get_atom: size = %d; wrong atom size\n", size);
   112 #endif
   113       /* adjust the size to provide the proper data alignment */
   114       size = align_datasize(size);
   115 #ifdef GLP_DEBUG
   116       size += align_datasize(sizeof(struct info));
   117 #endif
   118       /* adjust the size to make it multiple of 8 bytes, if needed */
   119       size = ((size + 7) / 8) * 8;
   120       /* determine the corresponding list of free cells */
   121       k = size / 8 - 1;
   122       xassert(0 <= k && k <= 31);
   123       /* obtain a free atom */
   124       if (pool->avail[k] == NULL)
   125       {  /* the list of free cells is empty */
   126          if (pool->used + size > DMP_BLK_SIZE)
   127          {  /* allocate a new memory block */
   128             void *block = xmalloc(DMP_BLK_SIZE);
   129             *(void **)block = pool->block;
   130             pool->block = block;
   131             pool->used = align_datasize(sizeof(void *));
   132          }
   133          /* place the atom in the current memory block */
   134          atom = (char *)pool->block + pool->used;
   135          pool->used += size;
   136       }
   137       else
   138       {  /* obtain the atom from the list of free cells */
   139          atom = pool->avail[k];
   140          pool->avail[k] = *(void **)atom;
   141       }
   142       memset(atom, '?', size);
   143       /* increase the number of atoms which are currently in use */
   144       pool->count.lo++;
   145       if (pool->count.lo == 0) pool->count.hi++;
   146 #ifdef GLP_DEBUG
   147       ((struct info *)atom)->pool = pool;
   148       ((struct info *)atom)->size = orig_size;
   149       atom = (char *)atom + align_datasize(sizeof(struct info));
   150 #endif
   151       return atom;
   152 }
   153 
   154 /***********************************************************************
   155 *  NAME
   156 *
   157 *  dmp_free_atom - return atom to dynamic memory pool
   158 *
   159 *  SYNOPSIS
   160 *
   161 *  #include "glpdmp.h"
   162 *  void dmp_free_atom(DMP *pool, void *atom, int size);
   163 *
   164 *  DESCRIPTION
   165 *
   166 *  The routine dmp_free_atom returns the specified atom (memory block)
   167 *  to the specified memory pool, making it free.
   168 *
   169 *  The parameter size is the atom size, in bytes, 1 <= size <= 256.
   170 *
   171 *  Note that the atom can be returned only to the pool, from which it
   172 *  was obtained, and its size must be exactly the same as on obtaining
   173 *  it from the pool. */
   174 
   175 void dmp_free_atom(DMP *pool, void *atom, int size)
   176 {     int k;
   177       if (!(1 <= size && size <= 256))
   178          xerror("dmp_free_atom: size = %d; invalid atom size\n", size);
   179 #if 0
   180       if (!(pool->size == 0 || pool->size == size))
   181          xerror("dmp_free_atom: size = %d; wrong atom size\n", size);
   182 #endif
   183       if (pool->count.lo == 0 && pool->count.hi == 0)
   184          xerror("dmp_free_atom: pool allocation error\n");
   185 #ifdef GLP_DEBUG
   186       atom = (char *)atom - align_datasize(sizeof(struct info));
   187       xassert(((struct info *)atom)->pool == pool);
   188       xassert(((struct info *)atom)->size == size);
   189 #endif
   190       /* adjust the size to provide the proper data alignment */
   191       size = align_datasize(size);
   192 #ifdef GLP_DEBUG
   193       size += align_datasize(sizeof(struct info));
   194 #endif
   195       /* adjust the size to make it multiple of 8 bytes, if needed */
   196       size = ((size + 7) / 8) * 8;
   197       /* determine the corresponding list of free cells */
   198       k = size / 8 - 1;
   199       xassert(0 <= k && k <= 31);
   200       /* return the atom to the list of free cells */
   201       *(void **)atom = pool->avail[k];
   202       pool->avail[k] = atom;
   203       /* decrease the number of atoms which are currently in use */
   204       pool->count.lo--;
   205       if (pool->count.lo == 0xFFFFFFFF) pool->count.hi--;
   206       return;
   207 }
   208 
   209 /***********************************************************************
   210 *  NAME
   211 *
   212 *  dmp_in_use - determine how many atoms are still in use
   213 *
   214 *  SYNOPSIS
   215 *
   216 *  #include "glpdmp.h"
   217 *  glp_long dmp_in_use(DMP *pool);
   218 *
   219 *  DESCRIPTION
   220 *
   221 *  The routine dmp_in_use determines how many atoms allocated from the
   222 *  specified memory pool with the routine dmp_get_atom are still in use,
   223 *  i.e. not returned to the pool with the routine dmp_free_atom.
   224 *
   225 *  RETURNS
   226 *
   227 *  The routine returns the number of atoms which are still in use. */
   228 
   229 glp_long dmp_in_use(DMP *pool)
   230 {     return
   231          pool->count;
   232 }
   233 
   234 /***********************************************************************
   235 *  NAME
   236 *
   237 *  dmp_delete_pool - delete dynamic memory pool
   238 *
   239 *  SYNOPSIS
   240 *
   241 *  #include "glpdmp.h"
   242 *  void dmp_delete_pool(DMP *pool);
   243 *
   244 *  DESCRIPTION
   245 *
   246 *  The routine dmp_delete_pool deletes the specified dynamic memory
   247 *  pool and frees all the memory allocated to this object. */
   248 
   249 void dmp_delete_pool(DMP *pool)
   250 {     while (pool->block != NULL)
   251       {  void *block = pool->block;
   252          pool->block = *(void **)block;
   253          xfree(block);
   254       }
   255       xfree(pool);
   256       return;
   257 }
   258 
   259 /* eof */