00001
00002
00003
00004 #include "memint.h"
00005
00006
00007 #if STDC_HEADERS
00008 # include <stdlib.h>
00009 #else
00010 # if defined(__STDC__)
00011 extern void exit(int);
00012 # else
00013 extern void exit();
00014 # endif
00015 #endif
00016
00017
00018
00019
00020 static SIZE_T block_allocation;
00021
00022
00023
00024
00025 void
00026 #if defined(__STDC__)
00027 mem_copy(pointer dest, pointer src, SIZE_T size)
00028 #else
00029 mem_copy(dest, src, size)
00030 pointer dest;
00031 pointer src;
00032 SIZE_T size;
00033 #endif
00034 {
00035 MEM_COPY(dest, src, size);
00036 }
00037
00038
00039
00040
00041 void
00042 #if defined(__STDC__)
00043 mem_zero(pointer ptr, SIZE_T size)
00044 #else
00045 mem_zero(ptr, size)
00046 pointer ptr;
00047 SIZE_T size;
00048 #endif
00049 {
00050 MEM_ZERO(ptr, size);
00051 }
00052
00053
00054
00055
00056 void
00057 #if defined(__STDC__)
00058 mem_fatal(char *message)
00059 #else
00060 mem_fatal(message)
00061 char *message;
00062 #endif
00063 {
00064 fprintf(stderr, "Memory management library: error: %s\n", message);
00065 exit(1);
00066 }
00067
00068
00069 SIZE_T
00070 #if defined(__STDC__)
00071 mem_allocation(void)
00072 #else
00073 mem_allocation()
00074 #endif
00075 {
00076
00077
00078 return (block_allocation);
00079 }
00080
00081
00082
00083
00084 #if !defined(USE_MALLOC_FREE)
00085
00086
00087 static block avail[MAX_SIZE_INDEX+1];
00088
00089
00090
00091
00092 static struct segment_ dummy_seg={(pointer)0, (SIZE_T)0};
00093
00094
00095
00096
00097 static segment curr_seg= &dummy_seg;
00098
00099
00100 static
00101 int
00102 #if defined(__STDC__)
00103 ceiling_log_2(SIZE_T i)
00104 #else
00105 ceiling_log_2(i)
00106 SIZE_T i;
00107 #endif
00108 {
00109 SIZE_T j;
00110 int result;
00111
00112 for (result=0, j=1; j < i; ++result, j*=2);
00113 return (result);
00114 }
00115
00116
00117
00118
00119 static
00120 int
00121 #if defined(__STDC__)
00122 block_size_index(SIZE_T size)
00123 #else
00124 block_size_index(size)
00125 SIZE_T size;
00126 #endif
00127 {
00128 if (size < 1)
00129 return (-1);
00130 if (size > MAX_SIZE)
00131 mem_fatal("block_size_index: block size too large");
00132 else
00133 size+=HEADER_SIZE;
00134 return (ceiling_log_2(size));
00135 }
00136
00137
00138
00139
00140 static
00141 void
00142 #if defined(__STDC__)
00143 add_to_free_list(block b)
00144 #else
00145 add_to_free_list(b)
00146 block b;
00147 #endif
00148 {
00149 int i;
00150
00151 i=b->size_index;
00152 if (!avail[i])
00153 {
00154 b->next=b;
00155 b->prev=b;
00156 avail[i]=b;
00157 }
00158 else
00159 {
00160 b->next=avail[i]->next;
00161 avail[i]->next->prev=b;
00162 avail[i]->next=b;
00163 b->prev=avail[i];
00164 }
00165 b->used=0;
00166 }
00167
00168
00169
00170
00171
00172 static
00173 block
00174 #if defined(__STDC__)
00175 remove_from_free_list(block b)
00176 #else
00177 remove_from_free_list(b)
00178 block b;
00179 #endif
00180 {
00181 int i;
00182
00183 i=b->size_index;
00184 if (b->next == b)
00185 avail[i]=0;
00186 else
00187 {
00188 b->next->prev=b->prev;
00189 b->prev->next=b->next;
00190 if (avail[i] == b)
00191 avail[i]=b->next;
00192 }
00193 b->used=1;
00194 return (b);
00195 }
00196
00197
00198
00199
00200
00201 static
00202 block
00203 #if defined(__STDC__)
00204 buddy(block b)
00205 #else
00206 buddy(b)
00207 block b;
00208 #endif
00209 {
00210 SIZE_T buddy_offset;
00211
00212 buddy_offset=(SIZE_T)(((INT_PTR)b-(INT_PTR)b->seg->base_address) ^ ((SIZE_T)1 << b->size_index));
00213 if (buddy_offset < b->seg->limit)
00214 return ((block)((INT_PTR)b->seg->base_address+buddy_offset));
00215 else
00216 return ((block)0);
00217 }
00218
00219
00220
00221
00222
00223
00224 static
00225 void
00226 #if defined(__STDC__)
00227 trim_to_size(block b, int size_index)
00228 #else
00229 trim_to_size(b, size_index)
00230 block b;
00231 int size_index;
00232 #endif
00233 {
00234 block bb;
00235
00236 while (b->size_index > size_index)
00237 {
00238 b->size_index--;
00239 bb=buddy(b);
00240 bb->size_index=b->size_index;
00241 bb->seg=b->seg;
00242 add_to_free_list(bb);
00243 }
00244 }
00245
00246
00247
00248
00249
00250
00251 static
00252 void
00253 #if defined(__STDC__)
00254 merge_and_free(block b)
00255 #else
00256 merge_and_free(b)
00257 block b;
00258 #endif
00259 {
00260 block bb;
00261
00262 for (bb=buddy(b); bb && !bb->used && bb->size_index == b->size_index; bb=buddy(b))
00263 {
00264 remove_from_free_list(bb);
00265 if ((INT_PTR)bb < (INT_PTR)b)
00266 b=bb;
00267 b->size_index++;
00268 }
00269 add_to_free_list(b);
00270 }
00271
00272
00273
00274
00275 pointer
00276 #if defined(__STDC__)
00277 mem_get_block(SIZE_T size)
00278 #else
00279 mem_get_block(size)
00280 SIZE_T size;
00281 #endif
00282 {
00283 int i;
00284 int size_index;
00285 int alloc_size_index;
00286 int new_seg;
00287 SIZE_T alloc_size;
00288 pointer sbrk_ret;
00289 block b;
00290
00291 if ((size_index=block_size_index(size)) < 0)
00292 return ((pointer)0);
00293
00294 for (i=size_index; i <= MAX_SIZE_INDEX && !avail[i]; ++i);
00295 if (i > MAX_SIZE_INDEX)
00296 {
00297
00298
00299 if (size_index < MIN_ALLOC_SIZE_INDEX)
00300 alloc_size_index=MIN_ALLOC_SIZE_INDEX;
00301 else
00302 alloc_size_index=size_index;
00303 alloc_size=((SIZE_T)1 << alloc_size_index);
00304
00305
00306 alloc_size+=((curr_seg->limit+alloc_size-1) & ~(alloc_size-1))-curr_seg->limit;
00307 if ((sbrk_ret=(pointer)SBRK(0)) != (pointer)((INT_PTR)curr_seg->base_address+curr_seg->limit) ||
00308 alloc_size+curr_seg->limit > MAX_SEG_SIZE)
00309 {
00310
00311
00312 alloc_size=ROUNDUP((INT_PTR)sbrk_ret)-(INT_PTR)sbrk_ret;
00313
00314
00315
00316 alloc_size+=((SIZE_T)1 << alloc_size_index)+ROUNDUP(sizeof(struct segment_));
00317 new_seg=1;
00318 }
00319 else
00320 new_seg=0;
00321 sbrk_ret=(pointer)SBRK(alloc_size);
00322 if (sbrk_ret == (pointer)-1)
00323 mem_fatal("mem_get_block: allocation failed");
00324 block_allocation+=alloc_size;
00325 if (new_seg)
00326 {
00327 curr_seg=(segment)ROUNDUP((INT_PTR)sbrk_ret);
00328 curr_seg->base_address=(pointer)((INT_PTR)curr_seg+ROUNDUP(sizeof(struct segment_)));
00329 curr_seg->limit=0;
00330
00331 alloc_size=(1l << alloc_size_index);
00332 }
00333
00334 while (alloc_size)
00335 {
00336 size=alloc_size-(alloc_size & (alloc_size-1));
00337 b=(block)((INT_PTR)curr_seg->base_address+curr_seg->limit);
00338 b->size_index=ceiling_log_2(size);
00339 b->seg=curr_seg;
00340 add_to_free_list(b);
00341 curr_seg->limit+=size;
00342 alloc_size-=size;
00343 }
00344
00345 for (i=size_index; i <= MAX_SIZE_INDEX && !avail[i]; ++i);
00346 }
00347 b=remove_from_free_list(avail[i]);
00348 trim_to_size(b, size_index);
00349 return ((pointer)((INT_PTR)b+HEADER_SIZE));
00350 }
00351
00352
00353
00354
00355 void
00356 #if defined(__STDC__)
00357 mem_free_block(pointer p)
00358 #else
00359 mem_free_block(p)
00360 pointer p;
00361 #endif
00362 {
00363 block b;
00364
00365 if (!p)
00366 return;
00367 b=(block)((INT_PTR)p-HEADER_SIZE);
00368 if (!b->used)
00369 mem_fatal("mem_free_block: block not in use");
00370 if (b->size_index < 0 || b->size_index > MAX_SIZE_INDEX)
00371 mem_fatal("mem_free_block: invalid block header");
00372 merge_and_free(b);
00373 }
00374
00375
00376
00377
00378
00379
00380 pointer
00381 #if defined(__STDC__)
00382 mem_resize_block(pointer p, SIZE_T new_size)
00383 #else
00384 mem_resize_block(p, new_size)
00385 pointer p;
00386 SIZE_T new_size;
00387 #endif
00388 {
00389 int new_size_index;
00390 block b;
00391 block bb;
00392 pointer q;
00393 SIZE_T old_size;
00394
00395 if (!p)
00396 return (mem_get_block(new_size));
00397 b=(block)((INT_PTR)p-HEADER_SIZE);
00398 if (!b->used)
00399 mem_fatal("mem_resize_block: block not in use");
00400 if (b->size_index < 0 || b->size_index > MAX_SIZE_INDEX)
00401 mem_fatal("mem_resize_block: invalid block header");
00402 if ((new_size_index=block_size_index(new_size)) < 0)
00403 {
00404 mem_free_block(p);
00405 return ((pointer)0);
00406 }
00407 if (b->size_index >= new_size_index)
00408 {
00409
00410 trim_to_size(b, new_size_index);
00411 return (p);
00412 }
00413 old_size=(1l << b->size_index)-HEADER_SIZE;
00414
00415 for (bb=buddy(b);
00416 bb && (INT_PTR)b < (INT_PTR)bb && !bb->used && bb->size_index == b->size_index;
00417 bb=buddy(b))
00418 {
00419 remove_from_free_list(bb);
00420 if (++(b->size_index) == new_size_index)
00421 return (p);
00422 }
00423
00424
00425 q=mem_get_block(new_size);
00426 mem_copy(q, p, old_size);
00427 merge_and_free(b);
00428 return (q);
00429 }
00430 #endif
00431
00432
00433
00434
00435 #if defined(USE_MALLOC_FREE)
00436 pointer
00437 #if defined(__STDC__)
00438 mem_get_block(SIZE_T size)
00439 #else
00440 mem_get_block(size)
00441 SIZE_T size;
00442 #endif
00443 {
00444 pointer result;
00445
00446 if (size <= 0)
00447 return ((pointer)0);
00448 result=MALLOC(size);
00449 if (!result)
00450 mem_fatal("mem_get_block: allocation failed");
00451 return (result);
00452 }
00453
00454
00455 void
00456 #if defined(__STDC__)
00457 mem_free_block(pointer p)
00458 #else
00459 mem_free_block(p)
00460 pointer p;
00461 #endif
00462 {
00463 if (!p)
00464 return;
00465 FREE(p);
00466 }
00467
00468
00469 pointer
00470 #if defined(__STDC__)
00471 mem_resize_block(pointer p, SIZE_T new_size)
00472 #else
00473 mem_resize_block(p, new_size)
00474 pointer p;
00475 SIZE_T new_size;
00476 #endif
00477 {
00478 if (!p)
00479 return (mem_get_block(new_size));
00480 if (new_size <= 0)
00481 {
00482 mem_free_block(p);
00483 return ((pointer)0);
00484 }
00485 return (REALLOC(p, new_size));
00486 }
00487 #endif