aboutsummaryrefslogtreecommitdiffstats
path: root/test/monniaux/glpk-4.65/src/misc/dmp.c
blob: a4882c86193d9e42c6c026f6c5d4a8e8e8388dae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
/* dmp.c (dynamic memory pool) */

/***********************************************************************
*  This code is part of GLPK (GNU Linear Programming Kit).
*
*  Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied
*  Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
*  reserved. E-mail: <mao@gnu.org>.
*
*  GLPK is free software: you can redistribute it and/or modify it
*  under the terms of the GNU General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  GLPK is distributed in the hope that it will be useful, but WITHOUT
*  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
*  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
*  License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with GLPK. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/

#include "env.h"
#include "dmp.h"

struct DMP
{     /* dynamic memory pool */
      void *avail[32];
      /* avail[k], 0 <= k <= 31, is a pointer to first available (free)
       * atom of (k+1)*8 bytes long; at the beginning of each free atom
       * there is a pointer to another free atom of the same size */
      void *block;
      /* pointer to most recently allocated memory block; at the
       * beginning of each allocated memory block there is a pointer to
       * previously allocated memory block */
      int used;
      /* number of bytes used in most recently allocated memory block */
      size_t count;
      /* number of atoms which are currently in use */
};

#define DMP_BLK_SIZE 8000
/* size of memory blocks, in bytes, allocated for memory pools */

struct prefix
{     /* atom prefix (for debugging only) */
      DMP *pool;
      /* dynamic memory pool */
      int size;
      /* original atom size, in bytes */
};

#define prefix_size ((sizeof(struct prefix) + 7) & ~7)
/* size of atom prefix rounded up to multiple of 8 bytes */

int dmp_debug;
/* debug mode flag */

/***********************************************************************
*  NAME
*
*  dmp_create_pool - create dynamic memory pool
*
*  SYNOPSIS
*
*  #include "dmp.h"
*  DMP *dmp_create_pool(void);
*
*  DESCRIPTION
*
*  The routine dmp_create_pool creates a dynamic memory pool.
*
*  RETURNS
*
*  The routine returns a pointer to the memory pool created. */

DMP *dmp_create_pool(void)
{     DMP *pool;
      int k;
      xassert(sizeof(void *) <= 8);
      if (dmp_debug)
         xprintf("dmp_create_pool: warning: debug mode is on\n");
      pool = talloc(1, DMP);
      for (k = 0; k <= 31; k++)
         pool->avail[k] = NULL;
      pool->block = NULL;
      pool->used = DMP_BLK_SIZE;
      pool->count = 0;
      return pool;
}

/***********************************************************************
*  NAME
*
*  dmp_get_atom - get free atom from dynamic memory pool
*
*  SYNOPSIS
*
*  #include "dmp.h"
*  void *dmp_get_atom(DMP *pool, int size);
*
*  DESCRIPTION
*
*  The routine dmp_get_atom obtains a free atom (memory space) from the
*  specified memory pool.
*
*  The parameter size is the atom size, in bytes, 1 <= size <= 256.
*
*  Note that the free atom contains arbitrary data, not binary zeros.
*
*  RETURNS
*
*  The routine returns a pointer to the free atom obtained. */

void *dmp_get_atom(DMP *pool, int size)
{     void *atom;
      int k, need;
      xassert(1 <= size && size <= 256);
      /* round up atom size to multiple of 8 bytes */
      need = (size + 7) & ~7;
      /* determine number of corresponding list of free atoms */
      k = (need >> 3) - 1;
      /* obtain free atom */
      if (pool->avail[k] == NULL)
      {  /* corresponding list of free atoms is empty */
         /* if debug mode is on, add atom prefix size */
         if (dmp_debug)
            need += prefix_size;
         if (pool->used + need > DMP_BLK_SIZE)
         {  /* allocate new memory block */
            void *block = talloc(DMP_BLK_SIZE, char);
            *(void **)block = pool->block;
            pool->block = block;
            pool->used = 8; /* sufficient to store pointer */
         }
         /* allocate new atom in current memory block */
         atom = (char *)pool->block + pool->used;
         pool->used += need;
      }
      else
      {  /* obtain atom from corresponding list of free atoms */
         atom  = pool->avail[k];
         pool->avail[k] = *(void **)atom;
      }
      /* if debug mode is on, fill atom prefix */
      if (dmp_debug)
      {  ((struct prefix *)atom)->pool = pool;
         ((struct prefix *)atom)->size = size;
         atom = (char *)atom + prefix_size;
      }
      /* increase number of allocated atoms */
      pool->count++;
      return atom;
}

/***********************************************************************
*  NAME
*
*  dmp_free_atom - return atom to dynamic memory pool
*
*  SYNOPSIS
*
*  #include "dmp.h"
*  void dmp_free_atom(DMP *pool, void *atom, int size);
*
*  DESCRIPTION
*
*  The routine dmp_free_atom returns the specified atom (memory space)
*  to the specified memory pool, making the atom free.
*
*  The parameter size is the atom size, in bytes, 1 <= size <= 256.
*
*  Note that the atom can be returned only to the pool, from which it
*  was obtained, and its size must be exactly the same as on obtaining
*  it from the pool. */

void dmp_free_atom(DMP *pool, void *atom, int size)
{     int k;
      xassert(1 <= size && size <= 256);
      /* determine number of corresponding list of free atoms */
      k = ((size + 7) >> 3) - 1;
      /* if debug mode is on, check atom prefix */
      if (dmp_debug)
      {  atom = (char *)atom - prefix_size;
         xassert(((struct prefix *)atom)->pool == pool);
         xassert(((struct prefix *)atom)->size == size);
      }
      /* return atom to corresponding list of free atoms */
      *(void **)atom = pool->avail[k];
      pool->avail[k] = atom;
      /* decrease number of allocated atoms */
      xassert(pool->count > 0);
      pool->count--;
      return;
}

/***********************************************************************
*  NAME
*
*  dmp_in_use - determine how many atoms are still in use
*
*  SYNOPSIS
*
*  #include "dmp.h"
*  size_t dmp_in_use(DMP *pool);
*
*  RETURNS
*
*  The routine returns the number of atoms of the specified memory pool
*  which are still in use. */

size_t dmp_in_use(DMP *pool)
{     return
         pool->count;
}

/***********************************************************************
*  NAME
*
*  dmp_delete_pool - delete dynamic memory pool
*
*  SYNOPSIS
*
*  #include "dmp.h"
*  void dmp_delete_pool(DMP *pool);
*
*  DESCRIPTION
*
*  The routine dmp_delete_pool deletes the specified dynamic memory
*  pool freeing all the memory allocated to this object. */

void dmp_delete_pool(DMP *pool)
{     while (pool->block != NULL)
      {  void *block = pool->block;
         pool->block = *(void **)block;
         tfree(block);
      }
      tfree(pool);
      return;
}

/* eof */