00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <string.h>
00029
00030 #include "mmprivate.h"
00031
00032
00033
00034 static int initialize PARAMS ((struct mdesc *));
00035 static PTR morecore PARAMS ((struct mdesc *, size_t));
00036 static PTR align PARAMS ((struct mdesc *, size_t));
00037
00038
00039
00040 static PTR
00041 align (mdp, size)
00042 struct mdesc *mdp;
00043 size_t size;
00044 {
00045 PTR result;
00046 unsigned long int adj;
00047
00048 result = mdp -> morecore (mdp, size);
00049 adj = RESIDUAL (result, BLOCKSIZE);
00050 if (adj != 0)
00051 {
00052 adj = BLOCKSIZE - adj;
00053 mdp -> morecore (mdp, adj);
00054 result = (char *) result + adj;
00055 }
00056 return (result);
00057 }
00058
00059
00060
00061 static int
00062 initialize (mdp)
00063 struct mdesc *mdp;
00064 {
00065 mdp -> heapsize = HEAP / BLOCKSIZE;
00066 mdp -> heapinfo = (mmalloc_info *)
00067 align (mdp, mdp -> heapsize * sizeof (mmalloc_info));
00068 if (mdp -> heapinfo == NULL)
00069 {
00070 return (0);
00071 }
00072 memset ((PTR)mdp -> heapinfo, 0, mdp -> heapsize * sizeof (mmalloc_info));
00073 mdp -> heapinfo[0].free.size = 0;
00074 mdp -> heapinfo[0].free.next = mdp -> heapinfo[0].free.prev = 0;
00075 mdp -> heapindex = 0;
00076 mdp -> heapbase = (char *) mdp -> heapinfo;
00077 mdp -> flags |= MMALLOC_INITIALIZED;
00078 return (1);
00079 }
00080
00081
00082
00083
00084 static PTR
00085 morecore (mdp, size)
00086 struct mdesc *mdp;
00087 size_t size;
00088 {
00089 PTR result;
00090 mmalloc_info *newinfo, *oldinfo;
00091 size_t newsize;
00092
00093 result = align (mdp, size);
00094 if (result == NULL)
00095 {
00096 return (NULL);
00097 }
00098
00099
00100 if ((size_t) BLOCK ((char *) result + size) > mdp -> heapsize)
00101 {
00102 newsize = mdp -> heapsize;
00103 while ((size_t) BLOCK ((char *) result + size) > newsize)
00104 {
00105 newsize *= 2;
00106 }
00107 newinfo = (mmalloc_info *) align (mdp, newsize * sizeof (mmalloc_info));
00108 if (newinfo == NULL)
00109 {
00110 mdp -> morecore (mdp, -(ptrdiff_t)size);
00111 return (NULL);
00112 }
00113 memset ((PTR) newinfo, 0, newsize * sizeof (mmalloc_info));
00114 memcpy ((PTR) newinfo, (PTR) mdp -> heapinfo,
00115 mdp -> heapsize * sizeof (mmalloc_info));
00116 oldinfo = mdp -> heapinfo;
00117 newinfo[BLOCK (oldinfo)].busy.type = 0;
00118 newinfo[BLOCK (oldinfo)].busy.info.size
00119 = BLOCKIFY (mdp -> heapsize * sizeof (mmalloc_info));
00120 mdp -> heapinfo = newinfo;
00121 __mmalloc_free (mdp, (PTR)oldinfo);
00122 mdp -> heapsize = newsize;
00123 }
00124
00125 mdp -> heaplimit = BLOCK ((char *) result + size);
00126 return (result);
00127 }
00128
00129
00130
00131 PTR
00132 mmalloc (md, size)
00133 PTR md;
00134 size_t size;
00135 {
00136 struct mdesc *mdp;
00137 PTR result;
00138 size_t block, blocks, lastblocks, start;
00139 register size_t i;
00140 struct mmlist *next;
00141 register size_t log;
00142
00143 if (size == 0)
00144 {
00145 return (NULL);
00146 }
00147
00148 mdp = MD_TO_MDP (md);
00149
00150 if (mdp -> mmalloc_hook != NULL)
00151 {
00152 return ((*mdp -> mmalloc_hook) (md, size));
00153 }
00154
00155 if (!(mdp -> flags & MMALLOC_INITIALIZED))
00156 {
00157 if (!initialize (mdp))
00158 {
00159 return (NULL);
00160 }
00161 }
00162
00163 if (size < sizeof (struct mmlist))
00164 {
00165 size = sizeof (struct mmlist);
00166 }
00167
00168
00169 if (size <= BLOCKSIZE / 2)
00170 {
00171
00172
00173 log = 1;
00174 --size;
00175 while ((size /= 2) != 0)
00176 {
00177 ++log;
00178 }
00179
00180
00181
00182 next = mdp -> fraghead[log].next;
00183 if (next != NULL)
00184 {
00185
00186
00187
00188 result = (PTR) next;
00189 next -> prev -> next = next -> next;
00190 if (next -> next != NULL)
00191 {
00192 next -> next -> prev = next -> prev;
00193 }
00194 block = BLOCK (result);
00195 if (--mdp -> heapinfo[block].busy.info.frag.nfree != 0)
00196 {
00197 mdp -> heapinfo[block].busy.info.frag.first =
00198 RESIDUAL (next -> next, BLOCKSIZE) >> log;
00199 }
00200
00201
00202 mdp -> heapstats.chunks_used++;
00203 mdp -> heapstats.bytes_used += 1 << log;
00204 mdp -> heapstats.chunks_free--;
00205 mdp -> heapstats.bytes_free -= 1 << log;
00206 }
00207 else
00208 {
00209
00210
00211 result = mmalloc (md, BLOCKSIZE);
00212 if (result == NULL)
00213 {
00214 return (NULL);
00215 }
00216
00217
00218 for (i = 1; i < (size_t) (BLOCKSIZE >> log); ++i)
00219 {
00220 next = (struct mmlist *) ((char *) result + (i << log));
00221 next -> next = mdp -> fraghead[log].next;
00222 next -> prev = &mdp -> fraghead[log];
00223 next -> prev -> next = next;
00224 if (next -> next != NULL)
00225 {
00226 next -> next -> prev = next;
00227 }
00228 }
00229
00230
00231 block = BLOCK (result);
00232 mdp -> heapinfo[block].busy.type = log;
00233 mdp -> heapinfo[block].busy.info.frag.nfree = i - 1;
00234 mdp -> heapinfo[block].busy.info.frag.first = i - 1;
00235
00236 mdp -> heapstats.chunks_free += (BLOCKSIZE >> log) - 1;
00237 mdp -> heapstats.bytes_free += BLOCKSIZE - (1 << log);
00238 mdp -> heapstats.bytes_used -= BLOCKSIZE - (1 << log);
00239 }
00240 }
00241 else
00242 {
00243
00244
00245
00246
00247 blocks = BLOCKIFY(size);
00248 start = block = MALLOC_SEARCH_START;
00249 while (mdp -> heapinfo[block].free.size < blocks)
00250 {
00251 block = mdp -> heapinfo[block].free.next;
00252 if (block == start)
00253 {
00254
00255
00256
00257 block = mdp -> heapinfo[0].free.prev;
00258 lastblocks = mdp -> heapinfo[block].free.size;
00259 if (mdp -> heaplimit != 0 &&
00260 block + lastblocks == mdp -> heaplimit &&
00261 mdp -> morecore (mdp, 0) == ADDRESS(block + lastblocks) &&
00262 (morecore (mdp, (blocks - lastblocks) * BLOCKSIZE)) != NULL)
00263 {
00264
00265
00266
00267 block = mdp -> heapinfo[0].free.prev;
00268
00269 mdp -> heapinfo[block].free.size += (blocks - lastblocks);
00270 mdp -> heapstats.bytes_free +=
00271 (blocks - lastblocks) * BLOCKSIZE;
00272 continue;
00273 }
00274 result = morecore(mdp, blocks * BLOCKSIZE);
00275 if (result == NULL)
00276 {
00277 return (NULL);
00278 }
00279 block = BLOCK (result);
00280 mdp -> heapinfo[block].busy.type = 0;
00281 mdp -> heapinfo[block].busy.info.size = blocks;
00282 mdp -> heapstats.chunks_used++;
00283 mdp -> heapstats.bytes_used += blocks * BLOCKSIZE;
00284 return (result);
00285 }
00286 }
00287
00288
00289
00290 result = ADDRESS(block);
00291 if (mdp -> heapinfo[block].free.size > blocks)
00292 {
00293
00294
00295 mdp -> heapinfo[block + blocks].free.size
00296 = mdp -> heapinfo[block].free.size - blocks;
00297 mdp -> heapinfo[block + blocks].free.next
00298 = mdp -> heapinfo[block].free.next;
00299 mdp -> heapinfo[block + blocks].free.prev
00300 = mdp -> heapinfo[block].free.prev;
00301 mdp -> heapinfo[mdp -> heapinfo[block].free.prev].free.next
00302 = mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev
00303 = mdp -> heapindex = block + blocks;
00304 }
00305 else
00306 {
00307
00308
00309 mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev
00310 = mdp -> heapinfo[block].free.prev;
00311 mdp -> heapinfo[mdp -> heapinfo[block].free.prev].free.next
00312 = mdp -> heapindex = mdp -> heapinfo[block].free.next;
00313 mdp -> heapstats.chunks_free--;
00314 }
00315
00316 mdp -> heapinfo[block].busy.type = 0;
00317 mdp -> heapinfo[block].busy.info.size = blocks;
00318 mdp -> heapstats.chunks_used++;
00319 mdp -> heapstats.bytes_used += blocks * BLOCKSIZE;
00320 mdp -> heapstats.bytes_free -= blocks * BLOCKSIZE;
00321 }
00322
00323 return (result);
00324 }
00325
00326
00327
00328
00329
00330
00331
00332 #ifndef NO_SBRK_MALLOC
00333
00334 PTR
00335 malloc (size)
00336 size_t size;
00337 {
00338 return (mmalloc ((PTR) NULL, size));
00339 }
00340
00341 #endif